Skip to content

脚本开发指南

librime-lua 是 RIME 输入法引擎的一个插件,它为用户提供了使用 lua 脚本语言扩展输入法的能力。通过 lua,您可以实现输入任意动态短语(如日期时间、大写数字、计算器)、自由重排/过滤候选词,甚至云输入等,单纯使用配置文件难以做到的,灵活多样的功能。本文将介绍本项目的配置和编程方法。

要理解本项目的工作原理,需先了解 RIME 功能组件的基本概念与工作流程,见RIME文档。简而言之,librime-lua 提供了 processor、segmentor、translator 和 filter 这四个功能组件的开发接口。下面首先通过一个例子来说明完整的流程,然后再详细介绍各个组件的编程接口。

例子:输入今天的日期

我们通过“输入今天的日期”这个例子,来说明开发定制的流程。一共分三步:编写代码、配置方案、重新部署。

编写代码

输入日期,需要用到 translator。我们希望在输入“date”之后,在输入法候选框中得到今天日期。我们在 RIME 的用户目录下新建一个 rime.lua 文件,这是整个 lua 脚本的总入口。在文件中录入以下内容:

lua
function date_translator(input, seg)
   if (input == "date") then
      --- Candidate(type, start, end, text, comment)
      yield(Candidate("date", seg.start, seg._end, os.date("%Y年%m月%d日"), " 日期"))
   end
end

上面实现了一个叫做 date_translator 的函数。它的输入是 inputseg,分别记录了 translator 需要翻译的内容和它在输入串中的位置。这个函数会判断输入的是否是“date”。如是则生成一个内容为今天日期的候选项。候选项的构造函数是 Candidate。这个函数如注释所说有五个参数:类型、开始位置、结束位置、候选内容和候选注释。类型可以是任意字符串,这里用了"date";开始、结束位置一般用 seg.startseg._end 就可以,它表示了我们要将整个待翻译的输入串替换为候选内容;候选内容是使用 lua 的库函数生成的日期;候选注释一般会在输入候选框中以灰色展示在候选内容旁边。候选项生成以后是通过 yield 发出的。yield 在这里可以简单理解为“发送一个候选项到候选框中”。一个函数可以 yield 任意次,这里我们只有一个候选项所以只有一个 yield

配置方案

我们已经编写了输入日期的 translator,为了让它生效,需要修改输入方案的配置文件。以明月拼音为例,找到 luna_pinyin.schema.yaml,在 engine/translators 中加入一项 lua_translator@date_translator,如下:

engine:
  ...
  translators:
    - lua_translator@date_translator
    ...

这样就完成了配置。它表示从 lua 执行环境中找到名为 date_translator 的全局实例,将它作为一种 translator 安装到引擎之中。其他类型的组件配置类推,分别叫做 lua_processor lua_segmentor lua_filter

重新部署

以上完成了所有开发和配置。点击“重新部署”,输入"date",就可以看到候选框中出现了今天的日期。

在本项目的 sample 目录下,还有更多的例子。配合其中的注释并稍加修改,就可以满足大部分的日常需求。

模块化

到目前为止,我们的代码完全集中在 rime.lua 中。本节说明 librime-lua 对模块化的支持。模块化是指把脚本分门别类,放到独立的文件中,避免各自的修改互相干扰,也方便把自己的作品分享给他人使用。仍然以 date_translator 为例。

分离脚本内容

首先需要把原来写在 rime.lua 的脚本搬运到独立的文件中。删掉 rime.lua 原有的内容后,在 RIME 的用户目录下新建一个 lua 目录,在 lua 下再建立一个 date_translator.lua 文件,录入以下内容:

lua
local function translator(input, seg)
   if (input == "date") then
      --- Candidate(type, start, end, text, comment)
      yield(Candidate("date", seg.start, seg._end, os.date("%Y年%m月%d日"), " 日期"))
   end
end

return translator

可以看到主要内容与之前一致,但有两点不同:

  • 使用 local。lua 脚本的变量作用域默认是全局的。如果不同模块的变量或函数正好用了相同的名字,就会导致互相干扰,出现难以排查的问题。因此,尽量使用 local 把变量作用域限制在局部。
  • 新增 return。librime-lua 是借助 lua 的 require 机制实现模块加载。引用模块时,整个文件被当作一个函数执行,返回模块内容。在这里返回的是一个 translator 组件。

引用模块

我们已经建立了一个名叫 date_translator 的模块。接下来是引用。

旧版 librime-lua

