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;
} 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)

View file

@ -18,7 +18,7 @@ import androidx.annotation.Nullable;
/**
* The string parser of the key specification.
*
* <p>
* 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;
}
}

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)
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) {

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 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.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<T : AbstractKeyData>(
open val main: T? = null,
@ -20,8 +20,8 @@ open class PopupSet<T : AbstractKeyData>(
open fun getPopupKeyLabels(params: KeyboardParams): Collection<String>? {
if (main == null && relevant == null) return null
val moreKeys = mutableListOf<String>()
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
}

View file

@ -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"

View file

@ -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 =