feat: 新增yaml正则转义lua正则模块,数字键处理逻辑将直接读取状态

This commit is contained in:
amzxyz
2026-01-05 10:34:19 +08:00
parent be21abc4d3
commit 0417d9dfdb
4 changed files with 292 additions and 218 deletions

View File

@@ -12,6 +12,7 @@
-- # compose : 无论是否在输入中,小键盘都参与编码(不直接上屏)
-- kp_number_mode: auto
local wanxiang = require("wanxiang")
-- 小键盘键码映射
@@ -27,69 +28,25 @@ local KP = {
[0xFFB9] = 9,
[0xFFB0] = 0, -- KP_0
}
local P = {}
-- 从 schema 读取 kp_number/patterns 列表
local function load_function_patterns(config)
local patterns = {}
-- [调试工具] 最小化日志打印 (如需调试请取消注释)
-- local function log_info(msg)
-- log.info("kp_number: " .. tostring(msg))
-- end
local ok_list, list = pcall(function()
return config:get_list("kp_number/patterns")
end)
if ok_list and list and list.size and list.size > 0 then
for i = 0, list.size - 1 do
local item = list:get_value_at(i)
if item then
local pat = item:get_string()
if pat and pat ~= "" then
table.insert(patterns, pat)
end
end
end
end
-- 如果用户没配,给一份保底的默认集合(等价你现在用的那些)
if #patterns == 0 then
patterns = {
"^/[0-9]$", "^/10$", "^/[A-Za-z]+$",
"^`[A-Za-z]*$",
"^``[A-Za-z/`']*$",
"^U[%da-f]+$",
"^R[0-9]+%.?[0-9]*$",
"^N0[1-9]?0?[1-9]?$",
"^N1[02]?0?[1-9]?$",
"^N0[1-9]?[1-2]?[1-9]?$",
"^N1[02]?[1-2]?[1-9]?$",
"^N0[1-9]?3?[01]?$",
"^N1[02]?3?[01]?$",
"^N19?[0-9]?[0-9]?[01]?[0-2]?[0-3]?[0-9]?$",
"^N20?[0-9]?[0-9]?[01]?[0-2]?[0-3]?[0-9]?$",
"^V.*$",
}
end
return patterns
end
-- 根据“当前编码 + 这次按下的数字字符”判断是否属于命令模式
-- 检查当前输入+数字是否匹配命令模式
local function is_function_code_after_digit(env, context, digit_char)
if not context or not digit_char or digit_char == "" then
return false
end
if not context or not digit_char or digit_char == "" then return false end
local code = context.input or ""
local s = code .. digit_char
local pats = env.function_patterns
if not pats or #pats == 0 then
return false
end
if not pats then return false end
for _, pat in ipairs(pats) do
-- 这里 pat 必须是 Lua pattern 语法
if s:match(pat) then
return true
end
-- Lua pattern 匹配
if s:match(pat) then return true end
end
return false
end
@@ -99,33 +56,27 @@ function P.init(env)
local engine = env.engine
local config = engine.schema.config
local context = engine.context
-- 读数字选词个数
env.page_size = config:get_int("menu/page_size") or 6
-- 读小键盘模式auto / compose默认 auto
local m = config:get_string("kp_number/kp_number_mode") or "auto"
if m ~= "auto" and m ~= "compose" then
m = "auto"
end
if m ~= "auto" and m ~= "compose" then m = "auto" end
env.kp_mode = m
-- 初始化状态快照
env.context = context
env.is_composing = context:is_composing()
env.has_menu = context:has_menu()
-- 读取命令模式 Lua pattern 集合
env.function_patterns = load_function_patterns(config)
-- 从 wanxiang 模块加载并转译正则
-- 这一步会自动处理 YAML 正则到 Lua 模式的所有转换
env.function_patterns = wanxiang.load_regex_patterns(config, "recognizer/patterns")
-- 用 update_notifier 同步 context / is_composing / has_menu
-- log_info("Loaded " .. #(env.function_patterns or {}) .. " patterns.")
env.kp_update_connection = context.update_notifier:connect(function(ctx)
env.context = ctx
env.is_composing = ctx:is_composing()
env.has_menu = ctx:has_menu()
end)
end
---@param env Env
function P.fini(env)
if env.kp_update_connection then
@@ -142,112 +93,67 @@ end
---@param env Env
---@return ProcessResult
function P.func(key, env)
-- 只处理按下
if key:release() then
return wanxiang.RIME_PROCESS_RESULTS.kNoop
end
if key:release() then return wanxiang.RIME_PROCESS_RESULTS.kNoop end
local engine = env.engine
local context = env.context or engine.context
local context = env.context or env.engine.context
local mode = env.kp_mode or "auto"
local page_sz = env.page_size
local is_composing = env.is_composing
local has_menu = env.has_menu
------------------------------------------------------------------
-- 1) 小键盘数字auto / compose
-- 如果“加上本次数字后”还匹配某个命令模式 pattern
-- 只作为编码输入,不 commit、不选词。
------------------------------------------------------------------
-- 1) 小键盘数字处理
local kp_num = KP[key.keycode]
if kp_num ~= nil then
if key:ctrl() or key:alt() or key:super() or key:shift() then
return wanxiang.RIME_PROCESS_RESULTS.kNoop
end
local ch = tostring(kp_num) -- "0".."9"
local ch = tostring(kp_num)
-- 如果匹配到正则(如网址、反查),则拦截,强制作为编码输入
if is_function_code_after_digit(env, context, ch) then
if context then
if context.push_input then
context:push_input(ch)
else
context.input = (context.input or "") .. ch
end
end
if context.push_input then context:push_input(ch)
else context.input = (context.input or "") .. ch end
return wanxiang.RIME_PROCESS_RESULTS.kAccepted
end
-- 正常数字逻辑
if mode == "auto" then
-- 输入中:参与编码;空闲:直接上屏
if is_composing then
if context.push_input then
context:push_input(ch)
else
context.input = (context.input or "") .. ch
end
if env.is_composing then
if context.push_input then context:push_input(ch)
else context.input = (context.input or "") .. ch end
else
engine:commit_text(ch)
end
else
-- compose始终参与编码
if context.push_input then
context:push_input(ch)
else
context.input = (context.input or "") .. ch
env.engine:commit_text(ch)
end
else -- compose
if context.push_input then context:push_input(ch)
else context.input = (context.input or "") .. ch end
end
return wanxiang.RIME_PROCESS_RESULTS.kAccepted
end
------------------------------------------------------------------
-- 2) 主键盘数字:
-- 2.1 若“加上本次数字后”匹配命令模式 → 只当编码输入
-- 2.2 否则:
-- 有菜单时:选第 n 个候选
-- 空闲时:直接上屏
------------------------------------------------------------------
-- 2) 主键盘数字处理
local r = key:repr() or ""
if r:match("^[0-9]$") then
if key:ctrl() or key:alt() or key:super() then
return wanxiang.RIME_PROCESS_RESULTS.kNoop
end
-- 命令模式:只作为编码输入
if is_function_code_after_digit(env, context, r) then
if context then
if context.push_input then
context:push_input(r)
else
context.input = (context.input or "") .. r
end
end
if context.push_input then context:push_input(r)
else context.input = (context.input or "") .. r end
return wanxiang.RIME_PROCESS_RESULTS.kAccepted
end
-- 有候选菜单时,用数字选「当前页」的第 n 个候选
if has_menu then
if env.has_menu then
local d = tonumber(r)
-- 如果按下的是 0视为第 10 个选项
if d == 0 then d = 10 end
-- 检查是否在有效范围内 (例如 page_size 是 10那么 1-10 都有效)
if d and d >= 1 and d <= page_sz then
local composition = context and context.composition
local composition = context.composition
if composition and not composition:empty() then
local seg = composition:back()
local menu = seg and seg.menu
if menu and not menu:empty() then
local sel_index = seg.selected_index or 0
local page_size = page_sz
-- 计算当前页起始位置
local page_no = math.floor(sel_index / page_size)
local page_start = page_no * page_size
-- 计算目标候选的全局下标 (d=10 则取第10个)
local page_start = math.floor(sel_index / page_sz) * page_sz
local index = page_start + (d - 1)
-- 防止越界并执行上屏
if index < menu:candidate_count() then
if context:select(index) then
return wanxiang.RIME_PROCESS_RESULTS.kAccepted
@@ -256,12 +162,11 @@ function P.func(key, env)
end
end
end
-- 如果数字超出了 page_size (例如设置每页6个按了7)
-- 或者没有选中成功,返回 kNoop交给 Rime 默认处理
return wanxiang.RIME_PROCESS_RESULTS.kNoop
end
end
return wanxiang.RIME_PROCESS_RESULTS.kNoop
end
return P
return P