From d5c97a96973dab9884904997e3da89b3989ff9bb Mon Sep 17 00:00:00 2001 From: Helium314 Date: Thu, 1 Feb 2024 07:22:41 +0100 Subject: [PATCH] follow code in popup keys code will always be preferred over a|b style labels add some tests for adjusted KeySpecParser fixes #466 --- .../main/java/helium314/keyboard/keyboard/Key.java | 1 - .../keyboard/keyboard/internal/KeySpecParser.java | 14 +++++++------- .../internal/keyboard_parser/KeyboardParser.kt | 2 +- .../internal/keyboard_parser/floris/KeyData.kt | 8 +++++++- .../internal/keyboard_parser/floris/PopupSet.kt | 8 ++++---- .../keyboard/latin/utils/CustomLayoutUtils.kt | 1 + .../keyboard/latin/utils/MoreKeysUtils.kt | 6 +++--- .../{ParserTest.kt => KeyboardParserTest.kt} | 0 8 files changed, 23 insertions(+), 17 deletions(-) rename app/src/test/java/helium314/keyboard/{ParserTest.kt => KeyboardParserTest.kt} (100%) diff --git a/app/src/main/java/helium314/keyboard/keyboard/Key.java b/app/src/main/java/helium314/keyboard/keyboard/Key.java index 5ba6bcd7..38d13bd9 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/Key.java +++ b/app/src/main/java/helium314/keyboard/keyboard/Key.java @@ -1120,7 +1120,6 @@ public class Key implements Comparable { mHintLabel = null; } else { // maybe also always null for comma and period keys - // todo: maybe remove mKeyboardParams.mHintLabelFromFirstMoreKey? final String hintLabel = MoreKeysUtilsKt.getHintLabel(popupSet, params, keySpec); mHintLabel = needsToUpcase ? StringUtils.toTitleCaseOfKeyLabel(hintLabel, localeForUpcasing) diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/KeySpecParser.java b/app/src/main/java/helium314/keyboard/keyboard/internal/KeySpecParser.java index df98f489..1af6c0ab 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/KeySpecParser.java +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/KeySpecParser.java @@ -18,7 +18,7 @@ import androidx.annotation.Nullable; /** * The string parser of the key specification. - * + *

* Each key specification is one of the following: * - Label optionally followed by keyOutputText (keyLabel|keyOutputText). * - 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) { final int length = keySpec.length(); if (keySpec.indexOf(BACKSLASH) < 0) { - final int labelEnd = keySpec.indexOf(VERTICAL_BAR); + final int labelEnd = keySpec.lastIndexOf(VERTICAL_BAR); if (labelEnd == 0) { if (length == 1) { // Treat a sole vertical bar as a special case of key label. @@ -95,12 +95,12 @@ public final class KeySpecParser { } return labelEnd; } - for (int pos = 0; pos < length; pos++) { + for (int pos = length - 1; pos >= 0; pos--) { final char c = keySpec.charAt(pos); - if (c == BACKSLASH && pos + 1 < length) { - // Skip escape char - pos++; - } else if (c == VERTICAL_BAR) { + if (c != VERTICAL_BAR) continue; + if (pos > 0 && keySpec.charAt(pos - 1) == BACKSLASH) { + pos--; // Skip escape char + } else { return pos; } } diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt index 79172493..134f8ab0 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/KeyboardParser.kt @@ -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) 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 } if (keyParams.mLabel?.length?.let { it > 1 } == true && keyParams.mLabel?.startsWith("!string/") == true) { diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyData.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyData.kt index 003c6bc4..31e9fd39 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyData.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/KeyData.kt @@ -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 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)}" + } } /** diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/PopupSet.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/PopupSet.kt index b29a3e75..012be0ea 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/PopupSet.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/floris/PopupSet.kt @@ -9,8 +9,8 @@ import kotlinx.serialization.Serializable import helium314.keyboard.keyboard.internal.KeySpecParser import helium314.keyboard.keyboard.internal.KeyboardParams -// taken from FlorisBoard, considerably modified -// we don't care about the difference between main and relevant in this app +// only the constructor and name remain from FlorisBoard +// we don't care about the difference between main and relevant (at least for now) @Serializable open class PopupSet( open val main: T? = null, @@ -20,8 +20,8 @@ open class PopupSet( open fun getPopupKeyLabels(params: KeyboardParams): Collection? { if (main == null && relevant == null) return null val moreKeys = mutableListOf() - main?.getLabel(params)?.let { moreKeys.add(KeySpecParser.getLabel(it)!!) } - relevant?.let { moreKeys.addAll(it.map { KeySpecParser.getLabel(it.getLabel(params))!! }) } + main?.getPopupLabel(params)?.let { moreKeys.add(it) } + relevant?.let { moreKeys.addAll(it.map { it.getPopupLabel(params) }) } if (moreKeys.isEmpty()) return null return moreKeys } diff --git a/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt index 88e89b47..a9b47847 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/CustomLayoutUtils.kt @@ -148,6 +148,7 @@ fun editCustomLayout(layoutName: String, context: Context, startContent: String? val isJson = checkLayout(content, context) if (isJson == null) { 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)) } else { val wasJson = file.name.substringAfterLast(".") == "json" diff --git a/app/src/main/java/helium314/keyboard/latin/utils/MoreKeysUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/MoreKeysUtils.kt index add6ba59..40bf0990 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/MoreKeysUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/MoreKeysUtils.kt @@ -15,6 +15,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import helium314.keyboard.keyboard.Key +import helium314.keyboard.keyboard.internal.KeySpecParser import helium314.keyboard.keyboard.internal.KeyboardParams import helium314.keyboard.keyboard.internal.keyboard_parser.floris.PopupSet import helium314.keyboard.keyboard.internal.keyboard_parser.rtlLabel @@ -80,11 +81,10 @@ fun getHintLabel(popupSet: PopupSet<*>?, params: KeyboardParams, label: String): if (hintLabel != null) break } - // don't do the rtl transform, hint label is only the label - return hintLabel?.let { if (it == "$$$") transformLabel(it, params) else it } + return hintLabel?.let { KeySpecParser.getLabel(transformLabel(it, params)) } // avoid e.g. !autoColumnOrder! as label // 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 = diff --git a/app/src/test/java/helium314/keyboard/ParserTest.kt b/app/src/test/java/helium314/keyboard/KeyboardParserTest.kt similarity index 100% rename from app/src/test/java/helium314/keyboard/ParserTest.kt rename to app/src/test/java/helium314/keyboard/KeyboardParserTest.kt