├── README.md ├── lua ├── charset.lua ├── date.lua ├── number.lua ├── reverse.lua ├── single_char.lua ├── time.lua └── week.lua └── rime.lua /README.md: -------------------------------------------------------------------------------- 1 | # rime-lua 2 | rime输入框架脚本集合 3 | -------------------------------------------------------------------------------- /lua/charset.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | charset_filter: 滤除含 CJK 扩展汉字的候选项 3 | charset_comment_filter: 为候选项加上其所属字符集的注释 4 | 5 | 本例说明了 filter 最基本的写法。 6 | 7 | 请见 `charset_filter` 和 `charset_comment_filter` 上方注释。 8 | --]] 9 | 10 | -- 帮助函数(可跳过) 11 | local charset = { 12 | ["CJK"] = { first = 0x4E00, last = 0x9FFF }, 13 | ["ExtA"] = { first = 0x3400, last = 0x4DBF }, 14 | ["ExtB"] = { first = 0x20000, last = 0x2A6DF }, 15 | ["ExtC"] = { first = 0x2A700, last = 0x2B73F }, 16 | ["ExtD"] = { first = 0x2B740, last = 0x2B81F }, 17 | ["ExtE"] = { first = 0x2B820, last = 0x2CEAF }, 18 | ["ExtF"] = { first = 0x2CEB0, last = 0x2EBEF }, 19 | ["Compat"] = { first = 0x2F800, last = 0x2FA1F } } 20 | 21 | local function exists(single_filter, text) 22 | for i in utf8.codes(text) do 23 | local c = utf8.codepoint(text, i) 24 | if (not single_filter(c)) then 25 | return false 26 | end 27 | end 28 | return true 29 | end 30 | 31 | local function is_charset(s) 32 | return function (c) 33 | return c >= charset[s].first and c <= charset[s].last 34 | end 35 | end 36 | 37 | local function is_cjk_ext(c) 38 | return is_charset("ExtA")(c) or is_charset("ExtB")(c) or 39 | is_charset("ExtC")(c) or is_charset("ExtD")(c) or 40 | is_charset("ExtE")(c) or is_charset("ExtF")(c) or 41 | is_charset("Compat")(c) 42 | end 43 | 44 | --[[ 45 | filter 的功能是对 translator 翻译而来的候选项做修饰, 46 | 如去除不想要的候选、为候选加注释、候选项重排序等。 47 | 48 | 欲定义的 filter 包含两个输入参数: 49 | - input: 候选项列表 50 | - env: 可选参数,表示 filter 所处的环境(本例没有体现) 51 | 52 | filter 的输出与 translator 相同,也是若干候选项,也要求您使用 `yield` 产生候选项。 53 | 54 | 如下例所示,charset_filter 将滤除含 CJK 扩展汉字的候选项: 55 | --]] 56 | local function charset_filter(input) 57 | -- 使用 `iter()` 遍历所有输入候选项 58 | for cand in input:iter() do 59 | -- 如果当前候选项 `cand` 不含 CJK 扩展汉字 60 | if (not exists(is_cjk_ext, cand.text)) 61 | then 62 | -- 结果中仍保留此候选 63 | yield(cand) 64 | end 65 | --[[ 上述条件不满足时,当前的候选 `cand` 没有被 yield。 66 | 因此过滤结果中将不含有该候选。 67 | --]] 68 | end 69 | end 70 | 71 | 72 | --[[ 73 | 如下例所示,charset_comment_filter 为候选项加上其所属字符集的注释: 74 | --]] 75 | local function charset_comment_filter(input) 76 | -- 使用 `iter()` 遍历所有输入候选项 77 | for cand in input:iter() do 78 | -- 判断当前候选内容 `cand.text` 中文字属哪个字符集 79 | for s, r in pairs(charset) do 80 | if (exists(is_charset(s), cand.text)) then 81 | --[[ 修改候选的注释 `cand.comment` 82 | 因复杂类型候选项的注释不能被直接修改, 83 | 因此使用 `get_genuine()` 得到其对应真实的候选项 84 | --]] 85 | cand:get_genuine().comment = cand.comment .. " " .. s 86 | break 87 | end 88 | end 89 | -- 在结果中对应产生一个带注释的候选 90 | yield(cand) 91 | end 92 | end 93 | 94 | -- 本例中定义了两个 filter,故使用一个表将两者导出 95 | return { filter = charset_filter, 96 | comment_filter = charset_comment_filter } 97 | -------------------------------------------------------------------------------- /lua/date.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | date_translator: 将 `date` 翻译为当前日期 3 | 4 | translator 的功能是将分好段的输入串翻译为一系列候选项。 5 | 6 | 欲定义的 translator 包含三个输入参数: 7 | - input: 待翻译的字符串 8 | - seg: 包含 `start` 和 `_end` 两个属性,分别表示当前串在输入框中的起始和结束位置 9 | - env: 可选参数,表示 translator 所处的环境(本例没有体现) 10 | 11 | translator 的输出是若干候选项。 12 | 与通常的函数使用 `return` 返回不同,translator 要求您使用 `yield` 产生候选项。 13 | 14 | `yield` 每次只能产生一个候选项。有多个候选时,可以多次使用 `yield` 。 15 | 16 | 请看如下示例: 17 | --]] 18 | 19 | local function translator(input, seg) 20 | -- 如果输入串为 `date` 则翻译 21 | if (input == "date") then 22 | --[[ 用 `yield` 产生一个候选项 23 | 候选项的构造函数是 `Candidate`,它有五个参数: 24 | - type: 字符串,表示候选项的类型 25 | - start: 候选项对应的输入串的起始位置 26 | - _end: 候选项对应的输入串的结束位置 27 | - text: 候选项的文本 28 | - comment: 候选项的注释 29 | --]] 30 | yield(Candidate("date", seg.start, seg._end, os.date("%Y年%m月%d日"), "日期")) 31 | --[[ 用 `yield` 再产生一个候选项 32 | 最终的效果是输入法候选框中出现两个格式不同的当前日期的候选项。 33 | --]] 34 | yield(Candidate("date", seg.start, seg._end, os.date("%Y-%m-%d"), "日期")) 35 | end 36 | end 37 | 38 | -- 将上述定义导出 39 | return translator 40 | -------------------------------------------------------------------------------- /lua/number.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | number_translator: 将 `/` + 阿拉伯数字 翻译为大小写汉字 3 | --]] 4 | 5 | local confs = { 6 | { 7 | comment = " 大写", 8 | number = { [0] = "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" }, 9 | suffix = { [0] = "", "拾", "佰", "仟" }, 10 | suffix2 = { [0] = "", "万", "亿", "万亿", "亿亿" } 11 | }, 12 | { 13 | comment = " 小写", 14 | number = { [0] = "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" }, 15 | suffix = { [0] = "", "十", "百", "千" }, 16 | suffix2 = { [0] = "", "万", "亿", "万亿", "亿亿" } 17 | }, 18 | { 19 | comment = " 大寫", 20 | number = { [0] = "零", "壹", "貳", "參", "肆", "伍", "陸", "柒", "捌", "玖" }, 21 | suffix = { [0] = "", "拾", "佰", "仟" }, 22 | suffix2 = { [0] = "", "萬", "億", "萬億", "億億" } 23 | }, 24 | { 25 | comment = " 小寫", 26 | number = { [0] = "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" }, 27 | suffix = { [0] = "", "十", "百", "千" }, 28 | suffix2 = { [0] = "", "萬", "億", "萬億", "億億" } 29 | }, 30 | } 31 | 32 | local function read_seg(conf, n) 33 | local s = "" 34 | local i = 0 35 | local zf = true 36 | 37 | while string.len(n) > 0 do 38 | local d = tonumber(string.sub(n, -1, -1)) 39 | if d ~= 0 then 40 | s = conf.number[d] .. conf.suffix[i] .. s 41 | zf = false 42 | else 43 | if not zf then 44 | s = conf.number[0] .. s 45 | end 46 | zf = true 47 | end 48 | i = i + 1 49 | n = string.sub(n, 1, -2) 50 | end 51 | 52 | return i < 4, s 53 | end 54 | 55 | local function read_number(conf, n) 56 | local s = "" 57 | local i = 0 58 | local zf = false 59 | 60 | n = string.gsub(n, "^0+", "") 61 | 62 | if n == "" then 63 | return conf.number[0] 64 | end 65 | 66 | while string.len(n) > 0 do 67 | local zf2, r = read_seg(conf, string.sub(n, -4, -1)) 68 | if r ~= "" then 69 | if zf and s ~= "" then 70 | s = r .. conf.suffix2[i] .. conf.number[0] .. s 71 | else 72 | s = r .. conf.suffix2[i] .. s 73 | end 74 | end 75 | zf = zf2 76 | i = i + 1 77 | n = string.sub(n, 1, -5) 78 | end 79 | return s 80 | end 81 | 82 | local function translator(input, seg) 83 | if string.sub(input, 1, 1) == "/" then 84 | local n = string.sub(input, 2) 85 | if tonumber(n) ~= nil then 86 | for _, conf in ipairs(confs) do 87 | local r = read_number(conf, n) 88 | yield(Candidate("number", seg.start, seg._end, r, conf.comment)) 89 | end 90 | end 91 | end 92 | end 93 | 94 | return translator 95 | -------------------------------------------------------------------------------- /lua/reverse.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | reverse_lookup_filter: 依地球拼音为候选项加上带调拼音的注释 3 | 4 | 本例说明了环境的用法。 5 | --]] 6 | 7 | -- 帮助函数(可跳过) 8 | local function xform_py(inp) 9 | if inp == "" then return "" end 10 | inp = string.gsub(inp, "([aeiou])(ng?)([1234])", "%1%3%2") 11 | inp = string.gsub(inp, "([aeiou])(r)([1234])", "%1%3%2") 12 | inp = string.gsub(inp, "([aeo])([iuo])([1234])", "%1%3%2") 13 | inp = string.gsub(inp, "a1", "ā") 14 | inp = string.gsub(inp, "a2", "á") 15 | inp = string.gsub(inp, "a3", "ǎ") 16 | inp = string.gsub(inp, "a4", "à") 17 | inp = string.gsub(inp, "e1", "ē") 18 | inp = string.gsub(inp, "e2", "é") 19 | inp = string.gsub(inp, "e3", "ě") 20 | inp = string.gsub(inp, "e4", "è") 21 | inp = string.gsub(inp, "o1", "ō") 22 | inp = string.gsub(inp, "o2", "ó") 23 | inp = string.gsub(inp, "o3", "ǒ") 24 | inp = string.gsub(inp, "o4", "ò") 25 | inp = string.gsub(inp, "i1", "ī") 26 | inp = string.gsub(inp, "i2", "í") 27 | inp = string.gsub(inp, "i3", "ǐ") 28 | inp = string.gsub(inp, "i4", "ì") 29 | inp = string.gsub(inp, "u1", "ū") 30 | inp = string.gsub(inp, "u2", "ú") 31 | inp = string.gsub(inp, "u3", "ǔ") 32 | inp = string.gsub(inp, "u4", "ù") 33 | inp = string.gsub(inp, "v1", "ǖ") 34 | inp = string.gsub(inp, "v2", "ǘ") 35 | inp = string.gsub(inp, "v3", "ǚ") 36 | inp = string.gsub(inp, "v4", "ǜ") 37 | inp = string.gsub(inp, "([nljqxy])v", "%1ü") 38 | inp = string.gsub(inp, "eh[0-5]?", "ê") 39 | return "(" .. inp .. ")" 40 | end 41 | 42 | local function reverse_lookup_filter(input, pydb) 43 | for cand in input:iter() do 44 | cand:get_genuine().comment = cand.comment .. " " .. xform_py(pydb:lookup(cand.text)) 45 | yield(cand) 46 | end 47 | end 48 | 49 | --[[ 50 | 如下,filter 除 `input` 外,可以有第二个参数 `env`。 51 | --]] 52 | local function filter(input, env) 53 | --[[ 从 `env` 中拿到拼音的反查库 `pydb`。 54 | `env` 是一个表,默认的属性有(本例没有使用): 55 | - engine: 输入法引擎对象 56 | - name_space: 当前组件的实例名 57 | `env` 还可以添加其他的属性,如本例的 `pydb`。 58 | --]] 59 | reverse_lookup_filter(input, env.pydb) 60 | end 61 | 62 | --[[ 63 | 当需要在 `env` 中加入非默认的属性时,可以定义一个 init 函数对其初始化。 64 | --]] 65 | local function init(env) 66 | -- 当此组件被载入时,打开反查库,并存入 `pydb` 中 67 | env.pydb = ReverseDb("build/terra_pinyin.reverse.bin") 68 | end 69 | 70 | --[[ 导出带环境初始化的组件。 71 | 需要两个属性: 72 | - init: 指向初始化函数 73 | - func: 指向实际函数 74 | --]] 75 | return { init = init, func = filter } 76 | -------------------------------------------------------------------------------- /lua/single_char.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | single_char_filter: 候选项重排序,使单字优先 3 | --]] 4 | 5 | local function filter(input) 6 | local l = {} 7 | for cand in input:iter() do 8 | if (utf8.len(cand.text) == 1) then 9 | yield(cand) 10 | else 11 | table.insert(l, cand) 12 | end 13 | end 14 | for i, cand in ipairs(l) do 15 | yield(cand) 16 | end 17 | end 18 | 19 | return filter 20 | -------------------------------------------------------------------------------- /lua/time.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | time_translator: 将 `time` 翻译为当前时间 3 | --]] 4 | 5 | local function translator(input, seg) 6 | if (input == "time") then 7 | yield(Candidate("time", seg.start, seg._end, os.date("%H:%M:%S"), " 时间")) 8 | end 9 | end 10 | 11 | return translator 12 | -------------------------------------------------------------------------------- /lua/week.lua: -------------------------------------------------------------------------------- 1 | function week_translator(input, seg) 2 | if (input == "week") then 3 | if (os.date("%w") == "0") then 4 | weekstr = "日" 5 | end 6 | if (os.date("%w") == "1") then 7 | weekstr = "一" 8 | end 9 | if (os.date("%w") == "2") then 10 | weekstr = "二" 11 | end 12 | if (os.date("%w") == "3") then 13 | weekstr = "三" 14 | end 15 | if (os.date("%w") == "4") then 16 | weekstr = "四" 17 | end 18 | if (os.date("%w") == "5") then 19 | weekstr = "五" 20 | end 21 | if (os.date("%w") == "6") then 22 | weekstr = "六" 23 | end 24 | yield(Candidate("qsj", seg.start, seg._end, os.date("%Y年%m月%d日").." 星期"..weekstr, "〔星期〕")) 25 | end 26 | end 27 | return week_translator 28 | -------------------------------------------------------------------------------- /rime.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | librime-lua 样例 3 | 4 | 调用方法: 5 | 在配方文件中作如下修改: 6 | ``` 7 | engine: 8 | ... 9 | translators: 10 | ... 11 | - lua_translator@lua_function3 12 | - lua_translator@lua_function4 13 | ... 14 | filters: 15 | ... 16 | - lua_filter@lua_function1 17 | - lua_filter@lua_function2 18 | ... 19 | ``` 20 | 21 | 其中各 `lua_function` 为在本文件所定义变量名。 22 | --]] 23 | 24 | --[[ 25 | 本文件的后面是若干个例子,按照由简单到复杂的顺序示例了 librime-lua 的用法。 26 | 每个例子都被组织在 `lua` 目录下的单独文件中,打开对应文件可看到实现和注解。 27 | 28 | 各例可使用 `require` 引入。 29 | 如: 30 | ``` 31 | foo = require("bar") 32 | ``` 33 | 可认为是载入 `lua/bar.lua` 中的例子,并起名为 `foo`。 34 | 配方文件中的引用方法为:`...@foo`。 35 | 36 | --]] 37 | 38 | 39 | -- I. translators: 40 | 41 | -- date_translator: 将 `date` 翻译为当前日期 42 | -- 详见 `lua/date.lua`: 43 | date_translator = require("date") 44 | 45 | -- time_translator: 将 `time` 翻译为当前时间 46 | -- 详见 `lua/time.lua` 47 | time_translator = require("time") 48 | 49 | -- number_translator: 将 `/` + 阿拉伯数字 翻译为大小写汉字 50 | -- 详见 `lua/number.lua` 51 | number_translator = require("number") 52 | 53 | -- number_translator: 将 `/` + 阿拉伯数字 翻译为大小写汉字 54 | -- 详见 `lua/number.lua` 55 | week_translator = require("week") 56 | 57 | 58 | -- II. filters: 59 | 60 | -- charset_filter: 滤除含 CJK 扩展汉字的候选项 61 | -- charset_comment_filter: 为候选项加上其所属字符集的注释 62 | -- 详见 `lua/charset.lua` 63 | local charset = require("charset") 64 | charset_filter = charset.filter 65 | charset_comment_filter = charset.comment_filter 66 | 67 | -- single_char_filter: 候选项重排序,使单字优先 68 | -- 详见 `lua/single_char.lua` 69 | single_char_filter = require("single_char") 70 | 71 | -- reverse_lookup_filter: 依地球拼音为候选项加上带调拼音的注释 72 | -- 详见 `lua/reverse.lua` 73 | reverse_lookup_filter = require("reverse") 74 | --------------------------------------------------------------------------------