如果使用的是较旧的 librime-lua,仍然需要在 rime.lua 内输入以下内容:

lua
date_translator = require("date_translator")

前一个 date_translator 是全局变量名,后一个是模块名。librime-lua 将 RIME 的用户目录和 RIME 共享目录下的 lua 目录加入了模块搜索路径,因此本句的意义是搜索 date_translator 模块,并将返回的组件绑定到同名的全局变量上。这样就可以在输入方案配置文件中使用了,方法与之前一致。

新版 librime-lua

如果使用的是最新的 librime-lua,则可以进一步避免修改 rime.lua,达到真正的模块化。

方法是将输入方案配置文件中直接写入以下内容:

engine:
  ...
  translators:
    - lua_translator@*date_translator
  ...

与之前的区别是第一个 @ 之后多了一个 *。这个星号表示后面的名字是模块名而不是全局变量名。当遇到星号时,librime-lua 会在内部先使用 require 机制加载模块,然后将其返回值作为 RIME 组件加载到输入法框架中。

配方补丁

以上我们实现了 lua 脚本的模块化。但为引用组件,仍需修改输入配方。为使对配方文件修改的模块化,请见RIME配方补丁

编程接口

本节详细介绍编程接口。需注意随着项目的开发,以下文档可能是不完整或过时的,敬请各位参与贡献文档。

lua_translator

lua_translator 提供了 translator 的开发接口。它在配置文件中的配置语法有两种,分别是:

engine:
  translators:
    - lua_translator@lua_object_name
    - lua_translator@lua_object_name@name_space

其中 lua_object_name 是 lua 环境中的一个全局对象,可能是一个 lua function 或者一个 lua table。后面的 name_space 当出现时是 translator 名字,与 RIME 组件配置中出现的 @ 意义一致。

lua_object_name 所指对象有多种形式:

lua
--- 简化形式1
function translator(input, seg)
...
end

--- 简化形式2
function translator(input, seg, env)
...
end

--- 完整形式
{
   init = function (env) ... end,
   func = function (input, seg, env) ... end,
   fini = function (env) ... end
}

简化形式是 lua function,此函数即为 translator 的工作函数。无返回值。可以通过 yield 发送 Candidate 对象。 参数:

  • input:字符串,为待翻译串。
  • segSegment 对象。
  • env:lua table 对象。预设 enginename_space 两个成员,分别是 Engine 对象和前述 name_space 配置字符串。

完整形式是 lua table,其中 func 与简化形式意义相同。initfini 分别在 lua_translator 构造与析构时调用。

lua_filter

lua_filter 提供了 filter 的开发接口。它在配置文件中的配置语法有两种,分别是:

engine:
  filters:
    - lua_filter@lua_object_name
    - lua_filter@lua_object_name@name_space

其中 lua_object_name 是 lua 环境中的一个全局对象,可能是一个 lua function 或者一个 lua table。后面的 name_space 当出现时是 filter 名字,与 RIME 组件配置中出现的 @ 意义一致。

lua_object_name 所指对象有多种形式:

lua
--- 简化形式1
function filter(input)
...
end

--- 简化形式2
function filter(input, env)
...
end

--- 简化形式3
function filter(input, env, cands)
...
end

--- 完整形式
{
   init = function (env) ... end,
   func = function (input, env) ... end,
   fini = function (env) ... end,
   tags_match = function (segment, env) ... end  --- 可选
}

简化形式是 lua function,此函数即为 filter 的工作函数。无返回值。可以通过 yield 发送 Candidate 对象。 参数:

  • inputTranslation 对象,为待过滤的 Candidate 流。
  • env:lua table 对象。预设 enginename_space 两个成员,分别是 Engine 对象和前述 name_space 配置字符串。

完整形式是 lua table,其中 func 与简化形式意义相同。initfini 分别在 lua_filter 构造与析构时调用。tags_match 出现时覆盖 filter 的 TagsMatch 方法。

lua_processor

lua_processor 提供了 processor 的开发接口。它在配置文件中的配置语法有两种,分别是:

engine:
  processors:
    - lua_processor@lua_object_name
    - lua_processor@lua_object_name@name_space

其中 lua_object_name 是 lua 环境中的一个全局对象,可能是一个 lua function 或者一个 lua table。后面的 name_space 当出现时是 processor 名字,与 RIME 组件配置中出现的 @ 意义一致。

lua_object_name 所指对象有多种形式:

lua
--- 简化形式1
function processor(key_event)
...
end

--- 简化形式2
function processor(key_event, env)
...
end

