RIME配置指南
1 写在前面
适合人群
适合人群:寻找适合自己输入法的人、喜欢折腾的人。
基本概念
Rime — 不是一种输入法,而是从常见键盘输入法中提炼出来的抽象输入算法框架。 Rime 涵盖了大多数输入法的「 共性 」部分,所以通过不同配置,Rime 可化身为不同输入法。
Rime 输入法方案 — 要让 Rime 实现某种具体输入法的功能,就需要一些数据来描述其工作方式,即定义该输入法的「 个性 」。例如:「汉语拼音」、「注音」、「五笔字型」 等输入法可凭借 Rime 提供的通用设施、通过设定不同工作参数来实现。
本文的重点就是讲解如何制作一套个性化的输入法方案。
为什么要这么繁琐?
一键就搞掂,则必然选项少、功能单一、可玩性低。
2 准备开工
2.1 Rime 的主要发行版
Rime 是跨平台的输入法软件,本文介绍的 Rime 输入法方案通用于以下发行版:
- 【中州韵】 ibus-rime → Linux / fcitx-rime / fcitx5-rime
- 【小狼毫】 Weasel → Windows
- 【鼠鬚管】 Squirrel → Mac OS X
你可以根据自身操作系统安装最新版的 Rime 输入法 !!!
2.2 Rime 采用文本文件做定制
Rime 的配置文件、输入法方案定义及词典文件,均为特定格式的文本文件。因此,只需要一款够专业的 文本编辑器 ,就可以设计 Rime Schema。 Rime 中的所有文本文件,均要求以 UTF-8 编码,并建议使用 UNIX 换行符(LF)。
鉴于一些文本编辑器会为 UTF-8 编码的文件自动添加 BOM 标记,为防止误将该字符混入文中,请不要从文件的第一行开始正文,建议在第一行的行首以 # 记号起一行注释,如:
1 | # Rime default settings |
当然也可继续以注释行写下方案简介、码表来源、制作者、修订记录等信息,然后再切入正文。
2.3 文本文件的格式
Rime 输入法采用扩展名为「.yaml
」的文本文件,以 YAML 数据描述语言编写。请访问 http://yaml.org/ 了解 YAML 文件格式。下文只对部分语法作简要说明,而将重点放在对 Rime 语义的解读上。
Rime 输入法方案的配置文件中亦会用到「 正则表达式 」实现一些高级功能。您需要掌握这份文件所描述的 Perl 正则表达式语法。
2.4 Rime 的文件分布及作用
除执行程序以外,Rime 还包括多种数据文件。这些数据文件主要存储在两个位置:
- 【中州韵】
/usr/share/rime-data/
- 【小狼毫】
"安装目录\data"
- 【鼠鬚管】
"/Library/Input Methods/Squirrel.app/Contents/SharedSupport/"
- 【中州韵】
ibus
为~/.config/ibus/rime/
fcitx5
为~/.local/fcitx5/rime/
- 【小狼毫】
%APPDATA%\Rime
- 【鼠鬚管】
~/Library/Rime/
共享资料夹 包含默认输入法方案的源文件。这些文件属于 Rime 发行软件的一部份,在访问权限控制较严格的系统上对用户是只读的,因此谢绝软件版本更新以外的任何修改。一旦用户修改这里的文件,很可能影响后续的软件升级或在升级时丢失数据。在执行「部署」操作时,将用到这里的输入法方案源文件、并结合用户定制的内容来编译默认输入法方案。
用户资料夹 则包含为用户准备的内容,如:
- 〔全局配置文件〕
default.yaml
- 〔发行版的配置文件〕
weasel.yaml
- 〔输入法方案的配置文件〕
<方案标识>.schema.yaml
- ※〔安装信息〕
installation.yaml
- ※〔用户状态信息〕
user.yaml
编译输入法方案所产出的二进制文件:
- 〔Rime 棱镜〕
<方案标识>.prism.bin
- 〔Rime 固态词典〕
<词典名>.table.bin
- 〔Rime 反查词典〕
<词典名>.reverse.bin
记录用户写作习惯的文件:
- ※〔用户词典〕
<词典名>.userdb/
或<词典名>.userdb.kct
- ※〔用户词典快照〕
<词典名>.userdb.txt
、<词典名>.userdb.kct.snapshot
见于同步文件夹
以及用户自己设置的:
- ※〔用户对全局设置的定制信息〕
default.custom.yaml
- ※〔用户对默认输入法方案的定制信息〕
<方案标识>.custom.yaml
- ※〔用户自制输入法方案〕及配套的词典源文件
注:以上标有 ※ 号的文件,为用户个性化的重要资料,您在清理文件时要注意备份!
3 详解输入法方案
一套输入法方案,通常包含「方案定义」文件和「词典」文件。「方案定义」文件命名为 <方案标识>.schema.yaml
,是一份包含输入法方案配置信息的 YAML 文件。下面按照板块来介绍该文件的详细设置方法。
3.1 方案描述
文件中需要有这样一组方案描述:
1 | # 以下代码片段节选自 luna_pinyin.schema.yaml |
-
方案名称。
schema/name
字段是显示在 Rime〔方案选单〕中的名称。上例中朙月拼音
即为一个方案名称。 -
方案标识。每一个输入法方案在整个 Rime 中必须有唯一的「方案标识」,即
schema/schema_id
字段。方案标识由小写字母、数字、下划线构成。该标识仅在 Rime 内部使用,并且是方案定义文件名的组成部分,为了兼容不同文件系统,建议不要用大写字母、汉字、空格和其他符号做方案标识。如上例中,输入法方案的标识为luna_pinyin
。 -
方案版本号。方案如做升级,可以通过版本号(
schema/version
)来区分新旧版本。版本号是以「.」分隔的整数(或文字)构成的字符串。如果方案的升级会导致原有用户输入习惯无法在新方案中继续使用,应当更换一个新方案标识以示区别。例如:【仓颉五代】之于【仓颉三代】
、【五笔 98】之于【五笔 86】
,其实都已是互不兼容的输入法。下面是版本号常见的一些形式:
1 | - "1" # 最好加引号表明是字符串! |
- 方案作者。采用字段
schema/author
列出作者和主要贡献者,格式为文字列表:
1 | schema: |
- 方案简介。 采用
schema/description
字段对输入法方案作简要介绍的多行文字。
注意:
上述 schema/schema_id
、schema/version
字段用于在程序中识别输入法方案,而 schema/name
、schema/author
、schema/description
则主要是展示给用户的信息。
3.2 输入法引擎与功能组件
除了 3.1 节
中的方案描述外,方案定义文件中还包含各种功能设置,控制着输入法引擎的工作方式。 Rime 输入法内部的工作流程大致为:
按键消息 → 后台「服务」 → 分配给对应的「会话」 → 交由「方案选单」或「输入引擎」处理……
此处的会话指:多窗口、多线程操作,例如同时与好几位 MM 聊天,会产生好几组会话。每一组会话中都有一部输入引擎来完成从按键序列到文字的转换过程。Rime 支持在不同会话中使用「方案选单」指定的不同输入引擎。「方案选单」本身可以响应一些按键,但大多数时候都是把按键传递给「输入引擎」做处理,也就是说真正做处理的是本节要介绍的「输入引擎」。
输入引擎
内部的工作流程大致如下:
加载输入法方案/预备功能组件 --> 进入处理按键消息、处理按键消息的循环。
在输入引擎中,响应各种按键并产生效果的工作,由不同功能组件分担。例如代码:
1 | # luna_pinyin.schema.yaml |
注:除了示例代码中引用的组件外,尚有
1 | - fluid_editor # ※ 句式编辑器,用于以空格断词、回车上屏的【注音】、【语句流】等输入法方案,替换 express_editor,也可以写作 fluency_editor |
输入引擎把完成具体功能的逻辑拆分为可装卸、组合的部件。在加载输入法方案时,按照配置文件给出的配方挂接所需的各种功能组件、加载各自设置,并准备执行各自的动作。所有功能组件接下来要完成的任务,均由输入引擎收到的某个按键消息触发。
从总体上看,输入引擎以按键消息为输入,其主要输出三个部分的内容:
- 一是对系统按键消息的响应,如反馈给操作系统
接受
还是拒绝
按键消息。 - 二是暂存于输入法、尚未完成处理的内容,会展现在输入法候选窗中。
- 三是要「上屏」的文字,并不是每按一键都有输出。通常中文字会伴随「确认」动作而上屏,有些按键也会直接导致符号上屏,但这要视具体场景而定。
3.2.1 Processors 功能组件
第一类功能组件 processor
,起着比较笼统地、「处理」按键消息的作用。
按键消息依次送往列表中的 processor
,由他给出对按键的三种可能处理意见之一:
- 「收」:即由 Rime 响应该按键;
- 「拒」:回禀操作系统 Rime 不做响应、请对按键做默认处理;
- 「转」:这个按键我不认得、请下一个
processor
继续处理。
优先级依照 processors
列表顺序排列,接收按键者会针对按键消息做处理。
虽然看起来 processor
通过组合可以承担引擎的全部任务,但为了将逻辑继续细分、Rime 又为引擎设置了另外三类功能组件。这些组件都可以访问引擎中的数据对象(即输入上下文),并将各自所做处理的阶段成果存于其中。
processor
最常见的处理,便是将按键所产生的字符记入上下文中的「输入码」序列。
当「输入码」发生变更时,下一组组件 segmentors
开始一轮新的作业。
3.2.2 Segmentors 功能组件
Rime 可对包含文字、数字、符号等不同内容的连续输入码进行识别,将其划分成若干段分而治之。这可以通过对整个输入序列代码的多轮划分操作完成。在每一轮中,所有 segmentor
各自识别起始于某一处、符合特定格式的编码段,并其中最长的编码段作为本轮划分的结果,给出此划分的(一个或多个) segmentor
组件则为该编码段打上「类型标签」;然后从此新编码段的结束位置,开始下一轮划分,直到整个输入码序列划分完毕。
举例来说,【朙月拼音】中,输入码 2012nian\
,划分为三个编码段:2012
( 被打上 number
标签)、nian
( 被打上 abc
标签)、\
(被打上 punct
标签)。
这些标签是初步划分后判定的类型,也可能有一个编码段被打上多个标签的情况。下一个阶段中,translator
会把特定类型的编码段翻译为文字。
3.2.3 Translators 功能组件
顾名思义,translator
完成由编码到文字的翻译。但有几个要点:
- 一、翻译的对象是划分好的一个编码段。
- 二、某个
translator
组件往往只翻译具有特定标签的编码段。 - 三、翻译结果可能有多条,每条结果都会成为展现给用户的候选项。
- 四、同一编码段可由多个
translator
分别翻译,其翻译结果按一定规则合并为候选。 - 五、候选项所对应的编码未必是整个编码段。用拼音敲一个词组时,词组后面继续列出单字候选就是这种情况。
下表给出了内存中编码段、标签和翻译结果的可视化示例:
input | tag | translations
------+--------+-------------------------------------
2012 | number | [ "2012" ], [ "二〇一二" ]
nian | abc | [ "年", "念", "唸",... ], [ "nian" ]
\ | punct | [ "、", "\" ]
一个输入串可被划分为多个编码段、每段编码又可具有多组翻译结果;取各编码段的首选结果连接起来,就是预备上屏的文字「2012 年、
」。可以将上述示例数据视为一篇未定稿的「作文」,输入法界面此时会显示预备上屏的文字「2012 年、
」,并列出最末一个编码段上的候选「、
」及「\
」以供选择。
有两款主力 translator
完成了大部分文字内容翻译工作,其实现方式很不一样:
script_translator
:也叫做r10n_translator
,主要实现罗马字分析法,以「固定音节表」为算法基础,识别输入码的音节构成,推敲排列组合、完成遣词造句。table_translator
:主要实现码表方法,基于规则的动态码表,构成编码空间内一个开放的编码集合。
拼音、注音、方言拼音等皆是以 固定音节表
上的拼写为基础,通过排列组合方式产生编码,故适用罗马字分析法。而仓颉、五笔字型之类则是适用于码表输入法。
如果以码表方式来写拼音输入法方案,是怎样的效果呢?虽然仍可完成输入,但无法完全实现支持简拼、模糊拼音、使用隔音符号的动态调频、智能语句等特性。
以罗马字方式使用码表输入法,则无法实现定长编码顶字上屏、按编码规则构词等功能。在 Rime 各发行版默认输入法方案中,有一款「速成」输入法方案,即是用 script_translator
翻译仓颉码,从而实现全、简码混合的语句输入。
总结起来,这是两种构造新编码的方式:
- 罗马字式输入法方案以一组固定的基本音节码为基础,通过构造新组合而构词;
- 码表式输入法方案则以一定码长为限,通过构造新编码映射而构词。
3.2.4 Filters 功能组件
上一步已经收集到各个编码段的翻译结果,当输入法需要在界面中呈现一页候选项时,就会从最末一个编码段的结果集中挑选,直至取够方案定义文件中指定的页最大候选数
。
在翻译结果进入候选序列之前,Rime 会对从结果集中选出每一条字词,做一组 filter
过滤。多个 filter
串行工作,进入候选序列的是串行过滤最终产出的结果。
filter
可以:
- 改装正在处理的候选项,修改某些属性值:简化字、火星文、菊花文有无有?
- 消除当前候选项,比如检测到重复(由不同
translator
产生)的候选条目 - 插入新的候选项,比如根据已有条目插入关联的结果
- 修改已有的候选序列
3.3 词典文件与码表
3.3.1 词典文件
词典是 translator
的参考书,通常与同名的输入法方案配套使用,如拼音输入法的词典以拼音码查字,仓颉输入法的词典以仓颉码查字。但也可以由若干编码属于同一系统的输入法方案共用,如各种双拼方案都会使用和拼音同样的词典,不仅可以复用码表数据,也可以共享用户录入的自造词。
Rime 的词典文件,命名为 <词典名>.dict.yaml
,包含一份 码表
及对应的 规则说明
。 词典文件的前半部份为 YAML 语法的规则说明
:
1 |
|
解释:
name
: 内部使用的词典名,命名原则与「方案标识」一致,但可以与其配套的输入法方案标识不同;version
: 管理词典的版本,规则同输入法方案定义文件中的版本号;sort
: 词条初始排序方式,可选填by_weight
(按词频高低排序)或original
(保持原码表中的顺序);use_preset_vocabulary
: 填true
或false
,选择是否导入默认词汇表【八股文】。
3.3.2 码表
码表定义了输入法中编码与文字之间的对应关系。码表位于词典文件中 YAML 结束标记之后的部份。其格式为:以 制表符分隔
的值,每行定义一条「文字-编码」的对应关系:
1 | # 单字 |
※注意:
不要 从网页复制以上代码到实际的词典文件中!因为网页里的制表符会被转换成空格,不符合 Rime 词典的格式要求。一些文本编辑器也会将制表符自动转换为空格,请注意检查和设置。
码表部份,除了以上格式的编码行,还可以包含空行(不含任何字符)及注释行(行首为 # 符号)。
- 文字:以制表符分隔的第一个字段是所定义的文字,可以是单字或词组;
- 编码:第二个字段是与文字对应的编码;若该编码由多个「音节」组成,音节之间以
空格
分开; - 频度:第三个字段为可选项,表示该字词的权重频度值(非负整数),或相对于默认权值的百分比(浮点数 %)。在拼音输入法中,往往多音字的若干种读音使用的场合不同,于是指定不同百分比来修正每个读音的使用频度。
词组如果满足以下条件,则可以省去编码字段:
- 词组中每个单字均有编码定义
- 词组中不包含多音字(例:你我),或多音字在该词组中读音的权值超过该多音字全部读音权值的 5%(例:我的)
因为,此时词组的编码可由单字编码的组合推导出来。
反之,则有必要给出词组的编码以消除自动注音的不确定性(例:天地)。
当含有多音字的词组缺少编码字段时,自动注音程序会利用权重百分比高于 5% 的读音进行组合、生成全部可能的注音,如:
「好好地」在编译时自动注音为「hao hao de
」、「hao hao di
」
3.4 设置项速查手册
雪斋的文件 全面而详细解释了输入法方案及词典中各设置项的含义及用法。
3.5 八股文
Rime 有一份名为【八股文】的默认词汇表。
多数输入法方案需要用到一些标准白话文中的通用词汇。为免重复在每份码表中包含这些词汇,减少输入法方案维护成本,Rime 提供了一份默认词汇表及自动编码(注音)的设施。
创作输入法方案时,如果希望完全控制词汇表的内容而不采用【八股文】中的词组,只须直接将词汇编入码表即可。
否则,在词典文件中设置 use_preset_vocabulary: true
将【八股文】导入该词典;
在码表中给出单字码、需要分辨多音字的词组编码、以及该输入法方案特有的词汇,其他交给自动注音来做就好啦。
Rime 默认输入法方案正是利用这份词汇表及自动注音工具,在不牺牲效果及可维护性的前提下、使词典文件压缩到最小的行数。
【八股文】包含从 CC-CEDICT、新酷音等开源项目中整理出来的约二十三万条词汇,其用字及词频数据针对传统汉字做过调整。因此基于这份词汇表产生的输入结果,比较接近以传统汉字行文的实际用法。
为了充分利用【八股文】提供的词汇,自定义的词典应保证单字码表收录了符合 opencc 字形标准的常用字。特别注意,该标准对以下几组异体字的取舍,【八股文】将这些字(包括词组及字频)统一到左边一列的字形。
1 | 为 为 |
请务必在码表中收录左列的单字;并建议收全右列的单字。
输入法词典往往对下列几组字不做严格区分,opencc 则倾向于细分异体字的不同用法。
1 | 喫 吃 |
请尽量在码表中收全以上单字。
部署过程中,未能完成自动注音的字、词会以警告形式出现在日志文件里。如果所报告的字为生僻字、您可以忽略他;如果警告中大量出现某个常用字,那么应该注意到码表里缺失了该字的注音。
3.6 编译输入法方案
将写好的输入法方案布署到 Rime 输入法的过程,称为「编译」:
为查询效率故,输入法工作时不直接加载文本格式的词典源文件,而要在编译过程中,为输入法方案生成专为高速查询设计的「.bin」文件。
编译时程序做以下几件事:
- 将用户的定制内容合併到输入法方案定义中,在用户资料夹生成 .schema.yaml 文件副本;
- 依照输入法方案中指定的词典:求得音节表(不同种编码的集合)、单字表;
- 对词典中未提供编码的词组自动注音,也包括从【八股文】导入的词组;
- 建立按音节编码检索词条的索引,制作 Rime 固态词典;
- 建立按词条检索编码的索引,制作 Rime 反查词典;
- 依照音节表和方案定义中指定的拼写运算规则,制作 Rime 棱镜。
3.7 布署 Rime
初次安装 Rime 输入法,无有任何输入法方案和用户设置。因此安装的最后一个步骤即是把发行版默认的输入法方案和设置文件布署到 Rime 为该用户创建的工作目录,至此 Rime 才成为一部可以发动的输入引擎。
此后无论是修改已有方案的设置,或是添加了新的输入法方案,都需要「重新布署」成功后方可使用户的新设置作用于 Rime 输入法。
〔★〕重新布署的方法是:
- 【小狼毫】从开始菜单选择「重新部署」;或当开启托盘图标时,在托盘图标上右键选择「重新布署」;
- 【鼠鬚管】在系统语言文字选单中选择「重新布署」;
- 【中州韵】点击输入法状态栏(或 IBus 菜单)上的 ⟲ (Deploy) 按钮;
- 早于 ibus-rime 0.9.2 的版本:删除用户资料夹的
default.yaml
之后、执行ibus-daemon -drx
重载 IBus
4 定制指南
Rime 输入法方案,将 Rime 输入法的设置整理成完善的、可分发的形式。但并非一定要创作新的输入法方案,才可以改变 Rime 的行为。当用户需要对 Rime 中的各种设置做小幅的调节,最直接、但不完全正确的做法是:编辑用户资料夹中那些 .yaml 文件。
这一方法有弊端:
- 当 Rime 软件升级时,也会升级各种设置档、默认输入法方案。用户编辑过的文件会被覆写为更高版本,所做调整也便丢失了。
- 即使在软件升级后再手动恢复经过编辑的文件,也会因设置档的其他部分未得到更新而失去本次升级新增和修复的功能。
因此,对于随 Rime 发行的设置档及默认输入法方案,推荐的定制方法是:
创建一个文件名的主体部份( 即「.」之前的部分 )与要定制的文件相同、次级扩展名( 即扩展名「.yaml」之前的部分 )为 .custom
的定制文件,如:default.yaml
--> default.custom.yaml
。 该文件应当用 patch
关键字定义一组设置的「补丁」,Rime 会对源文件中的相同设置进行替换、或写入新的设置项。例如:
1 | patch: |
以下这些例子,另载于 《定制指南》,其中所介绍的知识和技巧,覆盖了不少本文未讨论的细节,应当会对创作新的输入法方案有所启发。
重要!创作了新的输入法方案,最后一步就是在「方案选单」里启用他。
拼写运算
应该算是 Rime 输入法最主要的独创技术。
概括来说就是将方案中的编码通过规则映射到一组全新的拼写形式!
也就是说能让 Rime 输入法方案在不修改码表的情况下、适应不同的输入习惯。
拼写运算能用来:
- 改革拼写法
- 将编码映射到基于同一音系的其他拼写法,如注音、拼音、普通话罗马字相互转换
- 重定义注音键盘、双拼方案
- 实现简拼查询
- 在音节表上灵活地定义模糊音规则
- 实现音节自动纠错
- 变换回显的输入码或提示码,如将输入码显示为字根、注音符号、带声调标注的罗马字
给力吗?
[[★这里|SpellingAlgebra]] 有介绍拼写运算的专题文章。
综合演练
如果你安装好了 Rime 却不会玩,就一步一步跟我学吧。
本系列课程每个步骤的完整代码可由此查阅:
https://github.com/lotem/rimeime/tree/master/doc/tutorial
【一】破空中出鞘
Hello, Rime!
第一个例子,总是最简单的(也是最傻的)。
1 | # Rime schema |
起首几行是注释。而后只有一组必要的方案描述信息。
这一课主要练习建立格式正确的 YAML 文件。
- 要点一,让你的文本编辑器以 UTF-8 编码保存该文件;
- 要点二,注意将
schema:
之下的三行代码以空格缩进——我的习惯是用两个空格——而 不要 用 Tab 字符来缩进。
缩进表示设置项所属的层次。在他处引用到此文件中的设置项,可分别以 schema/schema_id
, schema/name
, schema/version
来指称。
我现在把写好的方案文件命名为 hello.schema.yaml
,丢进用户资料夹,只要这一个文件就妥了;
然后,启用他。有些版本会有「方案选单设置」这个界面,在那里勾选【大家好】这个方案即可。若无有设置界面,则按照上文《定制方案选单》一节来做。
好运!我已建立了一款名为【大家好】的新方案!虽然他没有实现任何效果、按键仍会像无有输入法一样直接输出西文。
开始改装
为了处理字符按键、生成输入码,本例向输入引擎添加两个功能组件。
以下代码仍是 ID 为 hello
的新款输入法方案,但增加了 schema/version
的数值。
以后每个版本,都以前一个版本为基础改写,引文略去无有改动的部分,以突出重点。
1 | # ... |
fluid_editor
将字符按键记入输入上下文,fallback_segmentor
将输入码连缀成一段。于是重新布署后,按下字符键不再直接上屏,而显示为输入码。
你会发现,该输入法只是收集了键盘上的可打印字符,并于按下空格、回车键时令输入码上屏。
现在就好似写输入法程序的过程中,将将取得一小点成果,还有很多逻辑未实现。不同的是,在 Rime 输入法方案里写一行代码,顶 Rime 开发者所写的上百上千行。因此我可以很快地组合各种逻辑组件、搭建出心里想的输入法。
创建候选项
第二版的【大家好】将键盘上所有字符都记入输入码,这对整句输入有用,但是时下流行输入法只处理编码字符、其他字符直接上屏的形式。为了对编码字符做出区分,以下改用 speller
+ express_editor
的组合取代 fluid_editor
:
1 | # ... |
speller
默认只接受小写拉丁字母作为输入码。
试试看,输入其他字符如大写字母、数字、标点,都会直接上屏。并且如果已经输入了编码时,下一个直接上屏的字符会将输入码顶上屏。
再接着,创建一个最简单的候选项——把编码串本身作为一个选项。故而会提供这个选项的新组件名叫 echo_translator
。
1 | # ... |
至此,【大家好】看上去与一个真正的输入法形似啦。只是还不会打出「大家好」哇?
编写词典
那就写一部词典,码表中设置以 hello
作为短语「大家好」的编码:
1 | # Rime dictionary |
※注意: 不要 从网页复制以上代码到实际的词典文件!因为网页里制表符被转换成空格从而不符合 Rime 词典要求的格式。一些文本编辑器也会将使用者输入的制表符自动转换为空格,请注意检查和设置。
同时修改方案定义:
1 | #... |
工作流程是这样的:
speller
将字母键加入输入码序列abc_segmentor
给输入码打上标签abc
table_translator
把带有abc
籤的输入码以查表的方式译为中文table_translator
所查的码表在translator/dictionary
所指定的词典里
现在可以敲 hello
而打出「大家好」。完工!
实现选字及换页
等一下。
记得 hello
词典里,还有个编码叫做 bye
。敲 bye
,Rime 给出「再见」、「再会」两个候选短语。
这时敲空格键,就会打出「再见」;那么怎样打出「再会」呢?
大家首先想到的方法,是:打完编码 bye
,按 1
选「再见」,按 2
选「再会」。
可是现在按下 2
去,却是上屏「再见」和数字「2」。可见并没有完成数字键选字的处理,而是将数字同其他符号一样做了顶字上屏处理。
增加一部 selector
,即可实现以数字键选字。
1 | schema: |
selector
除了数字键,还响应前次页、上下方向键。因此选择第二候选「再会」,既可以按数字 2
,又可以按方向键「↓」将「再会」高亮、再按空格键确认。
navigator
处理左右方向键、Home
、End
键,实现移动插入点的编辑功能。有两种情况需要用到他:一是发现输入码有误需要定位修改,二是缩小候选词对应的输入码的范围、精准地编辑新词组。
接下来向词典添加一组重码,以检验换页的效果:
1 |
|
默认每页候选数为 5,输入 weekday
,显示「星期一」至「星期五」。再敲 Page_Down
显示第二页后选词「星期六、星期日」。
输出中文标点
1 | schema: |
这次的修改,要注意 punctuator
, punct_segmentor
, punct_translator
相对于其他组件的位置。
punctuator/import_preset
告诉 Rime 使用一套默认的符号表。他的值 default
可以换成其他名字如 xxx
,则 Rime 会读取 xxx.yaml
里面定义的符号表。
如今再敲 hello.
就会得到「大家好。」
用符号键换页
早先流行用 -
和 =
这一对符号换页,如今流行用 ,
和 .
。
在第六版中「,」「。」是会顶字上屏的。现在要做些处理以达到一键两用的效果。
Rime 提供了 key_binder
组件,他能够在一定条件下,将指定按键绑定为另一个按键。对于本例就是:
- 当展现候选菜单时,句号键(
period
)绑定为向后换页(Page_Down
) - 当已有(向后)换页动作时,逗号键(
comma
)绑定为向前换页(Page_Up
)
逗号键向前换页的条件之所以比句号键严格,是为了「,」仍可在未进行换页的情况下顶字上屏。
经过 key_binder
的处理,用来换页的逗号、句号键改头换面为前、后换页键,从而绕过 punctuator
,最终被 selector
当作换页来处理。
最终的代码如下:
1 | schema: |
【二】修炼之道
与【大家好】这个方案不同。以下一组示例,主要演示如何活用符号键盘,以及罗马字转写式输入。
改造键盘
莫以为【大家好】是最最简单的输入法方案。码表式输入法,不如「键盘式」输入法来得简单明快!
用 punctuator
这一套组件,就可实现一款键盘输入法:
1 | # Rime schema |
对,所谓「键盘输入法」,就是按键和字直接对应的输入方式。
这次,不再写 punctuator/import_preset
这项,而是自订了一套符号表。
鸹!原来 punctuator
不单可以用来打出标点符号;还可以重定义空格以及全部 94 个可打印 ASCII 字符(码位 0x20 至 0x7e)。
在符号表代码里,用对应的 ASCII 字符表示按键。记得这些按键字符要放在引号里面,YAML 才能够正确解析喔。
示例代码表演了两种符号的映射方式:一对一及一对多。一对多者,按键后符号不会立即上屏,而是……嘿嘿,自己体验吧 :-)
关于代码里 symtable
的一点解释:
这是 YAML 的一种语法,&symtable
叫做「锚点标签」,给紧随其后的内容起个名字叫 symtable
;
*symtable
则相当于引用了 symtable
所标记的那段内容,从而避免重复。
Rime 里的符号有「全角」、「半角」两种状态。本方案里暂不作区分,教 half_shape
、full_shape
使用同一份符号表。
大写数字键盘
灵机一动,不如利用「全、半角」模式来区分「大、小写」中文数字!
1 | schema: |
先来定义状态开关:0
态改「半角」为「小写」,1
态改「全角」为「大写」。
这样一改,再打开「方案选单」,方案「数字之道」底下就会多出个「小写→大写」的选项,每选定一次、状态随之反转一次。
接着给 half_shape
、full_shape
定义不同的符号表:
1 | punctuator: |
哈,调出选单切换一下大小写,输出的字全变样!酷。
但是要去选单切换,总不如按下 Shift
就全都有了:
1 | punctuator: |
于是在「小写」态,只要按 Shift
+ 数字键即可打出大写数字。
用了几下,发现一处小小的不满意:敲 $
这个键,可选的符号有五个之多。想要打出殴元、英镑符号只得多敲几下 $
键使想要的符号高亮;但是按上、下方向键并没有效果,按符号前面标示的数字序号,更是不仅上屏了错误的符号、还多上屏一个数字——
这反映出两个问题。一是 selector
组件缺席使得选字、移动选字光标的动作未得到响应。立即加上:
1 | # ... |
因为要让 punctuator
来转换数字键,所以 selector
得放在他后头。
好。二一个问题还在:无法用数字序号选字。为解决这个冲突,改用闲置的字母键来选字:
1 | # ... |
完工。
罗马字之道
毕竟,键盘上只有 47 个字符按键、94 个编码字符,对付百十个字还管使。可要输入上千个常用汉字,嫌键盘式输入的编码空间太小,必得采用多字符编码。
罗马字,以拉丁字母的特定排列作为汉语音节的转写形式。一个音节代表一组同音字,再由音节拼写组合成词、句。
凡此单字(音节)编码自然连用而生词、句的输入法,皆可用 script_translator
组件完成基于音节码切分的智能词句转换。他有个别名 r10n_translator
——r10n
为 romanization
的简写。但不限于「拼音」、「注音」、「双拼」、「粤拼」等一族基于语音编码的输入法:形式相似者,如「速成」,虽以字形为本,亦可应用。
现在来把【数字之道】改成拼音→中文数字的变换。
1 | schema: |
符号表里,把小写字母、数字键都空出来了。小写字母用来拼音,数字键用来选重。重点是本次用了 script_translator
这组件。与 table_translator
相似,该组件与 translator/dictionary
指名的词典相关联。
编制词典:
1 | # Rime dictionary |
※注意: 不要 从网页复制以上代码到实际的词典文件!因为网页里制表符被转换成空格从而不符合 Rime 词典要求的格式。一些文本编辑器也会将使用者输入的制表符自动转换为空格,请注意检查和设置。
码表里给出了一个「示例」规格的小字集。其中包含几组重码字。
要诀 sort: by_weight
意图是不以码表的顺序排列重码字,而是比较字频。那字频呢?没写出来。
要诀 use_preset_vocabulary: true
用在输入法方案需要支持输入词组、而码表中词组相对匮乏时。编译输入法方案期间引入 Rime 默认的【八股文】词汇——及词频资料!这就是码表中未具字频的原因。
使用【八股文】,要注意码表所用的字形是否与该词汇表一致。八股文的词汇及词频统计都遵照 opencc 繁体字形标准。
如果缺少单字的编码定义,自然也无法导入某些词汇。所以本方案只会导入这个数字「小字集」上的词汇。
用拼写运算定义简码
如今有了一款专门输入数字的拼音输入法。比一比昇阳拼音、朙月拼音和地球拼音,还有哪里不一样?
很快我发现敲 xingqiwu
或 xingqiw
都可得到来自【八股文】的词组「星期五」,这很好。可是敲 xqw
怎会不中呢?
原来 script_translator
罗马字中译的方法是,将输入码序列切分为音节表中的拼写形式,再按音节查词典。不信你找本词典瞧瞧,是不是按完整的拼音(注音)编排的。Rime 词典也一样。并没有 xqw
这样的检索码。
现在我要用 Rime 独门绝活「拼写运算」来定义一种「音序查字法」。令 x
作 xing
的简码,q
作数字之道所有音节中起首为 q
者的简码,即略代音节 qi
与 qian
。
「汉语拼音」里还有三个双字母的声符,zh, ch, sh
也可做简码。
添加拼写运算规则:
1 | schema: |
如此 Rime 便知,除了码表里那些拼音,还有若干简码也是行得通的拼写形式。再输入 xqw
,Rime 将他拆开 x'q'w
,再默默对应到音节码 xing'qi'wan
、xing'qi'wu
、xing'qian'wan
等等,一翻词典就得到了一个好词「星期五」,而其他的组合都说不通。
现在有无有悟到,罗马字转写式输入法与码表式输入法理念上的不同?
哈,做中了。试试看 sss,sss,sssss,sssss
却好像不是我要的「四是四,十是十,十四是十四,四十是四十」……
好办。如果某些词汇在方案里很重要,【八股文】又未收录,那么,请添加至码表:
1 |
|
善哉。演示完毕。当然休想就此把 Rime 全盘掌握了。一本《指南书》,若能让读者入门,我止说「善哉〜」
再往后,就只有多读代码,才能见识到各种新颖、有趣的玩法。
【三】最高武艺
〔警告〕最后这部戏,对智力、技术功底的要求不一般。如果读不下去,不要怪我、不要怀疑自己的智商!
即使跳过本节书也无妨,只是不可忽略了下文《关于调试》这一节!(重要哇……)
请检查是否:
- ※ 已将前两组实例分析透彻
- ※ 学习完了《拼写运算》
- ※ 知道双拼是神码
- ※ 预习 Rime 默认输入法方案之【朙月拼音】
设计一款【智能 ABC 双拼】输入法方案做练习!
1 | # Rime schema |
完毕。
这是一道大题。通过改造拼写法而创作出新的输入法方案。
【四】标准库
如果需要制作完全属于自己的输入法方案,少不了要了解 Rime 的标准库。此时,请客倌品读《Rime 方案制作详解》。更多新意,就在你的笔下!
关于调试
如此复杂的输入法方案,很可能需要反覆调试方可达到想要的结果。
请于试验时及时查看日志中是否包含错误信息。日志文件位于:
- 【中州韵】
/tmp/rime.ibus.*
- 【小狼毫】
%TEMP%\rime.weasel.*
- 【鼠鬚管】
$TMPDIR/rime.squirrel.*
- 各发行版的早期版本
用户资料夹/rime.log
按照日志的级别分为 INFO / 信息、WARNING / 警告、ERROR / 错误。
后两类应重点关注,如果新方案部署后不可用或输出与设计不一致,原因可能在此。
没有任何错误信息,就是不好使,有可能是码表本身的问题,比如把码表中文字和编码两列弄颠倒了——Rime 等你输入由汉字组成的编码,然而键盘没有可能做到这一点(否则也不再需要输入法了)。
后续有计划为输入法方案创作者开发名为「拼写运算调试器」的工具,能够较直观地看到每一步拼写运算的结果。有助于定义双拼这样大量使用拼写运算的方案。
东风破
「东风破早梅,向暖一枝开。」
构想在 Rime 输入软件完善后,能够连结汉字字形、音韵、输入法爱好者的共同兴趣,形成稳定的使用者社羣,搭建一个分享知识的平台。
【东风破】,定义为配置管理器及 Rime 输入法方案仓库,是广大 Rime 用家分享配置和输入法方案的平台。
Rime 是一款强调个性的输入法。
Rime 不要定义输入法应当是哪个样、而要定义输入法可以玩出哪些花样。
Rime 不可能通过默认更多的输入法方案来满足玩家的需求;真正的玩家一定有一般人想不到的高招。
未来一定会有,【东风破】(注:现已投入运行),让用家轻松地找到最新、最酷、最适合自己的 Rime 输入法方案。