跳转至

超级处理器 (Super Processor):统一按键调度

super_processor.lua 是万象输入流程中的统一按键处理模块。它在 Rime 的 Processor 阶段集中处理需要结合“当前输入状态、候选状态和按键类型”才能判断的操作。

很多按键并不是固定只有一种用途。数字键既可能用于选词,也可能是日期、金额、Unicode 等功能编码的一部分;单引号既可以作为普通分词符,也可以用于调整长编码的音节边界;退格键既要正常删除编码,又要避免连续删除时越过输入区误删已经上屏的内容。

super_processor.lua 的作用,就是在这些场景之间统一判断按键应该:

  • 交给 Rime 继续处理
  • 写入当前编码
  • 直接执行某项操作
  • 拦截当前按键

当前模块主要整合了以下用户可感知功能:

  1. 以词定字
  2. 数字键与功能编码调度
  3. 小键盘数字行为
  4. 分词循环
  5. 退格保护
  6. 重复输入限制
  7. 声调回退
  8. 特殊模式字母选词

此外,快符和联想空格也在这一 Processor 中完成按键侧的协同处理,但它们已有独立功能说明,本文不再展开内部细节。


一、为什么数字键需要统一调度?

在普通中文输入中,数字键通常用于选择候选词。

但万象同时存在大量需要数字参与编码的功能,例如:

R123
N20260101
U4e00

此时如果数字键仍然直接执行选词,就无法继续完成当前功能编码。

因此,超级处理器并不是简单地规定“数字永远选词”或“数字永远进入编码区”,而是结合当前输入内容与 recognizer/patterns 判断数字键的实际用途。


二、Recognizer 正则兼容转换

为了让 Lua 侧的数字调度直接复用方案中已有的 recognizer/patterns,万象会在初始化时读取这些规则,并转换为 Lua 可以使用的匹配形式。

例如方案中已有:

recognizer:
  patterns:
    unicode: "^U[a-f0-9]+"
    number: "^R[0-9]+[.]?[0-9]*"
    yr1: "^N0[1-9]?0?[1-9]?"

当再次按下数字键时,处理器会先将这个数字临时拼到当前编码尾部,再判断新的完整编码是否仍然符合这些规则。

如果符合,就说明这个数字属于当前功能编码,应当继续进入输入区,而不是执行选词。

可以简单理解为:

当前编码 + 新数字
匹配 recognizer/patterns
命中:数字继续参与编码
未命中:进入普通数字键处理

这不是完整的 PCRE 正则引擎

万象的公共 wanxiang.lua 中提供了专门的兼容转换逻辑,用于处理当前 Recognizer 中常见的正则写法,例如:

  • \d\w\s 等常见转义
  • | 分支
  • ( ... ) 分组
  • ? 可选项
  • ^$ 边界

它的目的不是重新实现一套完整正则引擎,而是让万象现有的 recognizer/patterns 能够被 Lua 按键调度复用。

断言等复杂正则语法不在当前转换范围内。


三、数字键:编码还是选词?

超级处理器对主键盘数字的基本判断顺序可以概括为:

数字键
是否为 T9?
  ├─ 是 → 交给九宫格编码
  └─ 否
当前数字是否仍符合功能编码?
  ├─ 是 → 写入编码区
  └─ 否 → 按候选数字键处理

普通输入

存在候选菜单时,主键盘数字会按当前候选页执行选择。

1 对应当前页第 1 个候选,2 对应第 2 个,以此类推。

如果候选页允许第 10 个候选,0 会被视为第 10 个位置。

功能输入

例如当前输入:

R12

继续按下 3 后:

R123

仍然符合金额数字模式,因此 3 会继续进入编码区。

同理,日期、Unicode 等 Recognizer 规则也可以通过同一套机制参与判断。

T9 九宫格

在 T9 方案中,数字本身就是拼音编码的一部分,因此数字键直接交还给底层拼写流程,不进入普通选词判断。

这也是为什么同一个数字键在 26 键方案和 T9 方案中可以拥有完全不同的行为。


四、小键盘数字行为

右侧数字小键盘可以通过:

super_processor/kp_number_mode

单独设置行为。

当前方案默认:

super_processor:
  kp_number_mode: auto

auto

这是当前万象的默认模式。

  • 正在输入时:小键盘数字进入当前编码区。
  • 没有正在输入时:小键盘数字直接上屏。

因此,在普通文字输入和临时输入数字之间,不需要频繁切换中英文状态。

select

