map/symbol.src:12 says "Bare 1-9 choose from a prefix search; keep digit
aliases in matching slots", map/README:55 repeats it, and both
tests/engine_test.c:1001 and tests/mkemoji_test.py were written to it.
None of it happened. dictprefix ends in below(), which returns a node's
own words first and then its children in rune order (dict.c:29-39), and
under `^` the punctuation sorts ahead of the digits:
^ gave ⁽ ⁾ ⁺ ⁻ ⁰ ¹ ² ³ ⁴ ⁵ ...
_ gave ₍ ₎ ₊ ₋ ₀ ₁ ₂ ₃ ₄ ₅ ...
< gave ← ♥ 🫰🫶 ≤ ≠
so the file's own aliases picked the wrong character every time:
before after
^ then 1 ⁽ ¹
^ then 2 ⁾ ²
_ then 1 ₍ ₁
< then 3 🫰 ♥
mkemoji has no bare `^` row to emit, because no source row claims `^` as
an alias -- the prefix exists in the trie only as the parent of `^1`..`^9`
and `^(`..`^n`, and a parent has no words of its own. Giving the nine
superscripts `^` as a second alias, the nine subscripts `_`, and ←≤♥≠ `<`,
makes build() group them in source order and emit three rows:
< ← ≤ ♥ ≠
^ ¹ ² ³ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹
_ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉
which is what engine_test.c:1001's fixture has said all along, and the
first thing below() now returns. Nothing is lost: `^0`, `^(`, `^i` and
their kind still answer their own key, `0` is not a selection key so it
still extends the query, and addkouho drops the duplicate when a child
repeats what the parent already offered. Three rows on 18953.
tests/mkemoji_test.py was asking the wrong question. It checked that the
first nine `^` keys in the file are `^1`..`^9` -- true before and after,
and decided nothing, because the file's order is not the trie's. It now
checks the row the engine actually reads, and fails without this change
with a bare KeyError on `^`.
What this does not cover: `+1` and `-1`. They are not slot aliases, they
are words -- plus one, minus one -- and ➕ and ➖ are the right first
answers to `+` and `-`. 👍 is slot 3 of `+` and reachable there.