Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ abstract class EmptyStateFragment<T : ViewBinding> : FragmentWithBinding<T> {

open fun onFragmentLongPressed() {
val currentEditor = currentEditor ?: return
currentEditor.selectCurrentWord()
currentEditor.selectWordOrOperatorAtCursor()
}

private val gestureListener =
Expand Down
18 changes: 18 additions & 0 deletions editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import com.itsaky.androidide.editor.language.treesitter.TreeSitterLanguage
import com.itsaky.androidide.editor.language.treesitter.TreeSitterLanguageProvider
import com.itsaky.androidide.editor.processing.ProcessContext
import com.itsaky.androidide.editor.processing.TextProcessorEngine
import com.itsaky.androidide.editor.utils.getOperatorRangeAt
import com.itsaky.androidide.editor.schemes.IDEColorScheme
import com.itsaky.androidide.editor.schemes.IDEColorSchemeProvider
import com.itsaky.androidide.editor.snippets.AbstractSnippetVariableResolver
Expand Down Expand Up @@ -1215,4 +1216,21 @@ constructor(
log.error("Error setting selection from point", e)
}
}

/**
* Selects the word at the cursor, or if none (e.g. on an operator), selects
* the operator at the cursor so the code-action toolbar can be shown.
*/
fun selectWordOrOperatorAtCursor() {
if (isReleased) return
selectCurrentWord()
if (cursor.isSelected) return
val line = cursor.leftLine
val column = cursor.leftColumn
val columnCount = text.getColumnCount(line)
if (column < 0 || column >= columnCount) return
val range = text.getOperatorRangeAt(line, column) ?: return
val (startCol, endCol) = range
setSelectionRegion(line, startCol, line, endCol)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/

package com.itsaky.androidide.editor.utils

import io.github.rosemoe.sora.text.Content

/**
* Java/Kotlin operators for long-press selection, ordered by length descending
* so longer matches are tried first (e.g. `>>>` before `>>` before `>`).
*/
private val OPERATORS: List<String> =
listOf(
// 3-char
">>>",
"<<=",
">>=",
">>>=",
// 2-char
"==",
"!=",
"<=",
">=",
"+=",
"-=",
"*=",
"/=",
"%=",
"&=",
"|=",
"^=",
"++",
"--",
"&&",
"||",
"<<",
">>",
"->",
"?.",
"?:",
"..",
"!!",
"::",
// 1-char
"+",
"-",
"*",
"/",
"%",
"=",
"<",
">",
"!",
"&",
"|",
"^",
"~",
"?",
":",
";",
",",
".",
"@",
"(",
")",
"[",
"]",
"{",
"}",
)

/**
* Returns the column range of the operator at the given position, if any.
* Columns are 0-based; endColumn is exclusive (one past the last character).
*
* @param lineContent The full line text.
* @param column Cursor column (0-based).
* @return (startColumn, endColumnExclusive) or null if no operator at this position.
*/
fun getOperatorRangeAt(lineContent: CharSequence, column: Int): Pair<Int, Int>? {
if (column < 0 || column >= lineContent.length) return null
val suffix = lineContent.subSequence(column, lineContent.length)
for (op in OPERATORS) {
if (op.length <= suffix.length && suffix.subSequence(0, op.length) == op) {
return column to (column + op.length)
}
}
return null
}

/**
* Returns the column range of the operator at (line, column) in [content], if any.
* Columns are 0-based; endColumn is exclusive.
*/
fun Content.getOperatorRangeAt(line: Int, column: Int): Pair<Int, Int>? {
if (line < 0 || line >= lineCount) return null
val lineContent = getLine(line)
val maxColumn = lineContent.length
if (column < 0 || column > maxColumn) return null
val range = getOperatorRangeAt(lineContent, column) ?: return null
val (start, end) = range
if (end > maxColumn) return null
return range
}
Loading