mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-19 00:35:26 +02:00
feat(core): Add smart delete functionality
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
This commit is contained in:
parent
ce2ce6ff74
commit
04dabe60af
@ -78,6 +78,10 @@ object Token {
|
||||
power, factorial, modulo, percent, sqrt,
|
||||
)
|
||||
}
|
||||
|
||||
val allWithoutBrackets by lazy {
|
||||
all.filter { it !in listOf(leftBracket, rightBracket) }
|
||||
}
|
||||
}
|
||||
|
||||
object Func {
|
||||
|
@ -0,0 +1,88 @@
|
||||
package app.myzel394.numberhub.core.ui.common.textfield
|
||||
|
||||
import androidx.compose.ui.text.TextRange
|
||||
import app.myzel394.numberhub.core.base.Token
|
||||
|
||||
// Smartly delete tokens
|
||||
data class SmartDeleteHandler(
|
||||
private val value: String,
|
||||
private val selection: TextRange,
|
||||
) {
|
||||
fun calculateDeleteRange(): TextRange {
|
||||
if (isSelectionARange()) {
|
||||
return selection
|
||||
}
|
||||
|
||||
val position = selection.start
|
||||
|
||||
val rightBracketPosition =
|
||||
findRightBracket(position);
|
||||
val leftBracketPosition =
|
||||
findLeftBracket(position)
|
||||
?: return TextRange(
|
||||
rightBracketPosition?.let { takeNextIfIsOperator(it) }
|
||||
?.let { if (it > position) 0 else it } ?: 0,
|
||||
position,
|
||||
);
|
||||
|
||||
if (rightBracketPosition == null) {
|
||||
val rightBracketRelativeToLeftPosition = findRightBracket(leftBracketPosition + 1)
|
||||
|
||||
return if (rightBracketRelativeToLeftPosition == null) {
|
||||
// 1+2(+5|+6
|
||||
TextRange(leftBracketPosition + 1, position)
|
||||
} else {
|
||||
// 1+2(6)+5|+6
|
||||
TextRange(takeNextIfIsOperator(rightBracketRelativeToLeftPosition + 1), position)
|
||||
}
|
||||
}
|
||||
|
||||
return TextRange(leftBracketPosition + 1, findClosingParen(leftBracketPosition));
|
||||
}
|
||||
|
||||
private fun takeNextIfIsOperator(position: Int): Int {
|
||||
if (position + 1 < value.length && Token.Operator.allWithoutBrackets.contains(value[position].toString())) {
|
||||
return position + 1
|
||||
}
|
||||
|
||||
return position
|
||||
}
|
||||
|
||||
private fun isSelectionARange(): Boolean = selection.start != selection.end
|
||||
|
||||
private fun findLeftBracket(startPosition: Int): Int? {
|
||||
for (index in startPosition.coerceAtMost(value.length - 1) downTo 0) {
|
||||
if (value[index] == Token.Operator.leftBracket[0]) {
|
||||
return index
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun findRightBracket(startPosition: Int): Int? {
|
||||
for (index in startPosition.coerceAtMost(value.length - 1) until value.length) {
|
||||
if (value[index] == Token.Operator.rightBracket[0]) {
|
||||
return index
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
// Based of https://stackoverflow.com/a/12752226/9878135
|
||||
fun findClosingParen(openPos: Int): Int {
|
||||
var closePos = openPos
|
||||
var counter = 1
|
||||
|
||||
while (counter > 0) {
|
||||
val c = value[++closePos]
|
||||
if (c == Token.Operator.leftBracket[0]) {
|
||||
counter++
|
||||
} else if (c == Token.Operator.rightBracket[0]) {
|
||||
counter--
|
||||
}
|
||||
}
|
||||
return closePos
|
||||
}
|
||||
}
|
@ -127,6 +127,15 @@ fun TextFieldValue.deleteTokens(): TextFieldValue {
|
||||
)
|
||||
}
|
||||
|
||||
fun TextFieldValue.smartDeleteTokens(): TextFieldValue {
|
||||
val deleteRange = SmartDeleteHandler(text, selection).calculateDeleteRange()
|
||||
|
||||
return this.copy(
|
||||
text = text.removeRange(deleteRange.start, deleteRange.end),
|
||||
selection = TextRange(deleteRange.start),
|
||||
)
|
||||
}
|
||||
|
||||
fun TextFieldValue.placeCursorAtTheEnd(): TextFieldValue = copy(selection = TextRange(text.length))
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user