From 08ebf8fabc860fb66d586aade838483dda86b5b0 Mon Sep 17 00:00:00 2001 From: Jules Aguillon Date: Sat, 13 Dec 2025 15:58:34 +0100 Subject: Fix parsing of escaped characters in macros (#1126) * refactor: Better printing for KeyValue in tests * Fix parsing of escaped characters in macros The parsing code was bugged with custom macros like `symbol:\abc` and `symbol:\\abc`.--- srcs/juloo.keyboard2/KeyValue.java | 33 ++++++++++++++++++++++++---- srcs/juloo.keyboard2/KeyValueParser.java | 7 +++--- test/juloo.keyboard2/KeyValueParserTest.java | 10 +++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/srcs/juloo.keyboard2/KeyValue.java b/srcs/juloo.keyboard2/KeyValue.java index df0ef9d..d0c1fc7 100644 --- a/srcs/juloo.keyboard2/KeyValue.java +++ b/srcs/juloo.keyboard2/KeyValue.java @@ -312,8 +312,11 @@ public final class KeyValue implements Comparable public String toString() { - int value = _code & VALUE_BITS; - return "[KeyValue " + getKind().toString() + "+" + getFlags() + "+" + value + " \"" + getString() + "\"]"; + StringBuilder b = new StringBuilder() + .append(getKind().name()).append(":").append(getString()); + if (_payload instanceof Describe) + b.append(":").append(((Describe)_payload).describe()); + return b.toString(); } private KeyValue(Comparable p, int kind, int value, int flags) @@ -817,7 +820,14 @@ public final class KeyValue implements Comparable throw new RuntimeException("Assertion failure"); } - public static enum Slider + public static interface Describe + { + /** Describe the payload content, without the symbol. + Used for printing in tests. */ + public String describe(); + } + + public static enum Slider implements Describe { Cursor_left(0xE008), Cursor_right(0xE006), @@ -835,9 +845,12 @@ public final class KeyValue implements Comparable @Override public String toString() { return symbol; } + + @Override + public String describe() { return name(); } }; - public static final class Macro implements Comparable + public static final class Macro implements Comparable, Describe { public final KeyValue[] keys; private final String _symbol; @@ -848,8 +861,20 @@ public final class KeyValue implements Comparable _symbol = sym_; } + @Override public String toString() { return _symbol; } + @Override + public String describe() + { + StringBuilder b = new StringBuilder(); + if (keys.length > 0) + b.append(keys[0].toString()); + for (int i = 1; i < keys.length; i++) + b.append(",").append(keys[i].toString()); + return b.toString(); + } + @Override public int compareTo(Macro snd) { diff --git a/srcs/juloo.keyboard2/KeyValueParser.java b/srcs/juloo.keyboard2/KeyValueParser.java index 08558ad..a8c1fe7 100644 --- a/srcs/juloo.keyboard2/KeyValueParser.java +++ b/srcs/juloo.keyboard2/KeyValueParser.java @@ -60,7 +60,7 @@ public final class KeyValueParser if (KEYDEF_TOKEN != null) return; KEYDEF_TOKEN = Pattern.compile("'|,|keyevent:|(?:[^\\\\',]+|\\\\.)+"); - QUOTED_PAT = Pattern.compile("((?:[^'\\\\]+|\\\\')*)'"); + QUOTED_PAT = Pattern.compile("((?:[^'\\\\]+|\\\\.)*)'"); WORD_PAT = Pattern.compile("[a-zA-Z0-9_]+|."); } @@ -119,16 +119,17 @@ public final class KeyValueParser { if (!s.contains("\\")) return s; - StringBuilder out = new StringBuilder(s.length()); final int len = s.length(); + StringBuilder out = new StringBuilder(len); int prev = 0, i = 0; for (; i < len; i++) if (s.charAt(i) == '\\') { out.append(s, prev, i); prev = i + 1; + i++; } - out.append(s, prev, i); + out.append(s, prev, len); return out.toString(); } diff --git a/test/juloo.keyboard2/KeyValueParserTest.java b/test/juloo.keyboard2/KeyValueParserTest.java index d56b6b5..aa506e7 100644 --- a/test/juloo.keyboard2/KeyValueParserTest.java +++ b/test/juloo.keyboard2/KeyValueParserTest.java @@ -44,6 +44,12 @@ public class KeyValueParserTest KeyValue.getSpecialKeyByName("ctrl"), KeyValue.getSpecialKeyByName("backspace") }, 0)); + Utils.parse("symbol:a,'\\\\abc','abc','a\\\\bc'", KeyValue.makeMacro("symbol", new KeyValue[]{ + KeyValue.makeStringKey("a"), + KeyValue.makeStringKey("\\abc"), + KeyValue.makeStringKey("abc"), + KeyValue.makeStringKey("a\\bc") + }, 0)); Utils.expect_error("symbol:"); Utils.expect_error("unterminated_string:'"); Utils.expect_error("unterminated_string:abc,'"); @@ -57,6 +63,10 @@ public class KeyValueParserTest { Utils.parse("a:b", KeyValue.makeCharKey('b', "a", 0)); Utils.parse("symbol:abc", KeyValue.makeStringKey("abc").withSymbol("symbol")); + Utils.parse("symbol:\\abc", KeyValue.makeStringKey("abc").withSymbol("symbol")); + Utils.parse("symbol:a\\bc", KeyValue.makeStringKey("abc").withSymbol("symbol")); + Utils.parse("symbol:\\\\abc", KeyValue.makeStringKey("\\abc").withSymbol("symbol")); + Utils.parse("symbol:a\\\\bc", KeyValue.makeStringKey("a\\bc").withSymbol("symbol")); } @Test -- cgit v1.2.3