feat(super_filter): 新增英文智能空格,前所未有的体验

This commit is contained in:
amzxyz
2025-12-31 21:51:32 +08:00
parent cdcd26e1f2
commit 049b0ba8ae
4 changed files with 110 additions and 37 deletions

View File

@@ -135,6 +135,11 @@ tips:
charsetlist: []
charsetblacklist: []
#英文自动加空格除关闭外共有3种模式可供选择
#off: 关闭; before: 总是前加; after: 总是后加;
#smart: 智能模式连续输入英文时第二个单词前开始加空格,非输入状态的回车与空格都能打断加空格状态
english_spacing: smart
#shijian:仅仅作为提示使用编码已经写死引导键可以在key_binder下修改前缀
#时间osj 或者 /sj
#日期orq 或者 /rq

View File

@@ -20,6 +20,14 @@ end
function M.func(key, env)
local ctx = env.engine.context
local kc = key.keycode
-- 这里嵌入一段记录按键的逻辑,给英文空格使用
if not key:release() and ctx.composition:empty() then
-- 检测:回车 (0xff0d, 0xff8d) 或 空格 (0x20)
if kc == 0xff0d or kc == 0xff8d or kc == 0x20 then
-- 发送信号:刚才发生了空闲换行或空格,打断英文连贯性
ctx:set_property("english_spacing", "true")
end
end --嵌入结束
-- 非 Backspace 键或按键释放事件:重置状态
if kc ~= 0xFF08 or key:release() then
env.bs_sequence = false

View File

