forked from iDvel/rime-ice
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rime.lua
304 lines (288 loc) · 10.7 KB
/
rime.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
-- Rime Lua 扩展 https://github.com/hchunhui/librime-lua
-- 文档 https://github.com/hchunhui/librime-lua/wiki/Scripting
-------------------------------------------------------------
-- 日期时间
-- 提高权重的原因:因为在方案中设置了大于 1 的 initial_quality,导致 rq sj xq dt ts 产出的候选项在所有词语的最后。
function date_translator(input, seg, env)
local config = env.engine.schema.config
local date = config:get_string(env.name_space .. "/date") or "rq"
local time = config:get_string(env.name_space .. "/time") or "sj"
local week = config:get_string(env.name_space .. "/week") or "xq"
local datetime = config:get_string(env.name_space .. "/datetime") or "dt"
local timestamp = config:get_string(env.name_space .. "/timestamp") or "ts"
-- 日期
if (input == date) then
local cand = Candidate("date", seg.start, seg._end, os.date("%Y-%m-%d"), "")
cand.quality = 100
yield(cand)
local cand = Candidate("date", seg.start, seg._end, os.date("%Y/%m/%d"), "")
cand.quality = 100
yield(cand)
local cand = Candidate("date", seg.start, seg._end, os.date("%Y.%m.%d"), "")
cand.quality = 100
yield(cand)
local cand = Candidate("date", seg.start, seg._end,
os.date("%Y 年 ") .. tostring(tonumber(os.date("%m"))) .. os.date(" 月 %d 日"), "")
cand.quality = 100
yield(cand)
end
-- 时间
if (input == time) then
local cand = Candidate("time", seg.start, seg._end, os.date("%H:%M"), "")
cand.quality = 100
yield(cand)
local cand = Candidate("time", seg.start, seg._end, os.date("%H:%M:%S"), "")
cand.quality = 100
yield(cand)
end
-- 星期
if (input == week) then
local weakTab = {'日', '一', '二', '三', '四', '五', '六'}
local cand = Candidate("week", seg.start, seg._end, "星期" .. weakTab[tonumber(os.date("%w") + 1)], "")
cand.quality = 100
yield(cand)
local cand = Candidate("week", seg.start, seg._end, "礼拜" .. weakTab[tonumber(os.date("%w") + 1)], "")
cand.quality = 100
yield(cand)
local cand = Candidate("week", seg.start, seg._end, "周" .. weakTab[tonumber(os.date("%w") + 1)], "")
cand.quality = 100
yield(cand)
end
-- ISO 8601/RFC 3339 的时间格式 (固定东八区)(示例 2022-01-07T20:42:51+08:00)
if (input == datetime) then
local cand = Candidate("datetime", seg.start, seg._end, os.date("%Y-%m-%dT%H:%M:%S+08:00"), "")
cand.quality = 100
yield(cand)
local cand = Candidate("time", seg.start, seg._end, os.date("%Y%m%d%H%M%S"), "")
cand.quality = 100
yield(cand)
end
-- 时间戳(十位数,到秒,示例 1650861664)
if (input == timestamp) then
local cand = Candidate("datetime", seg.start, seg._end, os.time(), "")
cand.quality = 100
yield(cand)
end
-- -- 输出内存
-- local cand = Candidate("date", seg.start, seg._end, ("%.f"):format(collectgarbage('count')), "")
-- cand.quality = 100
-- yield(cand)
-- if input == "xxx" then
-- collectgarbage()
-- local cand = Candidate("date", seg.start, seg._end, "collectgarbage()", "")
-- cand.quality = 100
-- yield(cand)
-- end
end
-------------------------------------------------------------
-- 以词定字
-- https://github.com/BlindingDark/rime-lua-select-character
-- 删除了默认按键,需要在 key_binder 下设置
local function utf8_sub(s, i, j)
i = i or 1
j = j or -1
if i < 1 or j < 1 then
local n = utf8.len(s)
if not n then
return nil
end
if i < 0 then
i = n + 1 + i
end
if j < 0 then
j = n + 1 + j
end
if i < 0 then
i = 1
elseif i > n then
i = n
end
if j < 0 then
j = 1
elseif j > n then
j = n
end
end
if j < i then
return ""
end
i = utf8.offset(s, i)
j = utf8.offset(s, j + 1)
if i and j then
return s:sub(i, j - 1)
elseif i then
return s:sub(i)
else
return ""
end
end
local function first_character(s)
return utf8_sub(s, 1, 1)
end
local function last_character(s)
return utf8_sub(s, -1, -1)
end
function select_character(key, env)
local engine = env.engine
local context = engine.context
local commit_text = context:get_commit_text()
local config = engine.schema.config
-- local first_key = config:get_string('key_binder/select_first_character') or 'bracketleft'
-- local last_key = config:get_string('key_binder/select_last_character') or 'bracketright'
local first_key = config:get_string('key_binder/select_first_character')
local last_key = config:get_string('key_binder/select_last_character')
if (key:repr() == first_key and commit_text ~= "") then
engine:commit_text(first_character(commit_text))
context:clear()
return 1 -- kAccepted
end
if (key:repr() == last_key and commit_text ~= "") then
engine:commit_text(last_character(commit_text))
context:clear()
return 1 -- kAccepted
end
return 2 -- kNoop
end
-------------------------------------------------------------
-- 长词优先(提升「西安」「提案」「图案」「饥饿」等词汇的优先级)
-- 感谢&参考于: https://github.com/tumuyan/rime-melt
-- 修改:不提升英文和中英混输的
function long_word_filter(input, env)
-- 提升 count 个词语,插入到第 idx 个位置,默认 2、4。
local config = env.engine.schema.config
local count = config:get_int(env.name_space .. "/count") or 2
local idx = config:get_int(env.name_space .. "/idx") or 4
local l = {}
local firstWordLength = 0 -- 记录第一个候选词的长度,提前的候选词至少要比第一个候选词长
local done = 0 -- 记录筛选了多少个词条(只提升 count 个词的权重)
local i = 1
for cand in input:iter() do
-- 找到要提升的词
local leng = utf8.len(cand.text)
if (firstWordLength < 1 or i < idx) then
i = i + 1
firstWordLength = leng
yield(cand)
elseif ((leng > firstWordLength) and (done < count)) and (string.find(cand.text, "[%w%p%s]+") == nil) then
yield(cand)
done = done + 1
else
table.insert(l, cand)
end
-- 找齐了或者 l 太大了,就不找了
if (done == count) or (#l > 50) then
break
end
end
for _, cand in ipairs(l) do
yield(cand)
end
for cand in input:iter() do
yield(cand)
end
end
-------------------------------------------------------------
-- 降低部分英语单词在候选项的位置
-- https://dvel.me/posts/make-rime-en-better/#短单词置顶的问题
-- 感谢大佬 @[Shewer Lu](https://github.com/shewer) 指点
function reduce_english_filter(input, env)
local config = env.engine.schema.config
-- load data
if not env.idx then
env.idx = config:get_int(env.name_space .. "/idx") -- 要插入的位置
end
if not env.words then
env.words = {} -- 要过滤的词
local list = config:get_list(env.name_space .. "/words")
for i = 0, list.size - 1 do
local word = list:get_value_at(i).value
env.words[word] = true
end
end
-- filter start
local code = env.engine.context.input
if env.words[code] then
local pending_cands = {}
local index = 0
for cand in input:iter() do
index = index + 1
if string.lower(cand.text) == code then
table.insert(pending_cands, cand)
else
yield(cand)
end
if index >= env.idx + #pending_cands - 1 then
for _, cand in ipairs(pending_cands) do
yield(cand)
end
break
end
end
end
-- yield other
for cand in input:iter() do
yield(cand)
end
end
-------------------------------------------------------------
-- v 模式,单个字符优先
-- 因为设置了英文翻译器的 initial_quality 大于 1,导致输入「va」时,候选项是「van vain …… ā á ǎ à」
-- 把候选项应改为「ā á ǎ à …… van vain」,让单个字符的排在前面
-- 感谢改进 @[t123yh](https://github.com/t123yh) @[Shewer Lu](https://github.com/shewer)
function v_filter(input, env)
local code = env.engine.context.input -- 当前编码
env.v_spec_arr = env.v_spec_arr or Set(
{"0️⃣", "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "Vs."})
-- 仅当当前输入以 v 开头,并且编码长度为 2,才进行处理
if (string.len(code) == 2 and string.find(code, "^v")) then
local l = {}
for cand in input:iter() do
-- 特殊情况处理
if (env.v_spec_arr[cand.text]) then
yield(cand)
-- 候选项为单个字符的,提到前面来。
elseif (utf8.len(cand.text) == 1) then
yield(cand)
else
table.insert(l, cand)
end
end
for _, cand in ipairs(l) do
yield(cand)
end
else
for cand in input:iter() do
yield(cand)
end
end
end
-------------------------------------------------------------
-- iRime 九宫格专用,将输入框的数字转为对应的拼音或英文
function irime_t9_preedit(input, env)
for cand in input:iter() do
if (string.find(cand.text, "%w+") ~= nil) then
cand:get_genuine().preedit = cand.text
else
cand:get_genuine().preedit = cand.comment
end
yield(cand)
end
end
-------------------------------------------------------------
-- Unicode 输入
-- 复制自: https://github.com/shewer/librime-lua-script/blob/main/lua/component/unicode.lua
function unicode(input, seg, env)
local ucodestr = seg:has_tag("unicode") and input:match("U(%x+)")
if ucodestr and #ucodestr > 1 then
local code = tonumber(ucodestr, 16)
local text = utf8.char(code)
yield(Candidate("unicode", seg.start, seg._end, text, string.format("U%x", code)))
if #ucodestr < 5 then
for i = 0, 15 do
local text = utf8.char(code * 16 + i)
yield(Candidate("unicode", seg.start, seg._end, text, string.format("U%x~%x", code, i)))
end
end
end
end
-------------------------------------------------------------