--- 完整形式
{
   init = function (env) ... end,
   func = function (key_event, env) ... end,
   fini = function (env) ... end
}

简化形式是 lua function,此函数即为 processor 的工作函数。返回值为整数:

  • 0 表示 kRejected 字符上屏,结束 processors 流程
  • 1 表示 kAccepted 字符不上屏,结束 processors 流程
  • 2 表示 kNoop 字符不上屏,交给下一个 processor

参数:

  • key_eventKeyEvent 对象,为待处理的按键。
  • env:lua table 对象。预设 enginename_space 两个成员,分别是 Engine 对象和前述 name_space 配置字符串。

完整形式是 lua table,其中 func 与简化形式意义相同。initfini 分别在 lua_processor 构造与析构时调用。

lua_segmentor

lua_segmentor 提供了 segmentor 的开发接口。它在配置文件中的配置语法有两种,分别是:

engine:
  segmentors:
    - lua_segmentor@lua_object_name
    - lua_segmentor@lua_object_name@name_space

其中 lua_object_name 是 lua 环境中的一个全局对象,可能是一个 lua function 或者一个 lua table。后面的 name_space 当出现时是 segmentor 名字,与 RIME 组件配置中出现的 @ 意义一致。

lua_object_name 所指对象有多种形式:

lua
--- 简化形式1
function segmentor(segmentation)
...
end

--- 简化形式2
function segmentor(segmentation, env)
...
end

--- 完整形式
{
   init = function (env) ... end,
   func = function (segmentation, env) ... end,
   fini = function (env) ... end
}

简化形式是 lua function,此函数即为 segmentor 的工作函数。返回值为bool(true: 交由下一个segmentor处理;false: 终止segmentors处理流程)。 参数:

  • segmentationSegmentation 对象。
  • env:lua table 对象。预设 enginename_space 两个成员,分别是 Engine 对象和前述 name_space 配置字符串。

完整形式是 lua table,其中 func 与简化形式意义相同。initfini 分别在 lua_segmentor 构造与析构时调用。

对象接口

librime-lua 封装了 librime C++ 对象到 lua 中供脚本访问。此部分文档待整理。

Engine

可通过 env.engine 获得。

属性:

属性名类型解释
schema
contextContext
active_engine

方法:

方法名参数返回值解释
process_key
compose
commit_text(text)text: string上屏 text 字符串
apply_schema

Context

输入编码上下文。

可通过 env.engine.context 获得。 ( *W : 觸發 Compose() )

属性:

属性名类型解释
compositionComposition
inputstring*W 正在输入的编码字符串
caret_posnumber*W 脱字符位置
commit_notifierNotifier
select_notifierNotifier
update_notifierNotifier
delete_notifierNotifier
option_update_notifierOptionUpdateNotifier选项改变通知,使用 connect 方法接收通知
property_update_notifierPropertyUpdateNotifier
unhandled_key_notifierKeyEventNotifier

方法:

