mirror of
https://github.com/d0zingcat/rime_wanxiang.git
synced 2026-05-13 15:10:03 +00:00
61 lines
2.0 KiB
Lua
61 lines
2.0 KiB
Lua
-- 用于限制最大候选数量以及重复最大输入编码,防止卡顿性能异常
|
|
--@amzxyz
|
|
--https://github.com/amzxyz
|
|
local M = {}
|
|
local ACCEPT, PASS = 1, 2
|
|
|
|
local MAX_REPEAT = 8 -- 连续重复输入声母上限
|
|
local MAX_SEGMENTS = 40 -- 允许的最大“分段”数
|
|
local INITIALS = "[bpmfdtnlgkhjqxrzcsywiu]"
|
|
|
|
-- 计算末尾重复
|
|
local function tail_rep(s)
|
|
local last, n = s:sub(-1), 1
|
|
for i = #s - 1, 1, -1 do
|
|
if s:sub(i, i) == last then n = n + 1 else break end
|
|
end
|
|
return last, n
|
|
end
|
|
|
|
-- 在候选栏最后一个 segment 加提示
|
|
local function prompt(ctx, msg)
|
|
local comp = ctx.composition
|
|
if comp and not comp:empty() then comp:back().prompt = msg end
|
|
end
|
|
|
|
function M.func(key, env)
|
|
local ctx, kc = env.engine.context, key.keycode
|
|
-- 先拿到“上一轮”高亮候选的 preedit 及段数
|
|
local cand = ctx:get_selected_candidate()
|
|
local preedit = cand and (cand.preedit or cand:get_genuine().preedit) or ""
|
|
local segs = 1
|
|
for _ in preedit:gmatch("[%'%s]") do segs = segs + 1 end
|
|
-- 本次按键字符(只关心字母 / 分隔符)
|
|
local ch
|
|
if kc >= 0x61 and kc <= 0x7A then -- a~z
|
|
ch = string.char(kc)
|
|
elseif kc == 0x27 then -- '
|
|
ch = "'"
|
|
elseif kc == 0x20 then -- space
|
|
ch = " "
|
|
end
|
|
-- ① 连续声母限制:第 MAX_REPEAT 个同声母直接拦截
|
|
if ch and kc >= 0x61 and kc <= 0x7A then
|
|
local nxt = ctx.input .. ch
|
|
local last, rep_n = tail_rep(nxt)
|
|
if last:match(INITIALS) and rep_n > MAX_REPEAT then
|
|
prompt(ctx, " 〔已超最大重复声母〕")
|
|
return ACCEPT
|
|
end
|
|
end
|
|
-- ② 分段限制:第 MAX_SEGMENTS 段拦截
|
|
local segs_after = segs
|
|
if ch == "'" or ch == " " then segs_after = segs + 1 end
|
|
if segs_after >= MAX_SEGMENTS and kc >= 0x61 and kc <= 0x7A then
|
|
prompt(ctx, " 〔已超最大输入长度〕")
|
|
return ACCEPT
|
|
end
|
|
return PASS
|
|
end
|
|
|
|
return M |