Pinyin query: 110 lines of trie code, word frequency boosting, atomic user dictionary persistence.

This is part 4/8 of the TUX IM Dev Log: From Zero to 0.1 series.

Part 4 · Pinyin Mode: trie, Word Frequency, User Dictionary

This post starts the technical deep dive. Pinyin query is the hottest code path in the entire input method — every keypress requires multiple trie lookups. I’ll cover three things: the trie data structure itself, the word frequency learning mechanism, and atomic user dictionary persistence.

trie: 110 Lines Supporting All Pinyin Queries

First, the code (tux_im/input/lexicon/_trie.py):

Python
@dataclass
class _TrieNode:
    children: dict[str, _TrieNode] = field(default_factory=dict)
    entries: list[LexEntry] = field(default_factory=list)
    is_word: bool = False

class Trie:
    __slots__ = ("_root", "_size")

    def __init__(self) -> None:
        self._root = _TrieNode()
        self._size = 0

    def insert(self, code: str, word: str, freq: int = 0) -> None:
        code = code.lower().strip()
        if not code or not word:
            return
        node = self._root
        for ch in code:
            node = node.children.setdefault(ch, _TrieNode())
        if not node.is_word:
            self._size += 1
        node.entries.append(LexEntry(word=word, freq=freq, code=code))
        node.entries.sort(key=lambda e: (-e.freq, e.word))

The entire file is 110 lines, zero IO, zero logging, zero side effects. All 14 trie algorithm tests don’t need to mock the filesystem.

Why pure data structure is critical? Because trie is on the hot path — every keypress queries it. If trie mixed in IO, the entire hot path would be slowed down; mixed in logging, unit tests would be interrupted; mixed in state, tests would be non-repeatable. Pure = fast = testable = trustworthy.

For a buffer like nihao, it’s first segmented into ['ni3', 'hao3'] (via PinyinMode.segment()), then for each syllable, candidates are generated by looking up the trie and taking the top-k results, indexed by segment position.

Word Frequency Learning

TUX IM learns user preferences silently. Every time a user selects a candidate, the frequency of that word is incremented. This data is persisted atomically to prevent corruption.

Atomic User Dictionary Persistence

The user dictionary is saved to disk atomically using a write-to-temp-then-rename strategy, ensuring that a crash during write doesn’t corrupt the dictionary file.

Last modified: 2026年6月25日

Author

Comments

Write a Reply or Comment

Your email address will not be published.