方法名参数返回值解释
commit上屏选中的候选词
get_commit_textstring
get_script_textstring按音节分割
get_preeditPreedit
is_composingboolean是否有未上屏的编码
has_menuboolean是否有候选词(选项菜单)
get_selected_candidateCandidate返回选中的候选词
push_input(text)text: string*W 在caret_pos位置插入指定的text编码字符串,caret_pos跟隨右移
pop_input(num)num: numberboolean*W 在caret_pos位置往左删除num指定数量的编码字符串,caret_pos跟隨左移
delete_input
clear*W 清空正在输入的编码字符串
select(index)index: numberboolean选择下标候选词(下标0开始)
confirm_current_selection
delete_current_selectionboolean是否有候选词(this doesn't mean anything is deleted for sure)
https://github.com/rime/librime/.../src/context.cc#L125-L137
confirm_previous_selection
reopen_previous_selection *W
clear_previous_segment
reopen_previous_segment *W
clear_non_confirmed_composition
refresh_non_confirmed_composition *W
set_option
get_option
set_property(key, value)key: string
value: string
可以用于存储上下文信息(可配合 property_update_notifier 使用)
get_property(key)key: stringstring
clear_transient_options

Preedit

属性:

属性名类型解释
text
caret_pos
sel_start
sel_end

方法:

方法名参数返回值解释

Composition

上下文组成的“作品”。(通过此对象,可间接获得“菜单menu”、“候选词candidate”、“片段segment”相关信息)

可通过 env.engine.context.composition 获得。

属性:

属性名类型解释

方法:

方法名参数返回值解释
emptyboolean是否有候选词(是否有menu)
backSegment获得 Segment 对象
pop_back
push_back
has_finished_composition
get_promptstring获得 Segment 的 prompt 字符串(prompt 为活动编码左边的字符串提示)
toSegmentation

e.g.

lua
local composition = env.engine.context.composition

if(not composition:empty()) then
  -- 获得 Segment 对象
  local segment = composition:back()

  -- 获得选中的候选词下标
  local selected_candidate_index = segment.selected_index

  -- 获取 Menu 对象
  local menu = segment.menu

  -- 获得(已加载)候选词数量
  local loaded_candidate_count = menu:candidate_count()
end

Segmentation

在分词处理流程 Segmentor 中存储 Segment 并把其传递给 Translator 进行下一步翻译处理。

作为第一个参数传入以注册的 lua_segmentor。

或通过以下方法获得:

lua
local composition = env.engine.context.composition
local segmentation = composition:toSegmentation()

librime 定义 - https://github.com/rime/librime/blob/5c36fb74ccdff8c91ac47b1c221bd7e559ae9688/src/segmentation.cc#L28

属性:

属性名类型解释
inputstring活动中的原始(未preedit)输入编码

方法:

方法名参数返回值解释
emptyboolean是否包含 Segment
backSegment查看添加的 Segment
pop_backSegment查看最近添加的 Segment,并将其从 Segmentation 中移除
reset_length
add_segment(seg)seg: Segment添加 Segment
(librime v1.7.3:如果已包含 Segment,仅将新 Segment.tags 合并入旧 Segment.tags)
forward
trim清空其中的 Segment
has_finished_segmentationboolean
get_current_start_positionnumber
get_current_end_positionnumber
get_current_segment_lengthnumber
get_confirmed_positionnumber属性 input 中已经确认(处理完)的长度
(通过判断 status 为 "kSelected" 以上的 Segment 的 _end 来判断 confirmed_position)
https://github.com/rime/librime/.../src/segmentation.cc#L127

e.g.

txt
                         | 你hao‸a
env.engine.context.input | "nihaoa"
Segmentation.input       | "nihao"
get_confirmed_position   | 2

Segment

分词片段。触发 translator 时作为第二个参数传递给注册好的 lua_translator。

或者以下方法获得: (在 filter 以外的场景使用)

lua
local composition =  env.engine.context.composition
if(not composition:empty()) then
  local segment = composition:back()
end

构造方法:Segment(start_pos, end_pos)

  1. start_pos: 开始下标
  2. end_pos: 结束下标

属性:

属性名类型解释
statusstring1. kVoid - (默认)
2. kGuess
3. kSelected - 大于此状态才会被视为选中
4. kConfirmed
start
_start
_end
length
tagsSet标签
menu
selected_index
promptstring输入编码旁的提示字符串
image

方法:

方法名参数返回值解释
clear
close
reopen
has_tag
get_candidate_at(index)index: number 下标0开始Candidate
get_selected_candidateCandidate

Schema

方案。可以通过 env.engine.schema 获得。

构造方法:Schema(schema_id)

  1. schema_id: string

属性:

属性名类型解释
schema_idstring方案编号
schema_namestring方案名称
configConfig方案配置
page_sizenumber每页候选词数
select_keys

方法:

方法名参数返回值解释

Config

(方案的)配置。可以通过 env.engine.schema.config 获得

属性:

属性名类型解释

方法:

方法名参数返回值解释
load_from_file
save_to_file
is_null(conf_path)conf_path: string
is_value
is_list(conf_path)conf_path: stringboolean1. 存在且为 ConfigList 返回 true
2. 存在且不为 ConfigList 返回 false
3. 不存在返回 true ⚠️
is_map
get_bool
get_int
get_double
get_string(conf_path)conf_path: stringstring根据配置路径 conf_path 获取配置的字符串值
set_bool
set_int
set_double
set_string(path, str)path: string
str: string
get_item
set_item(path, item)path: string
item: ConfigItem
get_value
get_list(conf_path)conf_path: stringConfigList不存在或不为 ConfigList 时返回 nil
get_map(conf_path)conf_path: stringConfigMap不存在或不为 ConfigMap 时返回 nil
set_value(path, value)path: string
value: ConfigValue
set_list
set_map
get_list_size

ConfigMap

属性:

属性名类型解释
sizenumber
typestring如:“kMap”
element轉換成ConfigItem

方法:

方法名参数返回值解释
set
get(key)key: stringConfigItem
get_value(key)key: stringConfigValue
has_keyboolean
clear
emptyboolean
keystable

ConfigList

属性:

属性名类型解释
sizenumber
typestring如:“kList”
element轉換成ConfigItem

方法:

方法名参数返回值解释
get_at(index)index: number
(下标从0开始)
ConfigItem
get_value_at(index)index: number
(下标从0开始)
ConfigValue
set_at
append
insert
clear
empty
resize

ConfigValue

继承 ConfigItem

构造方法:ConfigValue(str)

  1. str: 值(可通过 get_string 获得)

属性:

属性名类型解释
valuestring
typestring如:“kScalar”
element轉換成ConfigItem

方法:

方法名参数返回值解释
get_bool
get_int
get_double
set_bool
set_int
set_double
get_string
set_string

ConfigItem

属性:

属性名类型解释
typestring1. "kNull"
2. "kScalar"
3. "kList"
4. "kMap"
empty

方法:

方法名参数返回值解释
get_value当 type == "kScalar" 时使用
get_list当 type == "kList" 时使用
get_map当 type == "kMap" 时使用

KeyEvent

按键事件对象。

当按键被按下、释放(release)、保持时均会产生按键事件(KeyEvent),触发 processor,此时 KeyEvent 会被作为第一个参数传递给已注册的 lua_processor。

属性:

属性名类型解释
keycodenumber按键值
modifier

方法:

方法名参数返回值解释
shiftboolean触发事件时,是否被按压
ctrlboolean触发事件时,是否被按压
altboolean触发事件时,是否被按压
caps
(CapsLk)
boolean
superboolean
releaseboolean当事件为“release”时为 true,否则为 false
repr
(representation)
string当非 release 时,为按键字符,如:“1”、“a”、“space”、“Shift_L”
当 release 时,为Releas+按键字符,如:“Release+space”
eq(key)
(equal)
key: KeyEventboolean两个 KeyEvent 是否“相等”
lt(key)
(less than)
key: KeyEventboolean对象小于参数时为 true

KeySequence

属性:

属性名类型解释

方法:

方法名参数返回值解释
parse
repr
toKeyEvent

Candidate

(简单的)候选词。(选中后不会更新用户字典)

构造方法:Candidate(type, start, end, text, comment)

  1. type: 标识
  2. start: 分词开始
  3. end: 分词结束
  4. text: 候选词内容
  5. comment: 註解

属性:

属性名类型解释
typestring候选词来源标记,如:“user_phrase”、“phrase”、“punct”、“simplified”
1. "user_phrase": 用户字典(随用户输入而更新)
2. "phrase"
3. "punct": 来源有两 "engine/segmentors/punct_segmentor" 或 "symbols:/patch/recognizer/patterns/punct"
4. "simplified"
5. "completion": 编码未完整。see https://github.com/rime/librime/.../src/rime/gear/table_translator.cc#L77
6...
startnumber
_startnumber编码开始位置,如:“好” 在 “ni hao” 中的 _start=2
_endnumber编码结束位置,如:“好” 在 “ni hao” 中的 _end=5
qualitynumber结果展示排名权重
textstring候选词内容
commentstring註解(name_space/comment_format)
image
preeditstring得到当前候选词的编码(一般空格分开圆音,如:"ni hao")(name_space/preedit_format)

方法:

方法名参数返回值解释
get_dynamic_typestring1. "Phrase": Phrase
2. "Simple": SimpleCandidate (即 Candidate)
3. "Shadow": ShadowCandidate
4. "Uniquified": UniquifiedCandidate
5. "Other"
get_genuineCandidate
get_genuinestable: <number, Candidate>
to_shadow_candidate
to_uniquified_candidate
append

UniquifiedCandidate

ShadowCandidate

衍生扩展词

https://github.com/hchunhui/librime-lua/pull/162

ShadowCandidate(cand,type,text,comment)類似 simplifier 的作法

构造方法:ShadowCandidate(cand, type, text, comment, inherit_comment)

  1. cand
  2. type
  3. text
  4. comment
  5. inherit_comment: (可选)

Phrase

候选词。(选择后会更新相应的用户字典)

构造方法:Phrase(memory, type, start, end, entry)

  1. memory: Memory
  2. type: string
  3. start: number
  4. end: number
  5. entry: DictEntry

属性:

属性名类型解释
language
type
start
_start
_end
quality
text
comment
preedit
weight
code
entry

方法:

方法名参数返回值解释
toCandidate

UniquifiedCandidate

https://github.com/hchunhui/librime-lua/pull/162

UniqifiedCandidate(cand,type,text,comment) 類似 uniqifier 的作法

Set

构造方法:Set(table)

  1. table: 列表

ex: local set_tab = Set({'a','b','c','c'}) # set_tab = {a=true,b=true, c=true}

属性:

属性名类型解释

方法:

方法名参数返回值解释
empty
__index
__add
__sub
__mul
__set

属性:

属性名类型解释

方法:

方法名参数返回值解释
add_translation
prepare
get_candidate_at
candidate_count
empty

Opencc

构造方法:Opencc(filename)

  1. filename: string

属性:

属性名类型解释

方法:

方法名参数返回值解释
convert

ReverseDb /ReverseLookup

反查

构造方法:ReverseDb(file_name)

  1. file_name: 反查字典文件路径。 如: build/terra_pinyin.reverse.bin

e.g.

lua
local pyrdb = ReverseDb("build/terra_pinyin.reverse.bin")

属性:

属性名类型解释

方法:

方法名参数返回值解释
lookup

ReverseLookup (ver #177)

构造方法:ReverseLookup(dict_name)

  1. dict_name: 字典名。 如: luna_pinyin

属性:

属性名类型解释

方法:

方法名参数返回值解释
lookup(key)key: stringstring如:ReverseLookup("luna_pinyin"):lookup( "百" ) == "bai bo"
lookup_stems

CommitEntry

继承 DictEntry

属性:

属性名类型解释

方法:

方法名参数返回值解释
get

DictEntry

构造方法:DictEntry()

librime 定义:https://github.com/rime/librime/blob/ae848c47adbe0411d4b7b9538e4a1aae45352c31/include/rime/impl/vocabulary.h#L33

属性:

属性名类型解释
textstring词,如:“好”
commentstring剩下的编码,如:preedit "h", text "好", comment "~ao"
preeditstring如:“h”
weightnumber如:“-13.998352335763”
commit_countnumber如:“2”
custom_codestring词编码(根据特定规则拆分,以" "(空格)连接,如:拼音中以音节拆分),如:“hao”、“ni hao”
remaining_code_lengthnumber(预测的结果中)未输入的编码,如:preedit "h", text "好", comment "~ao", remaining_code_length “2”
codeCode

方法:

方法名参数返回值解释

Code

构造方法:Code()

属性:

属性名类型解释

方法:

方法名参数返回值解释
push(inputCode)rime::SyllableId
(librime中定义的类型)
printstring

Memory

提供来操作 dict(字典、固态字典、静态字典)和 user_dict(用户字典、动态字典)的接口

构造方法:Memory(engine, schema, name_space)

  1. engine: Engine
  2. schema: Schema
  3. name_space: string (可选,默认为空)

e.g.

lua
env.mem = Memory(env.engine,env.engine.schema)  --  ns= "translator"
-- env.mem = Memory(env.engine,env.engine.schema, env.name_space )  
-- env.mem = Memory(env.engine,Schema("cangjie5") ) --  ns= "translator-
-- env.mem = Memory(env.engine,Schema("cangjie5"), "translator")

构造流程:https://github.com/rime/librime/blob/3451fd1eb0129c1c44a08c6620b7956922144850/src/gear/memory.cc#L51

  1. 加载 schema 中指定的字典(dictionary)
    (包括:"{name_space}/dictionary"、"{name_space}/prism"、"{name_space}/packs")
  2. 加在 schema 中指定的用户字典(user_dict)
    (前提:{name_space}/enable_user_dict 为 true)
    (包括:"{name_space}/user_dict" 或 "{name_space}/dictionary")
    (后缀:"*.userdb.txt")
  3. 添加通知事件监听(commit_notifier、delete_notifier、unhandled_key_notifier)

属性:

属性名类型解释

方法:

方法名参数返回值解释
dict_lookup(input, predictive, limit)input: string
predictive: boolean
limit: number
boolean 是否有结果查询
user_lookup(input, predictive)input: string
predictive: boolean
memorize(callback)callback: function
(回调参数:CommitEntry)
当用户字典候选词被选中时触发回调。
decode(code)code: Codetable: <number, string>
iter_dict配合 for ... end 获得 DictEntry
iter_user配合 for ... end 获得 DictEntry
update_userdict(entry, commits, prefix)entry: DictEntry
commits: number
prefix: string
boolean

使用案例:https://github.com/hchunhui/librime-lua/blob/67ef681a9fd03262c49cc7f850cc92fc791b1e85/sample/lua/expand_translator.lua#L32

e.g.

lua
-- 遍历

local input = "hello"
local mem = Memory(env.engine,env.engine.schema) 
mem:dict_lookup(input, true, 100)
-- 遍历字典
for entry in mem:iter_dict() do
 print(entry.text)
end

mem:user_lookup(input, true)
-- 遍历用户字典
for entry in mem:iter_user() do
 print(entry.text)
end
lua
-- 监听 & 更新

env.mem = Memory(env.engine, env.engine.schema) 
env.mem:memorize(function(commit) 
  for i,dictentry in ipairs(commit:get()) do
    log.info(dictentry.text .. " " .. dictentry.weight .. " " .. dictentry.comment .. "")
    -- memory:update_userdict(dictentry,0,"") -- do nothing to userdict
    -- memory:update_userdict(dictentry,1,"") -- update entry to userdict
    -- memory:update_userdict(dictentry,-1,"") -- delete entry to userdict
    --[[
      用户字典形式如:
      ```txt
      # Rime user dictionary
      #@/db_name	luna_pinyin.userdb
      #@/db_type	userdb
      #@/rime_version	1.5.3
      #@/tick	693
      #@/user_id	aaaaaaaa-bbbb-4c62-b0b0-ccccccccccc
      wang shang 	网上	c=1 d=0.442639 t=693
      wang shi zhi duo shao 	往事知多少	c=1 d=0.913931 t=693
      wang xia 	往下	c=1 d=0.794534 t=693
      wei 	未	c=1 d=0.955997 t=693
      ```
    --]]
  end
end

Projection

可以用于处理 candidate 的 comment 的转换

构造:Projection()

属性:

属性名类型解释

方法:

方法名参数返回值解释
load(rules)rules: ConfigList-加载转换规则
apply(str,[ret_org_str])str: string, ret_org_str: boolstring转换字符串: 預設轉換失敗返回 空字串, ret_org_str: true 返回原字串

使用参考: https://github.com/hchunhui/librime-lua/pull/102

lua
local config=env.engine.schema.config
-- load ConfigList  form  path
local proedit_fmt_list = conifg:get_list("translastor/preedit_format")
-- create Projection obj
local p1=Projection()
-- load convert rules
p1:load(proedit_fmt_list)
-- convert string
local str_raw = "abcdefg"
local str_preedit = p1:apply(str)

Component

調用 processor,segmentor,translator,filter 組件,可在lua script中再重組。 參考範例: librime-lua/sample/lua/component_test.lua

属性:

属性名类型解释

方法:

方法名参数返回值解释
Processorengine,[schema,]name_space,prescriptionProcessor如:Component.Processor(env.engine,"","ascii_composer"), Component.Processor(env.engine,Schema('cangjie5'),"",'ascii_composer)(使用Schema: cangjie5 config)
Segmentor同上Segmentor
Translator同上Translator`Component.Translator(env.engine,'','table_translator')
Filter同上FilterComponent.Filter(env.engine,'','uniquility')

Processor

属性:

属性名类型解释
name_spacestring取出instance name_space #212

方法:

方法名参数返回值解释
process_key_eventKeyEvent0-20:kReject 1:kAccepted 2:Noop,參考engine.cc

Segmentator

属性:

属性名类型解释
name_spacestring取出instance name_space #212

方法:

方法名参数返回值解释
proceedSegmentationbool參考engine.cc

Translator

属性:

属性名类型解释
name_spacestring取出instance name_space #212

方法:

方法名参数返回值解释
querystring: input, segmetTranslation 參考engine.cc

Filter

属性:

属性名类型解释
name_spacestring取出instance name_space #212

方法:

方法名参数返回值解释
applytranslation,candsTranslation參考engine.cc

Notifier

接收通知

通知类型:

  1. commit_notifier
  2. select_notifier
  3. update_notifier
  4. delete_notifier

属性:

属性名类型解释

方法: notifier connect

方法名参数返回值解释
connect(func[,group])func: function grup: intNotifier 新增 group 依 gorup 順序通知 0,1,...connect(func) 排在最後)

e.g.

lua
-- ctx: Context
env.engine.context.commit_notifier:connect(function(ctx)
  -- your code ...
end)

OptionUpdateNotifier

同 Notifier

e.g.

lua
-- ctx: Context
-- name: string
env.engine.context.option_update_notifier:connect(function(ctx, name)
  -- your code ...
end)

PropertyUpdateNotifier

同 Notifier

e.g.

lua
-- ctx: Context
-- name: string
env.engine.context.property_update_notifier:connect(function(ctx, name)
  -- your code ...
end)

KeyEventNotifier

同 Notifier

e.g.

lua
-- ctx: Context
-- key: KeyEvent
env.engine.context.unhandled_key_notifier:connect(function(ctx, key)
  -- your code ...
end)

Connection

属性:

属性名类型解释

方法:

方法名参数返回值解释
disconnect

log

记录日志到日志文件

日志位置:https://github.com/rime/home/wiki/RimeWithSchemata#關於調試

  • 【中州韻】 /tmp/rime.ibus.*
  • 【小狼毫】 %TEMP%\rime.weasel.*
  • 【鼠鬚管】 $TMPDIR/rime.squirrel.*
  • 各發行版的早期版本 用戶資料夾/rime.log

属性:

属性名类型解释

方法:

方法名参数返回值解释
info
warning
error

rime_api

属性:

属性名类型解释

方法:

方法名参数返回值解释
get_rime_versionstringlibrime 版本
get_shared_data_dirstring程序目录\data
get_user_data_dirstring用户目录
get_sync_dirstring用户资料同步目录
get_distribution_namestring如:“小狼毫”
get_distribution_code_namestring如:“Weasel”
get_distribution_versionstring发布版本号
get_user_id

CommitRecord

CommitRecord : 參考 librime/src/rime/ engine.cc commit_history.h

  • commit_text => {type: 'raw', text: string}
  • commit => {type: cand.type, text: cand.text}
  • reject => {type: 'thru', text: ascii code}

属性:

属性名类型解释
typestring
textstring

CommitHistory

engine 在 commit commit_text 會將 資料存入 commit_history, reject且屬於ascii範圍時存入ascii 此api 除了可以取出 CommitRecord 還可以在lua中推入commit_record 參考: librime/src/rime/gear/history_translator

属性:

属性名类型解释
sizenumbermax_size <=20

方法:

方法名参数返回值解释
push(KeyEvent),(composision,ctx.input)(cand.type,cand.text)推入 CommitRecord
backCommitRecord取出最後一個 CommitRecord
to_tablelua table of CommitRecord轉出 lua table of CommitRecord
iterreverse_iter
reprstring格式 [type]text[type]text....
latest_textstring取出最後一個CommitRecord.text
emptybool
clearsize=0
pop_back移除最後一個CommitRecord
lua
-- 將comit cand.type == "table" 加入 translation
local T={}
function T.func(inp,seg,env)
  if not seg.has_tag('histroy') then return end

  for r_iter,commit_record in context.commit_history:iter() do
    if commit_record.type=="table" then
       yield( Candidate( commit_record.type,seg.start,seg._end,commit_record.text,"commit_history"))
    end
  end
end
return T

DbAssessor

支援 leveldb:query(prefix_key)

methods: obj of LevelDb

方法名参数返回值解释
resetnonebooljump to begin
jumpprefix of key:stringbooljump to first of prefix_key
iternoneiter_func,self範例: for k,v in da:iter() do print(k,v) end

LevelDb ( 不可用於已開啓的userdb, 專用於 librime-lua key-value db)

便於調用大型資料庫且不佔用 lua 動態記憶

新建 leveldb

方法名参数返回值解释
LevelDbdbname:stringobj of LevelDblocal db = LevelDb('ecdict') -- opendb :user_data_dir/ecdict

物件方法

方法名参数返回值解释
opennonebool
open_read_onlynonebool禁用 earse ,update
closenonebool
loadednonebool
queryprefix of key:stringobj of DbAccessor查找 prefix key
fetchkey:stringvalue:string or nil查找 value
updatekey:string,value:stringbool
erasekey:stringbool

範例:

lua
 -- 建議加入 db_pool 可避免無法開啓已開啓DB
 _db_pool= _db_pool or {}
 local function wrapLevelDb(dbname,mode)
   _db_pool[dbname] = _db_pool[dbname] or LevelDb(dbname)
   local db = _db_pool[dbname]
   if db and not db:loaded() then
      if mode then
        db:open()
      else 
        db:open_read_only()
      end
      return db
   end
 end
 
 local db = wrapLevelDb('ecdict') -- open_read_only
 -- local db = wrapLevelDb('ecdictu',true) -- open
 local da = db:query('the') -- return obj of DbAccessor
 for k,v in da:iter() do print(k,v) end

Released under the MIT License.