follow code in popup keys

code will always be preferred over a|b style labels
add some tests for adjusted KeySpecParser
fixes #466
This commit is contained in:
Helium314 2024-02-01 07:22:41 +01:00
parent f19ffa54c9
commit d5c97a9697
8 changed files with 23 additions and 17 deletions

View file

@ -1120,7 +1120,6 @@ public class Key implements Comparable<Key> {
mHintLabel = null; mHintLabel = null;
} else { } else {
// maybe also always null for comma and period keys // maybe also always null for comma and period keys
// todo: maybe remove mKeyboardParams.mHintLabelFromFirstMoreKey?
final String hintLabel = MoreKeysUtilsKt.getHintLabel(popupSet, params, keySpec); final String hintLabel = MoreKeysUtilsKt.getHintLabel(popupSet, params, keySpec);
mHintLabel = needsToUpcase mHintLabel = needsToUpcase
? StringUtils.toTitleCaseOfKeyLabel(hintLabel, localeForUpcasing) ? StringUtils.toTitleCaseOfKeyLabel(hintLabel, localeForUpcasing)

View file

@ -18,7 +18,7 @@ import androidx.annotation.Nullable;
/** /**
* The string parser of the key specification. * The string parser of the key specification.
* * <p>
* Each key specification is one of the following: * Each key specification is one of the following:
* - Label optionally followed by keyOutputText (keyLabel|keyOutputText). * - Label optionally followed by keyOutputText (keyLabel|keyOutputText).
* - Label optionally followed by code point (keyLabel|!code/code_name). * - Label optionally followed by code point (keyLabel|!code/code_name).
@ -83,7 +83,7 @@ public final class KeySpecParser {
private static int indexOfLabelEnd(@NonNull final String keySpec) { private static int indexOfLabelEnd(@NonNull final String keySpec) {
final int length = keySpec.length(); final int length = keySpec.length();
if (keySpec.indexOf(BACKSLASH) < 0) { if (keySpec.indexOf(BACKSLASH) < 0) {
final int labelEnd = keySpec.indexOf(VERTICAL_BAR); final int labelEnd = keySpec.lastIndexOf(VERTICAL_BAR);
if (labelEnd == 0) { if (labelEnd == 0) {
if (length == 1) { if (length == 1) {
// Treat a sole vertical bar as a special case of key label. // Treat a sole vertical bar as a special case of key label.
@ -95,12 +95,12 @@ public final class KeySpecParser {
} }
return labelEnd; return labelEnd;
} }
for (int pos = 0; pos < length; pos++) { for (int pos = length - 1; pos >= 0; pos--) {
final char c = keySpec.charAt(pos); final char c = keySpec.charAt(pos);
if (c == BACKSLASH && pos + 1 < length) { if (c != VERTICAL_BAR) continue;
// Skip escape char if (pos > 0 && keySpec.charAt(pos - 1) == BACKSLASH) {
pos++; pos--; // Skip escape char
} else if (c == VERTICAL_BAR) { } else {
return pos; return pos;
} }
} }

View file

@ -289,7 +289,7 @@ abstract class KeyboardParser(private val params: KeyboardParams, private val co
if (key.type != KeyType.NUMERIC && keyParams.mBackgroundType != Key.BACKGROUND_TYPE_ACTION) if (key.type != KeyType.NUMERIC && keyParams.mBackgroundType != Key.BACKGROUND_TYPE_ACTION)
keyParams.mBackgroundType = Key.BACKGROUND_TYPE_FUNCTIONAL keyParams.mBackgroundType = Key.BACKGROUND_TYPE_FUNCTIONAL
if (params.mId.mElementId == KeyboardId.ELEMENT_PHONE && key.popup.main?.getLabel(params)?.length?.let { it > 1 } == true) { if (params.mId.mElementId == KeyboardId.ELEMENT_PHONE && key.popup.main?.getPopupLabel(params)?.length?.let { it > 1 } == true) {
keyParams.mMoreKeys = null // the ABC and stuff labels should not create moreKeys keyParams.mMoreKeys = null // the ABC and stuff labels should not create moreKeys
} }
if (keyParams.mLabel?.length?.let { it > 1 } == true && keyParams.mLabel?.startsWith("!string/") == true) { if (keyParams.mLabel?.length?.let { it > 1 } == true && keyParams.mLabel?.startsWith("!string/") == true) {

View file

@ -49,7 +49,13 @@ interface AbstractKeyData {
*/ */
fun asString(isForDisplay: Boolean): String // todo: remove it? not used at all (better only later, maybe useful for getting display label in some languages) fun asString(isForDisplay: Boolean): String // todo: remove it? not used at all (better only later, maybe useful for getting display label in some languages)
fun getLabel(params: KeyboardParams) = if (this is KeyData) label else compute(params)?.label ?: "" /** get the label, but also considers code, which can't be set separately for popup keys and thus goes into the label */
fun getPopupLabel(params: KeyboardParams): String {
val keyData = if (this is KeyData) this else compute(params) ?: return ""
if (keyData.code == KeyCode.UNSPECIFIED || keyData.code < 0) // don't allow negative codes in popups
return keyData.label
return "${keyData.label}|${StringUtils.newSingleCodePointString(keyData.code)}"
}
} }
/** /**

View file

@ -9,8 +9,8 @@ import kotlinx.serialization.Serializable
import helium314.keyboard.keyboard.internal.KeySpecParser import helium314.keyboard.keyboard.internal.KeySpecParser
import helium314.keyboard.keyboard.internal.KeyboardParams import helium314.keyboard.keyboard.internal.KeyboardParams
// taken from FlorisBoard, considerably modified // only the constructor and name remain from FlorisBoard
// we don't care about the difference between main and relevant in this app // we don't care about the difference between main and relevant (at least for now)
@Serializable @Serializable
open class PopupSet<T : AbstractKeyData>( open class PopupSet<T : AbstractKeyData>(
open val main: T? = null, open val main: T? = null,
@ -20,8 +20,8 @@ open class PopupSet<T : AbstractKeyData>(
open fun getPopupKeyLabels(params: KeyboardParams): Collection<String>? { open fun getPopupKeyLabels(params: KeyboardParams): Collection<String>? {
if (main == null && relevant == null) return null if (main == null && relevant == null) return null
val moreKeys = mutableListOf<String>() val moreKeys = mutableListOf<String>()
main?.getLabel(params)?.let { moreKeys.add(KeySpecParser.getLabel(it)!!) } main?.getPopupLabel(params)?.let { moreKeys.add(it) }
relevant?.let { moreKeys.addAll(it.map { KeySpecParser.getLabel(it.getLabel(params))!! }) } relevant?.let { moreKeys.addAll(it.map { it.getPopupLabel(params) }) }
if (moreKeys.isEmpty()) return null if (moreKeys.isEmpty()) return null
return moreKeys return moreKeys
} }

View file

@ -148,6 +148,7 @@ fun editCustomLayout(layoutName: String, context: Context, startContent: String?
val isJson = checkLayout(content, context) val isJson = checkLayout(content, context)
if (isJson == null) { if (isJson == null) {
editCustomLayout(layoutName, context, content) editCustomLayout(layoutName, context, content)
// todo: this actually always returns the "simple layout" error, even on a json layout with a single small error
infoDialog(context, context.getString(R.string.layout_error, Log.getLog(10).lastOrNull { it.tag == TAG }?.message)) infoDialog(context, context.getString(R.string.layout_error, Log.getLog(10).lastOrNull { it.tag == TAG }?.message))
} else { } else {
val wasJson = file.name.substringAfterLast(".") == "json" val wasJson = file.name.substringAfterLast(".") == "json"

View file

@ -15,6 +15,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import helium314.keyboard.keyboard.Key import helium314.keyboard.keyboard.Key
import helium314.keyboard.keyboard.internal.KeySpecParser
import helium314.keyboard.keyboard.internal.KeyboardParams import helium314.keyboard.keyboard.internal.KeyboardParams
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.PopupSet import helium314.keyboard.keyboard.internal.keyboard_parser.floris.PopupSet
import helium314.keyboard.keyboard.internal.keyboard_parser.rtlLabel import helium314.keyboard.keyboard.internal.keyboard_parser.rtlLabel
@ -80,11 +81,10 @@ fun getHintLabel(popupSet: PopupSet<*>?, params: KeyboardParams, label: String):
if (hintLabel != null) break if (hintLabel != null) break
} }
// don't do the rtl transform, hint label is only the label return hintLabel?.let { KeySpecParser.getLabel(transformLabel(it, params)) }
return hintLabel?.let { if (it == "$$$") transformLabel(it, params) else it }
// avoid e.g. !autoColumnOrder! as label // avoid e.g. !autoColumnOrder! as label
// this will avoid having labels on comma and period keys // this will avoid having labels on comma and period keys
?.takeIf { !it.startsWith("!") || it == "!" } ?.takeIf { !it.startsWith("!") || it.count { it == '!' } != 2 } // excluding the special labels
} }
private fun transformLabel(label: String, params: KeyboardParams): String = private fun transformLabel(label: String, params: KeyboardParams): String =