mirror of
https://github.com/d0zingcat/rime_wanxiang.git
synced 2026-05-30 07:36:52 +00:00
fix: 小键盘Lua优化
This commit is contained in:
@@ -11,171 +11,234 @@
|
||||
-- # auto : 空闲时直接上屏,输入中参与编码
|
||||
-- # compose : 无论是否在输入中,小键盘都参与编码(不直接上屏)
|
||||
-- kp_number_mode: auto
|
||||
--
|
||||
-- # 可选:命令模式 patterns(Lua pattern)
|
||||
-- # kp_number:
|
||||
-- # patterns:
|
||||
-- # - "^/[0-9]$"
|
||||
-- # - "^/[A-Za-z]+$"
|
||||
-- # - "^V.*$"
|
||||
-- # ...
|
||||
|
||||
local wanxiang = require("wanxiang")
|
||||
|
||||
-- 小键盘键码映射
|
||||
local KP = {
|
||||
[0xFFB1] = 1, [0xFFB2] = 2, [0xFFB3] = 3,
|
||||
[0xFFB4] = 4, [0xFFB5] = 5, [0xFFB6] = 6,
|
||||
[0xFFB7] = 7, [0xFFB8] = 8, [0xFFB9] = 9,
|
||||
[0xFFB0] = 0,
|
||||
[0xFFB1] = 1, -- KP_1
|
||||
[0xFFB2] = 2,
|
||||
[0xFFB3] = 3,
|
||||
[0xFFB4] = 4,
|
||||
[0xFFB5] = 5,
|
||||
[0xFFB6] = 6,
|
||||
[0xFFB7] = 7,
|
||||
[0xFFB8] = 8,
|
||||
[0xFFB9] = 9,
|
||||
[0xFFB0] = 0, -- KP_0
|
||||
}
|
||||
|
||||
local P = {}
|
||||
|
||||
-- 加载配置中的正则模式
|
||||
-- 从 schema 读取 kp_number/patterns 列表
|
||||
local function load_function_patterns(config)
|
||||
local patterns = {}
|
||||
local ok_list, list = pcall(function() return config:get_list("kp_number/patterns") 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 table.insert(patterns, item:get_string()) end
|
||||
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]?$",
|
||||
"^/[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 then return false end
|
||||
|
||||
if not pats or #pats == 0 then
|
||||
return false
|
||||
end
|
||||
|
||||
for _, pat in ipairs(pats) do
|
||||
if s:match(pat) then return true end
|
||||
-- 这里 pat 必须是 Lua pattern 语法
|
||||
if s:match(pat) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---@param env Env
|
||||
function P.init(env)
|
||||
local engine = env.engine
|
||||
local config = engine.schema.config
|
||||
local engine = env.engine
|
||||
local config = engine.schema.config
|
||||
local context = engine.context
|
||||
|
||||
-- 核心:判断并缓存设备类型
|
||||
env.is_mobile = wanxiang.is_mobile_device()
|
||||
|
||||
-- 读数字选词个数
|
||||
env.page_size = config:get_int("menu/page_size") or 6
|
||||
|
||||
local m = config:get_string("kp_number/kp_number_mode") or "auto"
|
||||
env.kp_mode = (m == "compose") and "compose" or "auto"
|
||||
|
||||
env.context = context
|
||||
-- 读小键盘模式: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
|
||||
env.kp_mode = m
|
||||
|
||||
-- 初始化状态快照
|
||||
env.context = context
|
||||
env.is_composing = context:is_composing()
|
||||
env.has_menu = context:has_menu()
|
||||
env.has_menu = context:has_menu()
|
||||
|
||||
-- 读取命令模式 Lua pattern 集合
|
||||
env.function_patterns = load_function_patterns(config)
|
||||
|
||||
-- 用 update_notifier 同步 context / is_composing / has_menu
|
||||
env.kp_update_connection = context.update_notifier:connect(function(ctx)
|
||||
env.context = ctx
|
||||
env.context = ctx
|
||||
env.is_composing = ctx:is_composing()
|
||||
env.has_menu = ctx:has_menu()
|
||||
env.has_menu = ctx:has_menu()
|
||||
end)
|
||||
end
|
||||
|
||||
---@param env Env
|
||||
function P.fini(env)
|
||||
if env.kp_update_connection then
|
||||
env.kp_update_connection:disconnect()
|
||||
env.kp_update_connection = nil
|
||||
end
|
||||
env.context = nil
|
||||
env.context = nil
|
||||
env.is_composing = nil
|
||||
env.has_menu = nil
|
||||
env.function_patterns = nil
|
||||
end
|
||||
|
||||
---@param key KeyEvent
|
||||
---@param env Env
|
||||
---@return ProcessResult
|
||||
function P.func(key, env)
|
||||
if key:release() then
|
||||
return wanxiang.RIME_PROCESS_RESULTS.kNoop
|
||||
-- 只处理按下
|
||||
if key:release() then
|
||||
return wanxiang.RIME_PROCESS_RESULTS.kNoop
|
||||
end
|
||||
|
||||
local context = env.context
|
||||
local engine = env.engine
|
||||
local context = env.context or 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、不选词。
|
||||
------------------------------------------------------------------
|
||||
local kp_num = KP[key.keycode]
|
||||
if kp_num ~= nil then
|
||||
local ch = tostring(kp_num) -- "0".."9"
|
||||
|
||||
-----------------------------------------------------------
|
||||
-- 1. 桌面端小键盘专用逻辑 (非 Mobile 才执行)
|
||||
-- Mobile 端直接跳过此段,进入下方通用逻辑
|
||||
-----------------------------------------------------------
|
||||
if kp_num ~= nil and not env.is_mobile then
|
||||
local ch = tostring(kp_num)
|
||||
|
||||
-- 检查命令模式
|
||||
if is_function_code_after_digit(env, context, ch) then
|
||||
context:push_input(ch)
|
||||
if context then
|
||||
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
|
||||
|
||||
-- Auto / Compose 模式处理
|
||||
if env.kp_mode == "auto" then
|
||||
if env.is_composing then
|
||||
context:push_input(ch)
|
||||
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
|
||||
else
|
||||
env.engine:commit_text(ch)
|
||||
engine:commit_text(ch)
|
||||
end
|
||||
else
|
||||
context:push_input(ch)
|
||||
-- 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) 主键盘数字:
|
||||
-- 2.1 若“加上本次数字后”匹配命令模式 → 只当编码输入
|
||||
-- 2.2 否则:
|
||||
-- 有菜单时:选第 n 个候选
|
||||
-- 空闲时:直接上屏
|
||||
------------------------------------------------------------------
|
||||
local r = key:repr() or ""
|
||||
|
||||
-- 特殊处理:如果是移动端且按下了小键盘,强制将其视为普通数字
|
||||
if kp_num ~= nil and env.is_mobile then
|
||||
r = tostring(kp_num)
|
||||
end
|
||||
|
||||
-- 仅处理数字键
|
||||
if r:match("^[0-9]$") then
|
||||
-- 优先检查:是否匹配命令模式(参与编码)
|
||||
-- 命令模式:只作为编码输入
|
||||
if is_function_code_after_digit(env, context, r) then
|
||||
context:push_input(r)
|
||||
if context then
|
||||
if context.push_input then
|
||||
context:push_input(r)
|
||||
else
|
||||
context.input = (context.input or "") .. r
|
||||
end
|
||||
end
|
||||
return wanxiang.RIME_PROCESS_RESULTS.kAccepted
|
||||
end
|
||||
|
||||
-- 其次检查:是否有菜单(用于选词)
|
||||
-- 这就是移动端小键盘想要的效果:有菜单时选词
|
||||
if env.has_menu then
|
||||
-- 有候选菜单时,用数字选「当前页」的第 n 个候选
|
||||
if has_menu then
|
||||
local d = tonumber(r)
|
||||
local page_sz = env.page_size
|
||||
|
||||
if d and d >= 1 and d <= page_sz then
|
||||
local composition = context.composition
|
||||
local composition = context and context.composition
|
||||
if composition and not composition:empty() then
|
||||
local seg = composition:back()
|
||||
local menu = seg.menu
|
||||
|
||||
local seg = composition:back() -- 当前正在编辑的 segment
|
||||
local menu = seg and seg.menu
|
||||
if menu and not menu:empty() then
|
||||
-- 当前高亮候选的全局下标(0 开始)
|
||||
local sel_index = seg.selected_index or 0
|
||||
local page_no = math.floor(sel_index / page_sz)
|
||||
local index = (page_no * page_sz) + (d - 1)
|
||||
local page_size = page_sz
|
||||
-- 当前页号 = 高亮索引 / 每页大小
|
||||
local page_no = math.floor(sel_index / page_size)
|
||||
local page_start = page_no * page_size
|
||||
-- 当前页第 n 个候选的全局下标
|
||||
local index = page_start + (d - 1)
|
||||
|
||||
-- 防止越界(最后一页候选不足一整页)
|
||||
if index < menu:candidate_count() then
|
||||
if context:select(index) then
|
||||
return wanxiang.RIME_PROCESS_RESULTS.kAccepted
|
||||
@@ -184,12 +247,10 @@ function P.func(key, env)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- 如果是数字键但没选中(例如超出页码),不做处理,交由系统(通常会上屏数字)
|
||||
return wanxiang.RIME_PROCESS_RESULTS.kNoop
|
||||
end
|
||||
end
|
||||
|
||||
return wanxiang.RIME_PROCESS_RESULTS.kNoop
|
||||
end
|
||||
|
||||
return P
|
||||
return P
|
||||
|
||||
Reference in New Issue
Block a user