rename params, don't do unnecessary type checks, no unbraced multiline if's

This commit is contained in:
devycarol 2025-03-06 20:16:13 -07:00
parent 631ab60eb9
commit ec8c4e477f

View file

@ -9,43 +9,43 @@ import helium314.keyboard.latin.settings.SpacingAndPunctuations
import java.math.BigInteger import java.math.BigInteger
import java.util.Locale import java.util.Locale
fun loopOverCodePoints(s: CharSequence, run: (Int) -> Boolean) { fun loopOverCodePoints(text: CharSequence, loop: (cp: Int) -> Boolean) {
val text = if (s is String) s else s.toString() val s = text.toString()
var offset = 0 var offset = 0
while (offset < text.length) { while (offset < s.length) {
val codepoint = text.codePointAt(offset) val cp = s.codePointAt(offset)
if (run(codepoint)) return if (loop(cp)) return
offset += Character.charCount(codepoint) offset += Character.charCount(cp)
} }
} }
fun loopOverCodePointsBackwards(s: CharSequence, run: (Int) -> Boolean) { fun loopOverCodePointsBackwards(text: CharSequence, loop: (cp: Int) -> Boolean) {
val text = if (s is String) s else s.toString() val s = text.toString()
var offset = text.length var offset = s.length
while (offset > 0) { while (offset > 0) {
val codepoint = text.codePointBefore(offset) val cp = s.codePointBefore(offset)
if (run(codepoint)) return if (loop(cp)) return
offset -= Character.charCount(codepoint) offset -= Character.charCount(cp)
} }
} }
fun nonWordCodePointAndNoSpaceBeforeCursor(s: CharSequence, spacingAndPunctuations: SpacingAndPunctuations): Boolean { fun nonWordCodePointAndNoSpaceBeforeCursor(text: CharSequence, spacingAndPunctuations: SpacingAndPunctuations): Boolean {
var space = false var space = false
var nonWordCodePoint = false var nonWordCodePoint = false
loopOverCodePointsBackwards(s) { loopOverCodePointsBackwards(text) {
if (!space && Character.isWhitespace(it)) if (!space && Character.isWhitespace(it)) space = true
space = true
// treat double quote like a word codepoint for the purpose of this function (not great, maybe clarify name, or extend list of chars?) // treat double quote like a word codepoint for the purpose of this function (not great, maybe clarify name, or extend list of chars?)
if (!nonWordCodePoint && !spacingAndPunctuations.isWordCodePoint(it) && it != '"'.code) if (!nonWordCodePoint && !spacingAndPunctuations.isWordCodePoint(it) && it != '"'.code) {
nonWordCodePoint = true nonWordCodePoint = true
}
space && nonWordCodePoint // stop if both are found space && nonWordCodePoint // stop if both are found
} }
return nonWordCodePoint && !space // return true if an non-word codepoint and no space was found return nonWordCodePoint && !space // return true if an non-word codepoint and no space was found
} }
fun hasLetterBeforeLastSpaceBeforeCursor(s: CharSequence): Boolean { fun hasLetterBeforeLastSpaceBeforeCursor(text: CharSequence): Boolean {
var letter = false var letter = false
loopOverCodePointsBackwards(s) { loopOverCodePointsBackwards(text) {
if (Character.isWhitespace(it)) true if (Character.isWhitespace(it)) true
else if (Character.isLetter(it)) { else if (Character.isLetter(it)) {
letter = true letter = true
@ -56,17 +56,15 @@ fun hasLetterBeforeLastSpaceBeforeCursor(s: CharSequence): Boolean {
return letter return letter
} }
/** get the complete emoji at end of [s], considering that emojis can be joined with ZWJ resulting in different emojis */ /** get the complete emoji at end of [text], considering that emojis can be joined with ZWJ resulting in different emojis */
fun getFullEmojiAtEnd(s: CharSequence): String { fun getFullEmojiAtEnd(text: CharSequence): String {
val text = if (s is String) s else s.toString() val s = text.toString()
var offset = text.length var offset = s.length
while (offset > 0) { while (offset > 0) {
val codepoint = text.codePointBefore(offset) val codepoint = s.codePointBefore(offset)
// stop if codepoint can't be emoji // stop if codepoint can't be emoji
if (!mightBeEmoji(codepoint))
return text.substring(offset)
offset -= Character.charCount(codepoint) offset -= Character.charCount(codepoint)
if (offset > 0 && text[offset - 1].code == KeyCode.ZWJ) { if (offset > 0 && s[offset - 1].code == KeyCode.ZWJ) {
// todo: this appends ZWJ in weird cases like text, ZWJ, emoji // todo: this appends ZWJ in weird cases like text, ZWJ, emoji
// and detects single ZWJ as emoji (at least irrelevant for current use of getFullEmojiAtEnd) // and detects single ZWJ as emoji (at least irrelevant for current use of getFullEmojiAtEnd)
offset -= 1 offset -= 1
@ -76,19 +74,17 @@ fun getFullEmojiAtEnd(s: CharSequence): String {
if (codepoint in 0x1F3FB..0x1F3FF) { if (codepoint in 0x1F3FB..0x1F3FF) {
// Skin tones are not added with ZWJ, but just appended. This is not nice as they can be emojis on their own, // Skin tones are not added with ZWJ, but just appended. This is not nice as they can be emojis on their own,
// but that's how it is done. Assume that an emoji before the skin tone will get merged (usually correct in practice) // but that's how it is done. Assume that an emoji before the skin tone will get merged (usually correct in practice)
val codepointBefore = text.codePointBefore(offset) val codepointBefore = s.codePointBefore(offset)
if (isEmoji(codepointBefore)) { if (isEmoji(codepointBefore)) {
offset -= Character.charCount(codepointBefore) offset -= Character.charCount(codepointBefore)
continue continue
} }
} }
// check the whole text after offset // check the whole text after offset
val textToCheck = text.substring(offset) val textToCheck = s.substring(offset)
if (isEmoji(textToCheck)) { if (isEmoji(textToCheck)) return textToCheck
return textToCheck
}
} }
return text.substring(offset) return s.substring(offset)
} }
/** split the string on the first of consecutive space only, further consecutive spaces are added to the next split */ /** split the string on the first of consecutive space only, further consecutive spaces are added to the next split */
@ -110,8 +106,7 @@ fun String.splitOnFirstSpacesOnly(): List<String> {
sb.append(c) sb.append(c)
} }
} }
if (sb.isNotBlank()) if (sb.isNotBlank()) out.add(sb.toString())
out.add(sb.toString())
return out return out
} }
@ -120,8 +115,7 @@ fun CharSequence.isValidNumber(): Boolean {
} }
fun String.decapitalize(locale: Locale): String { fun String.decapitalize(locale: Locale): String {
if (isEmpty() || !this[0].isUpperCase()) if (isEmpty() || !this[0].isUpperCase()) return this
return this
return replaceFirstChar { it.lowercase(locale) } return replaceFirstChar { it.lowercase(locale) }
} }
@ -136,7 +130,7 @@ fun containsValueWhenSplit(string: String?, value: String, split: String): Boole
fun isEmoji(c: Int): Boolean = mightBeEmoji(c) && isEmoji(newSingleCodePointString(c)) fun isEmoji(c: Int): Boolean = mightBeEmoji(c) && isEmoji(newSingleCodePointString(c))
fun isEmoji(s: CharSequence): Boolean = mightBeEmoji(s) && s.matches(emoRegex) fun isEmoji(text: CharSequence): Boolean = mightBeEmoji(text) && text.matches(emoRegex)
fun String.splitOnWhitespace() = split(whitespaceSplitRegex) fun String.splitOnWhitespace() = split(whitespaceSplitRegex)