# How the Auxiliary Code (辅码) System Works in Wanxiang: A Technical Deep Dive

> **Wanxiang's auxiliary code system enables precise Chinese character input by appending user-defined supplemental codes after pinyin, parsing these from dictionary comments via the [`super_lookup.lua`](https://github.com/amzxyz...

- Repository: [amzxyz/rime_wanxiang](https://github.com/amzxyz/rime_wanxiang)
- Tags: 
- Published: 2026-02-24

---

**Wanxiang's auxiliary code system enables precise Chinese character input by appending user-defined supplemental codes after pinyin, parsing these from dictionary comments via the [`super_lookup.lua`](https://github.com/amzxyz/rime_wanxiang/blob/main/super_lookup.lua) processor to filter candidates.**

The **auxiliary code (辅码) system in Wanxiang** provides a sophisticated mechanism for disambiguating Chinese character input by combining standard pinyin with secondary lookup codes. Implemented in the `amzxyz/rime_wanxiang` repository, this feature leverages Lua scripting to parse semicolon-delimited codes from dictionary comments, enabling both exact and fuzzy matching strategies that prioritize user-defined shortcuts over standard reverse lookup.

## Where Auxiliary Codes Are Stored

Wanxiang stores auxiliary codes in two primary locations, allowing flexibility between built-in tables and custom dictionary annotations.

### Built-in Auxiliary Tables

The **built-in aux table** resides in [`custom/aux_code.txt`](https://github.com/amzxyz/rime_wanxiang/blob/main/custom/aux_code.txt), which the build script [`aux_go.py`](https://github.com/amzxyz/rime_wanxiang/blob/main/aux_go.py) references at line 168 (`AUX_FILE = "custom/aux_code.txt"`) to inject into the runtime dictionary. This file maps individual characters to their permissible auxiliary codes using a strict tab-delimited format:

```text
呵	;kk;kk;kk;dz;ks;kk;kh
嗄	;kw;kw;kx;dh;kd;kw;kh
錒	;jk;jk;ja;zz;qb;;jv

```

Each line contains the character, a tab separator, and a semicolon-delimited list of auxiliary strings. The leading semicolon ensures empty entries are handled correctly during parsing.

### Comment-Driven Auxiliary Data

Any dictionary entry may embed auxiliary codes directly in its **comment field** using the same `;code1;code2;…` syntax. This approach powers the **Pro** version, which pulls aux data from reverse-lookup dictionaries without modifying the core table. During candidate generation, the engine extracts these codes from the comment text to build the auxiliary lookup index.

## Enabling the Aux Source in Your Schema

The schema configuration determines whether the engine processes auxiliary data. In [`wanxiang_pro.schema.yaml`](https://github.com/amzxyz/rime_wanxiang/blob/main/wanxiang_pro.schema.yaml), the `data_source` field controls this behavior:

```yaml

# wanxiang_pro.schema.yaml

data_source: ['aux', 'db']   # load aux codes from comments first, then DB reverse lookup

```

When `'aux'` appears in the `data_source` array, the Lua engine sets `env.has_comment = true` during initialization (lines 28-31 of [`super_lookup.lua`](https://github.com/amzxyz/rime_wanxiang/blob/main/super_lookup.lua)). This flag triggers the parsing pipeline for all subsequent candidates. In the **Standard** schema, only `['db']` is listed by default, meaning auxiliary codes remain inactive unless the user explicitly adds `'aux'` to the configuration.

## Parsing Comments into Auxiliary Lists

The core parsing logic lives in `parse_comment_codes()` at lines 66-96 of [`wanxiang/lua/super_lookup.lua`](https://github.com/amzxyz/rime_wanxiang/blob/main/wanxiang/lua/super_lookup.lua). This function transforms raw comment text into structured auxiliary data:

```lua
local function parse_comment_codes(comment, pattern, target_len, enable_tone)
    local parts = split_string(comment, pattern)
    local result = {}
    
    for i, part in ipairs(parts) do
        local p1, p2 = part:find(";")
        local pinyin_part = p1 and part:sub(1, p1-1) or part
        local codes_part  = p1 and part:sub(p2+1) or ""

        local codes_list = {}
        if #codes_part > 0 then                     -- Extract aux codes
            for c in codes_part:gmatch("[^,]+") do
                local trimmed = c:gsub("^%s+", ""):gsub("%s+$", "")
                if #trimmed > 0 then table.insert(codes_list, trimmed) end
            end
        end
        if enable_tone then                         -- Extract tone numbers (optional)
            local tone = get_tone_from_pinyin(pinyin_part)
            if tone then table.insert(codes_list, tone) end
        end
        result[i] = codes_list
    end
    return result
end

```

The function returns a **nested table** where each index corresponds to a character position, containing an array of valid auxiliary strings and optional tone digits. The delimiter for splitting comment segments defaults to a space-apostrophe combination (`" '"`), configurable via `speller/delimiter` in the schema.

## Building Raw Candidate Data

During the lookup loop, each candidate receives a `raw_data` record that caches parsed auxiliary information. Lines 53-64 of [`super_lookup.lua`](https://github.com/amzxyz/rime_wanxiang/blob/main/super_lookup.lua) demonstrate this assignment:

```lua
-- A. Aux data (from comment)
if env.has_comment then
    local comment_text = genuine and genuine.comment or ""
    if comment_text ~= "" then
        comment_cache[cache_key] = parse_comment_codes(...)
        raw_data.aux = comment_cache[cache_key]           -- Stored for matching
        raw_data._comment_internal = comment_cache[cache_key]  -- Used for tone borrowing
    end
end

```

The **comment cache** prevents redundant parsing of identical comment strings across multiple candidates, significantly improving performance during large dictionary lookups.

## Splitting and Processing User Input

When input arrives, the engine separates the primary pinyin from the auxiliary code using `split_lookup_input()`:

```lua
local _, fuma, s_start, s_end = split_lookup_input(ctx_input, env.search_key_str, env.bypass_prefix)

```

The variable `fuma` contains everything after the delimiter (e.g., `kk` in `呵/kk`). The engine then filters this into:
- **`clean_fuma`**: The actual auxiliary code characters
- **`tone_filter_seq`**: Extracted tone digits (7-0) when `enable_tone` is active

This separation occurs in the main processing loop at lines 12-22 of [`super_lookup.lua`](https://github.com/amzxyz/rime_wanxiang/blob/main/super_lookup.lua).

## Matching Auxiliary Codes Against Input

For each configured `data_source` (processed in array order), the engine retrieves the appropriate code list and performs **matching**:

1. **Exact group matching** for single-character candidates using `group_match()`
2. **Fuzzy recursive matching** for multi-character words using `match_fuzzy_recursive()`

The logic at lines 31-46 implements this discrimination:

```lua
if source_type == 'aux' then
    if cand_len == 1 then
        if group_match(codes_seq[1], clean_fuma) then is_match = true end
    else
        if match_fuzzy_recursive(codes_seq, 1, clean_fuma, 1, memo, false) then is_match = true end
    end
elseif source_type == 'db' then
    -- Similar algorithm with DB-specific flag
end

```

**Priority ordering** is enforced by the `data_source` array sequence. Since `['aux', 'db']` places `'aux'` first, matches from the auxiliary code system outrank standard reverse-lookup matches, ensuring user-defined shortcuts take precedence.

## Tone Borrowing for Reverse Lookup

When `enable_tone = true`, the system extracts tone numbers from comments and stores them in `borrowed_tones`. During the tone-filter step (lines 20-22), the engine accepts tone digits as valid auxiliary inputs if they appear in the borrowed set:

```lua
if not has_tone and source_type == 'db' then
    if borrowed_tones[k] and borrowed_tones[k][tone_input] then has_tone = true end
end

```

This allows inputs like `shi/5` (tone 5) to retrieve the character `是` if the comment contains that tone marking, effectively treating tonal information as auxiliary codes during DB lookups.

## Practical Usage Examples

| Desired Character | Input Pattern | Mechanism |
|-------------------|---------------|-----------|
| `呵` | `he/kk` or `he/dz` | The aux part `kk` matches against the list from [`custom/aux_code.txt`](https://github.com/amzxyz/rime_wanxiang/blob/main/custom/aux_code.txt) |
| `爱` | `ai/vw` | Matches comment-embedded code `vw` from the reverse dictionary |
| `是` (tone) | `shi/5` | `enable_tone` treats `5` as aux code via tone borrowing |
| Multi-char word | `zhong/kw` | `match_fuzzy_recursive` walks each character's aux list to fit `kw` |

The delimiter (default `/`) is configurable via the `speller/delimiter` option in your schema YAML.

## Summary

- **Auxiliary codes** are semicolon-delimited strings stored in [`custom/aux_code.txt`](https://github.com/amzxyz/rime_wanxiang/blob/main/custom/aux_code.txt) or dictionary comments
- **Enable the feature** by adding `'aux'` to the `data_source` array in your schema configuration
- **Parsing** occurs via `parse_comment_codes()` at lines 66-96 of [`super_lookup.lua`](https://github.com/amzxyz/rime_wanxiang/blob/main/super_lookup.lua), handling both aux strings and tone numbers
- **Matching** uses exact matching for single characters and fuzzy recursive matching for phrases, with `'aux'` sources outranking `'db'` sources
- **Tone borrowing** allows tone digits to function as auxiliary codes when `enable_tone` is enabled

## Frequently Asked Questions

### What is an auxiliary code in Wanxiang?

An auxiliary code is a user-defined supplemental key sequence that follows the main pinyin input (after a delimiter) to disambiguate character selection. According to the `amzxyz/rime_wanxiang` source code, these codes are semicolon-delimited strings stored in dictionary comments or the [`custom/aux_code.txt`](https://github.com/amzxyz/rime_wanxiang/blob/main/custom/aux_code.txt) file, parsed by the [`super_lookup.lua`](https://github.com/amzxyz/rime_wanxiang/blob/main/super_lookup.lua) processor to filter candidates during lookup.

### How do I enable auxiliary codes in my schema?

Add `'aux'` to the `data_source` array in your schema YAML file (e.g., [`wanxiang_pro.schema.yaml`](https://github.com/amzxyz/rime_wanxiang/blob/main/wanxiang_pro.schema.yaml)). The standard schema lists only `['db']` by default, which disables auxiliary processing. When `'aux'` is present, the engine sets `env.has_comment = true` (lines 28-31 of [`super_lookup.lua`](https://github.com/amzxyz/rime_wanxiang/blob/main/super_lookup.lua)) and begins parsing comment fields for auxiliary data.

### Can I use tone numbers as auxiliary codes?

Yes, when `enable_tone` is set to `true` in your configuration, the system extracts tone numbers from dictionary comments and treats them as valid auxiliary inputs. This allows typing pinyin followed by a tone digit (e.g., `shi/5`) to filter characters by their tonal classification, implemented in the tone-filter logic at lines 20-22 of [`super_lookup.lua`](https://github.com/amzxyz/rime_wanxiang/blob/main/super_lookup.lua).

### What is the difference between 'aux' and 'db' data sources?

The `'aux'` source refers to auxiliary codes parsed from dictionary comments or [`aux_code.txt`](https://github.com/amzxyz/rime_wanxiang/blob/main/aux_code.txt), while `'db'` refers to standard reverse-lookup codes from the dictionary database. When both appear in `data_source`, `'aux'` matches take precedence over `'db'` matches because the engine processes sources in array order and buckets results accordingly, ensuring user-defined shortcuts override default reverse lookups.