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.
Δ Γ Λ Ω Φ Ψ Σ Θ answered only to De, Ga, La, Om, Ph, Ps, Si, Th, while
their small letters answered to delta, gamma and the rest; they answer to
the names too now. mkemoji and cldr2emoji write UTF-8 whatever the
locale, as the other generators already did; verify-map calls python3 the
one way; the tests' include path drops a directory nothing includes
through; and bench.sh says which binary is missing instead of blaming the
daemon ten seconds later.
II, PP, SS, sq, mul, vv, xx, oo, dn, inf, and deg were the only way to
∫ ∏ ∑ √ × ✓ ✗ ● ↓ ∞ °; integral, prod, sum, sqrt, times, check, cross,
circle, down, infinity, and degree find them as well.
A query typed in the Hiragana mode is hiragana; CLDR's Japanese
keywords are mostly katakana (スマイル, ハート), so the one could not
find the other. mkemoji now writes each alias that has kana in both
scripts.
emoji.src was a seed of thirty emoji. cldr2emoji now generates it from
Unicode's emoji-test.txt (Emoji 17.0) and CLDR 48.2.0's annotations: the
1914 fully-qualified emoji without their skin-tone variants, each with
its names and keywords in the three languages, so that a search finds
what fcitx5's emoji picker finds. The data is under the Unicode License,
added to LICENSES.
mkemoji wrote a row for every prefix of every alias, so that a query
matched as it was typed; the trie is a prefix index already, and with a
real emoji list those rows would be four times the aliases themselves.
Now emoji.dict has one row per alias, trienode() names a key's node, and
dictlookup walks the entries at and below it, the key's own first, up to
Maxkouho. Trie children are appended rather than pushed, so the walk
keeps the file's order and a bare digit still picks the superscript or
subscript it always did.
The hand-written symbol rows move to symbol.src; emoji.src is left to
the emoji. mkemoji reads both by default, or the files it is given.