From 23439a52f7dda0e313fbbd91a9a857a226009fbc Mon Sep 17 00:00:00 2001 From: afiqzudinhadi Date: Fri, 3 Jul 2026 20:08:45 +0800 Subject: [PATCH] Parse Plover number strokes: digits = number bar + positional key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit parse_stroke silently dropped digit characters, so number strokes collapsed onto their letter-only bitmasks: "12K" and "K" both parsed to K → first-wins dedup let "12K"→"12:00" clobber "K"→"can" (and 297 more core entries: -R→are eaten by 12-R→XII, -S→{^s} by 2-S→2s...). Digits now map per Plover: 1=S- 2=T- 3=P- 4=H- 5=A- 0=O- 6=-F 7=-P 8=-L 9=-T, all implying #. Collisions: 298 → 0; 300 union keys and 161 translations recovered. Verified: all 262,309 entries byte-exact, 42,000-vector host round trip 0 mismatches. --- tools/compile_mphf.py | 25 ++++++++++++++++++++++--- tools/compile_v4.py | 25 ++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/tools/compile_mphf.py b/tools/compile_mphf.py index b54576d..e105328 100755 --- a/tools/compile_mphf.py +++ b/tools/compile_mphf.py @@ -31,14 +31,27 @@ STENO_KEYS = { IMPLICIT_HYPHEN = set('AOEU*') +# Plover number strokes: a digit means the number bar (#) plus the key +# sharing its physical position. Each digit maps to exactly one key. +DIGIT_KEYS = { + '1': 'S-', '2': 'T-', '3': 'P-', '4': 'H-', + '5': 'A-', '0': 'O-', + '6': '-F', '7': '-P', '8': '-L', '9': '-T', +} + + def parse_stroke(s): result = 0 if '#' in s: result |= STENO_KEYS['#'] s = s.replace('#', '') + if any(c in DIGIT_KEYS for c in s): + result |= STENO_KEYS['#'] has_hyphen = '-' in s s_clean = s.replace('-', '') - if not has_hyphen and not any(c in IMPLICIT_HYPHEN for c in s_clean): + if (not has_hyphen and + not any(c in IMPLICIT_HYPHEN for c in s_clean) and + not any(c in DIGIT_KEYS for c in s_clean)): for c in s_clean: key = c + '-' if key in STENO_KEYS: @@ -49,7 +62,9 @@ def parse_stroke(s): for i, c in enumerate(s): if c == '-': continue - if c in 'AO': + if c in DIGIT_KEYS: + result |= STENO_KEYS[DIGIT_KEYS[c]] + elif c in 'AO': result |= STENO_KEYS[c + '-'] elif c in 'EU': result |= STENO_KEYS['-' + c] @@ -62,7 +77,11 @@ def parse_stroke(s): else: past_vowels = False for c in s_clean: - if c in 'AO': + if c in DIGIT_KEYS: + result |= STENO_KEYS[DIGIT_KEYS[c]] + if c in '5069' or c in '78': + past_vowels = True + elif c in 'AO': result |= STENO_KEYS[c + '-'] past_vowels = True elif c in 'EU': diff --git a/tools/compile_v4.py b/tools/compile_v4.py index 86686ed..9701f59 100644 --- a/tools/compile_v4.py +++ b/tools/compile_v4.py @@ -98,14 +98,27 @@ STENO_KEYS = { IMPLICIT_HYPHEN = set('AOEU*') +# Plover number strokes: a digit means the number bar (#) plus the key +# sharing its physical position. Each digit maps to exactly one key. +DIGIT_KEYS = { + '1': 'S-', '2': 'T-', '3': 'P-', '4': 'H-', + '5': 'A-', '0': 'O-', + '6': '-F', '7': '-P', '8': '-L', '9': '-T', +} + + def parse_stroke(s): result = 0 if '#' in s: result |= STENO_KEYS['#'] s = s.replace('#', '') + if any(c in DIGIT_KEYS for c in s): + result |= STENO_KEYS['#'] has_hyphen = '-' in s s_clean = s.replace('-', '') - if not has_hyphen and not any(c in IMPLICIT_HYPHEN for c in s_clean): + if (not has_hyphen and + not any(c in IMPLICIT_HYPHEN for c in s_clean) and + not any(c in DIGIT_KEYS for c in s_clean)): for c in s_clean: key = c + '-' if key in STENO_KEYS: @@ -116,7 +129,9 @@ def parse_stroke(s): for i, c in enumerate(s): if c == '-': continue - if c in 'AO': + if c in DIGIT_KEYS: + result |= STENO_KEYS[DIGIT_KEYS[c]] + elif c in 'AO': result |= STENO_KEYS[c + '-'] elif c in 'EU': result |= STENO_KEYS['-' + c] @@ -129,7 +144,11 @@ def parse_stroke(s): else: past_vowels = False for c in s_clean: - if c in 'AO': + if c in DIGIT_KEYS: + result |= STENO_KEYS[DIGIT_KEYS[c]] + if c in '5069' or c in '78': + past_vowels = True + elif c in 'AO': result |= STENO_KEYS[c + '-'] past_vowels = True elif c in 'EU':