Skip to content
骆言 edited this page Sep 20, 2022 · 62 revisions

脚本开发指南

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

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

例子:输入今天的日期

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

编写代码

输入日期,需要用到 translator。我们希望在输入“date”之后,在输入法候选框中得到今天日期。我们在 RIME 的用户目录下新建一个 rime.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 目录下,还有更多的例子。配合其中的注释并稍加修改,就可以满足大部分的日常需求。

编程接口

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

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 所指对象有多种形式:

--- 简化形式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 所指对象有多种形式:

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

--- 简化形式2
function filter(input, env)
...
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 所指对象有多种形式:

--- 简化形式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 所指对象有多种形式:

--- 简化形式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
context Context
active_engine

方法:

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

Context

输入编码上下文。

可通过 env.engine.context 获得。

属性:

属性名 类型 解释
composition Composition
input string 正在输入的编码字符串
caret_pos number 脱字符位置
commit_notifier Notifier
select_notifier Notifier
update_notifier Notifier
delete_notifier Notifier
option_update_notifier OptionUpdateNotifier 选项改变通知,使用 connect 方法接收通知
property_update_notifier PropertyUpdateNotifier
unhandled_key_notifier KeyEventNotifier

方法:

方法名 参数 返回值 解释
commit 上屏选中的候选词
get_commit_text
get_script_text
get_preedit
is_composing boolean 是否有未上屏的编码
has_menu boolean 是否有候选词(选项菜单)
get_selected_candidate Candidate 返回选中的候选词
push_input(text) text: string 插入指定的text编码字符串
pop_input(num) num: number boolean 删除num指定数量的编码字符串
delete_input
clear 清空正在输入的编码字符串
select
confirm_current_selection
delete_current_selection
confirm_previous_selection
reopen_previous_selection
clear_previous_segment
reopen_previous_segment
clear_non_confirmed_composition
refresh_non_confirmed_composition
set_option
get_option
set_property
get_property
clear_transient_options

Composition

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

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

属性:

属性名 类型 解释

方法:

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

e.g.

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

Schema

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

属性:

属性名 类型 解释
schema_id string 方案编号
schema_name string 方案名称
config Config 方案配置
page_size number 每页候选词数
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: string boolean 1. 存在且为 ConfigList 返回 true
2. 存在且不为 ConfigList 返回 false
3. 不存在返回 true ⚠️
is_map
get_bool
get_int
get_double
get_string(conf_path) conf_path: string string 根据配置路径 conf_path 获取配置的字符串值
set_bool
set_int
set_double
set_string
get_item
set_item
get_value
get_list(conf_path) conf_path: string ConfigList 不存在或不为 ConfigList 时返回 nil
get_map(conf_path) conf_path: string ConfigMap 不存在或不为 ConfigMap 时返回 nil
set_value
set_list
set_map
get_list_size

ConfigMap

属性:

属性名 类型 解释
size number
type string 如:“kMap”
element

方法:

方法名 参数 返回值 解释
set
get(key) key: string ConfigItem
get_value(key) key: string ConfigValue
has_key boolean
clear
empty boolean
keys table

ConfigList

属性:

属性名 类型 解释
size number
type string 如:“kList”
element

方法:

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

ConfigValue

属性:

属性名 类型 解释
value string
type string 如:“kScalar”
element

方法:

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

ConfigItem

属性:

属性名 类型 解释
type string 1. "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。

属性:

属性名 类型 解释
keycode number 按键值
modifier

方法:

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

KeySequence

属性:

属性名 类型 解释

方法:

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

Candidate

候选词

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

  1. type: 标识
  2. start: 分词开始
  3. end: 分词结束
  4. quality: 权重

属性:

属性名 类型 解释
type string 候选词来源标记,如:“user_phrase”、“phrase”、“punct”、“simplified”
1. "user_phrase": 用户字典(随用户输入而更新)
2. "phrase"
3. "punct": 来源有两 "engine/segmentors/punct_segmentor" 或 "symbols:/patch/recognizer/patterns/punct"
4. "simplified"
5. ...
start number
_start number 编码开始位置,如:“好” 在 “ni hao” 中的 _start=2
_end number 编码结束位置,如:“好” 在 “ni hao” 中的 _end=5
quality number 结果展示排名权重
text string 候选词内容
comment string
preedit string 得到当前候选词的编码

方法:

方法名 参数 返回值 解释
get_dynamic_type string 1. "Phrase": Phrase
2. "Simple": SimpleCandidate
3. "Shadow": ShadowCandidate
4. "Uniquified": UniquifiedCandidate
5. "Other"
get_genuine
get_genuines
to_shadow_candidate
to_uniquified_candidate
append

SimpleCandidate

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: (可选)

UniquifiedCandidate

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

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

Segmentation

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

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

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

属性:

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

方法:

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

e.g.

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

Segment

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

构造方法:Segment(start_pos, end_pos)

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

属性:

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

方法:

方法名 参数 返回值 解释
clear
close
reopen
has_tag
get_candidate_at
get_selected_candidate

Set

构造方法:Set(table)

  1. table: 列表

属性:

属性名 类型 解释

方法:

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

Menu

属性:

属性名 类型 解释

方法:

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

ReverseDb

反查

构造方法:ReverseDb(file_name)

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

属性:

属性名 类型 解释

方法:

方法名 参数 返回值 解释
lookup

ReverseLookup

构造方法:ReverseLookup(dict_name)

  1. dict_name: 字典名。 如: luna_pinyin

属性:

属性名 类型 解释

方法:

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

Component

属性:

属性名 类型 解释

方法:

方法名 参数 返回值 解释
Processor 如:Component.Processor(env.engine,"","ascii_composer")
Segmentor
Translator
Filter

Notifier

接收通知

通知类型:

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

属性:

属性名 类型 解释

方法:

方法名 参数 返回值 解释
connect(func) func: function

e.g.

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

OptionUpdateNotifier

同 Notifier

e.g.

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

PropertyUpdateNotifier

同 Notifier

e.g.

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

KeyEventNotifier

同 Notifier

e.g.

-- 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#%E9%97%9C%E6%96%BC%E8%AA%BF%E8%A9%A6

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

属性:

属性名 类型 解释

方法:

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

rime_api

属性:

属性名 类型 解释

方法:

方法名 参数 返回值 解释
get_rime_version string librime 版本
get_shared_data_dir string 程序目录\data
get_user_data_dir string 用户目录
get_sync_dir string 用户资料同步目录
get_distribution_name string 如:“小狼毫”
get_distribution_code_name string 如:“Weasel”
get_distribution_version string 发布版本号
get_user_id
Clone this wiki locally