@@ -26,6 +26,8 @@
-- 功能G 由于在混输场景中输入comment commit等等之类的英文时候由于直接辅助码的派生能力会将三个好不想干的单字组合在一起这会造成不好的体验
-- 因此在首选已经是英文的时候且type=completion且大于等于4个字符这个时候后面如果有type=sentence的派生词则直接干掉这个还要依赖表翻译器
-- 权重设置与主翻译器不可相差太大
-- 功能H英文自动空格english_spacing
-- 支持模式off(默认), before(前), after(后), smart(连续英文时在前加空格)
local wanxiang = require("wanxiang")
local M = {}
@@ -172,50 +174,70 @@ local function apply_escape_fast(text)
end
local function format_and_autocap(cand, code_ctx)
-- 对候选做:空白规范化 → 转义替换 → 英文大写
local text = cand.text
if not text or text == "" then return cand end
-- ① 空白规范化
local changed = false
-- 空白规范化
local norm = normalize_spaces(text)
local changed = (norm ~= text)
text = norm
local has_backslash = (find(text, "\\", 1, true) ~= nil)
local b1 = byte(text, 1)
-- ② 转义替换
if has_backslash then
local t2, ch = apply_escape_fast(text)
if ch then text, changed = t2, true end
if norm ~= text then
text = norm
changed = true
end
-- ③ 英文自动大写:
-- - 允许 ASCII 短语he's / e-mail
-- - 只有“纯字母单词”才会在 all_upper 时变成全大写
if code_ctx.enable_cap then
if b1 and b1 <= 127 and is_ascii_phrase_fast(text) then
-- 纯字母单词a..z / A..Z
local pure_word = is_ascii_word_fast(text)
-- 转义替换 (\n, \t, \s 等)
-- 必须先处理转义,因为转义可能会改变字符串开头 (如 \sApple -> Apple)
if find(text, "\\", 1, true) then
local t2, ch = apply_escape_fast(text)
if ch then
text = t2
changed = true
end
end
-- 状态检测:转义完成后,检测当前文本是否为 ASCII 短语
local b1 = byte(text, 1)
local is_ascii_phrase = (b1 and b1 <= 127 and is_ascii_phrase_fast(text))
-- 英文自动大写
if code_ctx.enable_cap and is_ascii_phrase then
local pure_word = is_ascii_word_fast(text)
if cand.type == "completion" or ascii_equal_ignore_case_to_pure(text, code_ctx.pure_code_lc) then
local new_text
if code_ctx.all_upper and pure_word then
-- 只有纯单词才允许全大写HELLO
new_text = upper(text)
else
-- 带符号he's、e-mail…即使 all_upper 也只做首字母大写
new_text = text:gsub("^%a", string.upper)
end
if cand.type == "completion" or ascii_equal_ignore_case_to_pure(text, code_ctx.pure_code_lc) then
local new_text = nil
if code_ctx.all_upper and pure_word then
-- 全大写逻辑 (HELLO)
new_text = upper(text)
else
-- 首字母大写逻辑 (Hello)
new_text = text:gsub("^%a", string.upper)
end
if new_text and new_text ~= text then
text = new_text
changed = true
end
if new_text and new_text ~= text then
text = new_text
changed = true
end
end
end
-- 英文自动空格
if is_ascii_phrase and code_ctx.spacing_mode and code_ctx.spacing_mode ~= "off" then
local mode = code_ctx.spacing_mode
-- smart模式: 若“上次上屏是英文”且“当前也是英文”,则在前面补空格
if mode == "smart" then
if code_ctx.prev_is_eng then
text = " " .. text
changed = true
end
elseif mode == "before" then
text = " " .. text
changed = true
elseif mode == "after" then
text = text .. " "
changed = true
end
end
-- 输出结果
if not changed then return cand end
local nc = Candidate(cand.type, cand.start, cand._end, text, cand.comment)
nc.preedit = cand.preedit
return nc
@@ -563,7 +585,27 @@ function M.init(env)
local okb, bv = pcall(function() return cfg:get_bool("paired_symbols/mirror") end)
if okb and bv ~= nil then env.suppress_mirror = bv end
end
-- 英文自动空格配置
-- off: 关闭; before: 前加; after: 后加; smart: 连续英文时前加
env.english_spacing_mode = "off"
if cfg then
local oks, sv = pcall(function() return cfg:get_string("english_spacing") end)
if oks and sv and (sv == "before" or sv == "after" or sv == "smart") then
env.english_spacing_mode = sv
end
end
-- 上一次上屏是否为英文(用于 smart 模式)
env.prev_commit_is_eng = false
-- 注册 commit 通知器来追踪上屏历史
if env.engine and env.engine.context then
env.commit_notifier = env.engine.context.commit_notifier:connect(function(ctx)
local commit_text = ctx:get_commit_text()
-- 1. 判断上屏内容是否为英文短语
env.prev_commit_is_eng = is_ascii_phrase_fast(commit_text)
-- 2. 上屏后,立即清除打断信号
ctx:set_property("english_spacing", "")
end)
end
env.cache = nil -- 首候选缓存(已格式化)
env.locked = false -- 是否进入锁定态(检测到 prefix\suffix
@@ -577,8 +619,12 @@ function M.init(env)
init_charset_filter(env, cfg)
end
function M.fini(env) end
function M.fini(env)
if env.commit_notifier then
env.commit_notifier:disconnect()
env.commit_notifier = nil
end
end
-- ========= 统一产出通道 =========
-- ctxs:
-- charset : 字符集过滤
@@ -732,12 +778,21 @@ function M.func(input, env)
local all_upper = code:find("^%u%u") ~= nil
local first_upper = (not all_upper) and (code:find("^%u") ~= nil)
local enable_cap = (code_len > 1 and not code:find("^[%l%p]"))
local break_signal = (ctx:get_property("english_spacing") == "true") --接受空状态下的空格或者回车信号
-- 计算最终的 prev_is_eng (上文是否为英文)
local effective_prev_is_eng = env.prev_commit_is_eng
if break_signal then
-- 收到打断信号,强制认为上文不是英文(从而不自动加空格)
effective_prev_is_eng = false
end
local code_ctx = {
pure_code = pure_code,
pure_code_lc = pure_code_lc,
all_upper = all_upper,
first_upper = first_upper,
enable_cap = enable_cap,
spacing_mode = env.english_spacing_mode, -- 传递空格模式配置
prev_is_eng = effective_prev_is_eng, -- 传递上一次上屏是否英文
}
local en_only, zh_only = false, false

View File

@@ -131,6 +131,11 @@ tips:
charsetlist: []
charsetblacklist: []
#英文自动加空格除关闭外共有3种模式可供选择
#off: 关闭; before: 总是前加; after: 总是后加;
#smart: 智能模式连续输入英文时第二个单词前开始加空格,非输入状态的回车与空格都能打断加空格状态
english_spacing: smart
#shijian:仅仅作为提示使用编码已经写死引导键可以在key_binder下修改前缀
#时间osj 或者 /sj
#日期orq 或者 /rq