小键盘不由 Lua 强制写入编码,而是继续交给 Rime 原有的数字键处理流程,可用于与普通候选选词行为保持一致。

功能编码优先

无论当前采用哪种小键盘模式,如果“当前编码 + 新数字”能够继续命中 recognizer/patterns,处理器都会优先把数字写入编码区。


五、以词定字 (Select Character)

当一个字不方便直接输入时,可以先打出包含它的词,再从当前候选中提取首字或尾字。

默认配置:

super_processor:
  select_character: "[,]"

对应:

  • [:提交当前选中候选的第一个字
  • ]:提交当前选中候选的最后一个字

例如需要输入“试”,可以先输入“测试”,再按 ]

测试
]

这里提取的是当前选中的候选词,并不固定只能操作第一候选。

自定义按键

既可以直接写字符:

patch:
  "super_processor/select_character": "[,]"

也可以使用 Rime 按键名称:

patch:
  "super_processor/select_character": "bracketleft, bracketright"

如果不需要该功能:

patch:
  "super_processor/select_character": false

六、分词循环 (Super Segmentation)

长编码尤其是 Pro 辅助码输入中,自动音节边界有时并不符合用户预期。

万象允许连续按下手动分词符 ',在若干合理的切分组合之间循环。

以 4 码为例

4 个连续编码可以在以下结构之间切换:

2-2
1-3
3-1

连续按下 ' 时,会依次尝试这些切分方式,再回到原来的状态。

常见切分组合

当前 Lua 内置的主要切分规则包括:

3 码:2-1 / 1-2

4 码:2-2 / 1-3 / 3-1

5 码:2-3 / 3-2

6 码:2-2-2 / 3-3

7 码:2-2-3 / 2-3-2 / 3-2-2

8 码:2-2-2-2 / 2-3-3 / 3-2-3 / 3-3-2

10 码:2-2-2-2-2

对于 大于 10 码的长编码,处理器会动态生成两类切分方式:

按 2 码分组
按 3 码分组

并在两种结果之间继续切换。

第一次单引号仍然是正常分词

第一次按下 ' 时,处理器会先保留正常的手动分词行为。

继续重复按下 ',才开始进入其他分组方式的循环,因此不会改变原本单次分词符的基本使用习惯。

该功能由:

super_processor:
  enable_seg_loop: true

控制。


七、退格保护 (Backspace Limit)

连续按住退格键删除输入码时,一个常见问题是:

正在删除拼音
输入区刚好被清空
退格继续向前传递
开始删除已经上屏的正文

超级处理器会记录连续退格过程中的输入长度变化。

在适用的桌面环境中,当它检测到输入区刚从最后一个字符删到空,并且退格仍在继续时,会拦住继续向前删除的动作。

因此,它主要解决的是长按或连续退格越过编码区边界的问题,而不是改变正常的单次 Backspace 行为。

配置:

patch:
  "super_processor/enable_backspace_limit": true

八、重复输入限制 (Limit Repeated)

当键盘按键卡住、长按或发生异常重复输入时,过长的无效编码会增加不必要的候选计算。

超级处理器提供两层限制。

默认配置:

super_processor:
  limit_repeated: "8,40"

两个数字分别表示:

最大连续重复声母数, 最大允许音节数

1. 连续重复声母

当末尾连续出现超过设定数量的声母时,新的按键会被阻止。

例如超过默认阈值后:

fffffffff

候选区域会提示:

〔已超最大重复声母〕

2. 输入音节数量

处理器还会根据当前候选 Preedit 的分隔情况估算音节数量。

达到设定上限后,会阻止继续输入,并提示:

〔已超最大输入长度〕

如果完全不需要这一限制,可以关闭:

patch:
  "super_processor/limit_repeated": false

九、声调回退 (Tone Fallback)

万象使用:

7 8 9 0

作为声调辅助键时,实际打字过程中并不要求输错声调后先退格删除。

超级处理器会对普通中文输入中的连续声调键序列进行压缩,只保留最后一次输入的声调。

例如:

wang888

会整理为:

wang8

更重要的是:

wang789

会整理为:

wang9

因此如果不确定声调,可以直接连续按:

7 → 8 → 9 → 0

候选会随着最后一个声调键变化,不需要每次先删除前一个数字。

可以把它理解成“声调覆盖”

在普通中文拼音输入中,连续输入多个声调键时,最后一次输入的声调覆盖前面的声调

这比“只压缩相同数字”更准确,也正是声调回退功能的主要使用方式。

为了避免干扰其他数字编码,特殊功能输入、反查、英文候选以及 T9 等场景会避开普通声调压缩逻辑。

配置:

patch:
  "super_processor/enable_tone_fallback": true

十、特殊模式的字母选词 (Letter Selector)

在金额和日期等模式中,数字键本身需要用于继续输入数据,因此不能同时承担候选选择。

超级处理器会在对应模式下启用字母选词。

当前主要针对:

number
Ndate

两类 Tag。

此时:

q w e r t y u i o
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
1 2 3 4 5 6 7 8 9

例如输入金额转换:

R123

出现多个候选后,可以使用 qwe 等字母选择对应候选,而数字键仍然可以继续参与金额输入。

这样可以避免“数字既要输入,又要选词”的按键冲突。


十一、快符与其他按键协同

super_processor.lua 同时承担快符的按键拦截与直接提交。

例如默认:

a/

命中快符规则后,Processor 会直接提交对应符号,并清空当前输入状态。

其中还支持 "repeat" 映射,用于重复最近一次上屏内容。

这部分已经属于独立的 Quick Symbol 功能,具体映射和自定义方法建议参考快符章节,本文只需要知道:

快符之所以能够在输入过程中立即上屏,是因为触发按键在 Processor 阶段已经被识别并处理。


十二、联想空格

enable_predict_space 是与预测候选配合使用的可选功能。

当当前已经没有普通编码,但仍存在联想候选菜单时,按下空格可以直接提交一个空格并结束当前联想状态。

当前万象默认:

super_processor:
  enable_predict_space: false

不使用该行为时保持默认即可。


十三、按键处理为什么不会互相抢占?

这些功能全部放进同一个 Processor 的重要意义,是可以明确规定处理顺序。

当前主要顺序可以概括为:

空格联想
快符
退格保护
以词定字
分词循环
重复输入限制
字母选词
数字键综合处理

例如:

  • 以词定字需要先于普通符号处理确定是否提交当前候选;
  • 字母选词只在指定功能 Tag 中启用,不会全局抢占 q-w-e-r...
  • 数字键最后再根据 T9、Recognizer 和候选菜单决定是编码还是选词;
  • 声调回退也只在适合的普通拼音场景中工作。

因此,这个模块更准确的定位不是“堆在一起的多个快捷键”,而是一个根据输入上下文统一分配按键用途的调度层


十四、Custom 配置

当前方案中的主要默认配置为:

super_processor:
  enable_backspace_limit: true
  enable_seg_loop: true
  enable_tone_fallback: true
  enable_predict_space: false
  kp_number_mode: auto
  limit_repeated: "8,40"
  select_character: "[,]"

如需自定义,可以在 wanxiang.custom.yaml 中 Patch:

patch:
  # 以词定字:[ 取首字,] 取尾字
  "super_processor/select_character": "[,]"

  # 重复限制:最大连续重复声母数, 最大音节数
  "super_processor/limit_repeated": "8,40"

  # 小键盘数字模式
  "super_processor/kp_number_mode": "auto"

  # 功能开关
  "super_processor/enable_backspace_limit": true
  "super_processor/enable_seg_loop": true
  "super_processor/enable_tone_fallback": true
  "super_processor/enable_predict_space": false

不需要以词定字或重复输入限制时,也可以直接关闭:

patch:
  "super_processor/select_character": false
  "super_processor/limit_repeated": false

十五、自定义数字功能时应修改哪里?

如果你自己增加了一个需要数字继续参与编码的功能模式,不需要直接修改 super_processor.lua

应优先在:

recognizer/patterns

中定义对应规则。

例如:

patch:
  "recognizer/patterns/my_number": "^X[0-9]+$"

这样在输入:

X12

后继续按数字时,超级处理器可以复用这条 Recognizer 规则,判断数字仍然属于当前功能编码。

Recognizer 规则应保持在兼容范围内

超级处理器复用的是经过 wanxiang.lua 转换后的 Lua Pattern,并不是直接调用一套完整的 PCRE 正则实现。

因此,自定义规则尽量沿用万象现有 recognizer/patterns 中已经使用的常规写法,不要依赖断言等复杂语法。


总结

super_processor.lua 解决的核心问题不是“增加更多快捷键”,而是处理同一个按键在不同输入状态下应该做什么

它把几个最容易发生职责冲突的输入行为集中起来:

候选操作
数字输入
功能编码
分词调整
声调选择
退格边界
异常重复
特殊模式选词

最终由当前输入状态决定按键是继续传递、进入编码、提交候选还是被拦截。

超级处理器负责的不是单个按键,而是同一个按键在不同输入场景中的正确行为。