From 581c5940e09682f41d2e8432f48fdf72d245b478 Mon Sep 17 00:00:00 2001 From: amzxyz Date: Sun, 18 Jan 2026 15:43:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AD=97=E7=AC=A6=E9=9B=86=E8=BF=87?= =?UTF-8?q?=E6=BB=A4=E7=8E=B0=E5=B7=B2=E5=85=A8=E9=9D=A2=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=EF=BC=8C=E5=85=B7=E4=BD=93=E9=98=85=E8=AF=BB=E6=96=B9=E6=A1=88?= =?UTF-8?q?=E4=B8=AD=E9=85=8D=E7=BD=AE=E6=AE=B5=E8=90=BD=E7=9A=84=E8=AF=B4?= =?UTF-8?q?=E6=98=8E=EF=BC=8C=E7=8E=B0=E5=9C=A8=E5=8F=AF=E4=BB=A5=E5=85=BC?= =?UTF-8?q?=E5=AE=B9=E5=AD=97=E7=AC=A6=E9=9B=86=E8=BF=87=E6=BB=A4=E4=B8=8E?= =?UTF-8?q?=E7=AE=80=E7=B9=81=E8=BD=AC=E6=8D=A2=E7=9A=84=E5=86=B2=E7=AA=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- custom/wanxiang_pro.schema.yaml | 41 +++- lua/charset.bin | Bin 54012 -> 0 bytes lua/data/charset.reverse.bin | Bin 0 -> 565032 bytes lua/super_filter.lua | 410 +++++++++++++++++--------------- wanxiang.schema.yaml | 40 +++- wanxiang_t9.schema.yaml | 55 ++++- 6 files changed, 345 insertions(+), 201 deletions(-) delete mode 100644 lua/charset.bin create mode 100644 lua/data/charset.reverse.bin diff --git a/custom/wanxiang_pro.schema.yaml b/custom/wanxiang_pro.schema.yaml index c9b20ea..d9e352f 100644 --- a/custom/wanxiang_pro.schema.yaml +++ b/custom/wanxiang_pro.schema.yaml @@ -130,10 +130,6 @@ tips: # 可选项为:偏旁,符号,化学式,时间,符号,组字,翻译,表情,货币,车牌 disabled_types: [] -#在8105基础上你可以通过黑白名单微调你自己的字符集过滤清单,主数据库位于lua/charset.bin不可编辑 -charsetlist: [] -charsetblacklist: [] - # 给 kp_number_processor 用的小键盘模式,能自动读取recognizer下面正则与之功能对齐 kp_number_mode: auto #小键盘数字处理逻辑 @@ -199,6 +195,43 @@ super_replacer: files: - lua/data/TWVariants.txt - lua/data/TWVariantsRevPhrases.txt + +# 字符集过滤lua +# a,通用规范汉字表 +# b,GB2312, +# g,GBK, +# T,Big5,(台港澳常用) +# j,简体,OpenCC (t2s) +# f,通用繁体,OpenCC (s2t) +# h,香港繁体, OpenCC (s2hk) +# t,台湾繁体, OpenCC (s2tw) +# u,基本区,U+4E00 - U+9FFF +# A-I,扩展 A-I 区,U+3400 及各扩展区 (支持到 Ext-I) +# c,兼容区汉字 +# 你可以通过黑白名单微调你自己每个开关下面的字符集过滤清单,主数据库位于lua/charset.reverse.bin不可编辑 +# 你可以按上面提到的规则代号在base处填写上基础集,还可以在每一个开关的开白名单设置微调数据,就像默认添加的字符集过滤在8105基础上新增了一些 +# 你可以定义多个开关,多个开启状态的开关求并集,比如charset_filter开着,s2hk也开着,那么就会显示这两个集合的所有汉字 +# 优雅的地方在于s2hk开着,charset_filter关着 我们照样能使用 港繁能用到的所有字,是真正的本体,无关字会被过滤,而当都开着则是享受简体转换成繁体的后的结果 +# 这个设计真正的兼容了简繁转换与字符集过滤的矛盾,还能满足用户多种自定义需求,你可以在开关增加类别,并在charset下面新增option类去选择按照字区去过滤,等多种组合方式 +charset: + - option: charset_filter + base: a #可以填入多个类别如aj + addlist: + - "诶濛硷氽尛躝〇冇吔咗囧屌鲶芶咲畑垅𰻝𰻞" + blacklist: [] + - option: s2t + base: f + addlist: [] + blacklist: [] + - option: s2hk + base: h + addlist: [] + blacklist: [] + - option: s2tw + base: t + addlist: [] + blacklist: [] + #shijian:仅仅作为提示使用,编码已经写死,引导键可以在key_binder下修改前缀 #时间:osj 或者 /sj #日期:orq 或者 /rq diff --git a/lua/charset.bin b/lua/charset.bin deleted file mode 100644 index 86083499e303c732be0b21248f2a5f2e26700b13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54012 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

F>es(7!`-c9v(&dAHfKeU4&B?k>3*ADwxY&rI!z z#v{Aht3NU~xsUdz)>`Zw{Sue@7H6sVF8t^|NBL`epV2zgv$n%h?dmyK>#gn0ENzMR zYJBf~Eb*4`XP#@^Va%Vo%br>6x3%L^eFRr?0K)a(^t*>-0fpG|GB^SxWAw2IXrUKM|vN7(!byRPP_d6 zcK0CP<;<@<$KKg{dG|c&kLu_CAAbkF%N<^Ejw>`CeC0^1Qc}scr z8>c5WU(yhlo8H=*->Z+tUM{@+@7vue_fSipHRD;Iwe<4z)Yf#fcTYTOJu=7MEx%{4 zy`0(p_Kr315gT{4caI;n#-7w3YqNYwFLjcW@8L{u4NIMow={3$t>tGlvS&$qi37g$ zf7blpFmCad>Pxu#)H5FWYqgR4%=}&VdgdLxYS!oOUv=~EKlkc)<7&P4zroLjci#Z- z)K_`09^LcN{=1*WO#jTzXL@F{KiKC6uDXHm@=kJ&?{b!_p6yYcJMQle&704ZQ1fde^DZ$CJ_3yFaXN%7bd~VPDS)6bB=Sz{HWd@{%pn!+oN@c^UPUi_M_*SJ3e#P+55=8EBC!pD|cLqnfL6OOS?Q1 zf0r{qy2qpadFNMZrS2#G+`xCcfuHHK^4-tM`LuU=Pw%?(yL4yw#(&fG%z3jN-Ua&( z_wXIg@GkGeXOBO+0p6?6yY)x+F-EVvn`h5{_Po67t7o6lqvuRtp5qfAzkyfY`7381 zzp3LLzSH{S3ZIU=f!RHNrFZBn?V9&~SA50)#^bKt9@X9RtoL&E@E+aw(|_y+KF{RX zeLaJH*E2zPrai-+an8?-^EdFFpIM$Q)S{m+&>cJ+(8sXL|PR@(!G@a<(J?KKbf<<&I|eG{df*{YpL0o&J^kIQzphTndj9XU%busR_Pp25vR2zO_f?#;dwWmg z-e>jHne~h5<*xZ7+%=t7)!0AnReS86JKp!0qcg*{^w)aUYHPY@`_?qyrN-GtV>hvP z+4HOI@txn9yPm~Yd*^({`n&FBru&MSxyM&~R=GRztM6~z=Nb9hnZNq;T)MxtGcWbr zjeFOx+HE#>hTVM+d-Si^D>aBS-?PIR&a>v6+3n7rE6)9l=X2*Byu0@2e$PFj&%GVH zw`bhfY{m>@^CkS)sqSHqyN&rhQ}0v#>ige!Gw-SVd0y+!<#Rvl_w$PCJ3W(k+U3Zz z_^Nv^oze5?mv|ria|53nc)uI?%Aeb>y!+WVVLbDgpVeLKW5%92GtLZKoAs>P+Fon5 zJN9Fqc8C5uYd-s~-}x@S`)=?0tdD;7UU80B%-r)n9=*Fgn%{}@uFvf|-SKxi%iZtG z-THSti#v9{LzA=LrF+M{eh1CZegDx@yz(xt)cT_hACKO3ug6cetnlhHpP4`QjQR3u z-?MVZ{!5xm__J>2$owPRXYGIW9M1S%&w16kW;!!$>)D*?+0r~xXTEl%PwuPtcaM+% z+`xDPvv+fbjeU3IubO+uS>9RmbI-s3bgsUWtMz_=;}3Gh4ZPcPVxOyaI-_%@XM7Gv zH1=@!aK;_(&R@CHD`($*uRn{v&rtufocnXm&kelG4SYU(@A4!*d%XJ%?D>CRZ|(E6 zRy%w4nI_l_KRe@!zIWT_iZd-~oH^^6o~8NE!rA$&?0t0CuX3(OpY=PO^Xv|1`^G!F zN@vs^^JmQ&=WgX^_BzwEwa0g@UvXDz=)db-jpusT^S*MgSI!=v&m;LA=eR@j9nN^? zxsGTb;XZP2SM+Y}x>euW;Y|OTo~=DT_4mJlz5oAJeBO_Hp5=J2W1dsjYRQ|$kMz#; zKG@f}fuHHwbJnkX-mkp-*ZD-e&!$J8_nrKs+GlU^t~qz^C*t^{amUy1T0TS8SrX(~TFjE!}#m+rGNrg81>4{&vZ18>|w4)%43)5#`CxL>vR#X&LD2Q-?CknY+Ky*g8j>8Tiy7H;=1d&Jkk1z%H3@P?k@wL zXuEjj!FI9Bc5vlTI5_**4Yorn-JAZK#EIlRc~GCK)on{0w{n2D1ZVe5GdgGV_Y8m zUfX4=btSWYGV9c~y=>R;6-dS({yNF57pM`e8!UrzmMD-f3S`RLHPuto?{%qXredd3 zPb%xy<-Sul3ZMWA)TBVBu2-3=r>6GuI|@{%Kx6Y^W82^Aj(zNJXcMbQ&EFfMX4z(sJA|sb=A(GUVj-NllvLepGuvz*(R0xv$<}r?n|O}B`VLRW{ovg zE^42PZECFkV81i3Kr;SLW}VEpj2clO_Z8sW$o*rKk1cF0zH2P|nU5aLm3_*#hq4_n zkvXrz%wEK=C70V4zs0pLZA|-`j7qV3#C}hvjzsHZvaUoi zvR&Sg_Ng{)t<5&sJ_flMFW$e&5w9$^?a8bYyG?z4&t-4qa@*25UirFT>1fhWx6PMh znd|$JYWotcAFn)KneWF$<*rwgS;t*JU7l_{fBSUnNOd2w9WT}PWo!LxXrGMM*=R?m zG)-oIY7?uj>a9&%YT71~ZOvp|HMN`Hf2=^N`lq`7k0aWWpsv_uutrese|LHCdwneH zyB+l%zdkgtiWYYra316lS!wy!(cj>kPLd-pK3M(bSg zK%#3*qVjCFIak_|?foVm*9Sa+2k-zMzyo*y58wejfCumZ9>4>501w~+Jb(uR5Ad86 zF9cp-i5Kty9`Nr8>D(96-5w9(!Cdq}I_E?#?hkF^Ji`O^;{mQE^`m<{zo&XE-1S`^ zuWq+2m37_i;JM?Kx;hrAdc$4c<#pA*e5@DU^8dW5jc;r6MRmWszq!0N?TFpRuP@Ve z#>PnZd#<-H-TiCq+sE@@z8&-0>`!gB$)=a$9k+P#gY|;_iCxCqhO*qaj|RuCu8v3G zg}SOg*XwQU`=80<(?oq4klPxx$?`GEcD#80%VZnex?CPFZcrAxUhMZ^y;PU6^%UsX z0yL;A546Q!oL_hV58wejfCunE3Lc>EK)fZzDUT@Rg9uL&72lD0k<;#9>KGg5|fd1%@2k-zMXjmTb@Bj1x8rCt( z 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 E52jBjC;$Ke literal 0 HcmV?d00001 diff --git a/lua/super_filter.lua b/lua/super_filter.lua index 1423e13..6090d68 100644 --- a/lua/super_filter.lua +++ b/lua/super_filter.lua @@ -18,7 +18,7 @@ -- - ctx:get_option("en_only") == true → 仅英文:只保留英文候选 -- - ctx:get_option("zh_only") == true → 仅中文:丢弃英文候选 -- - 两者都 false → 混合模式:中英都输出 --- 功能E 字符集过滤,默认8105+𰻝𰻝,可以在方案中定义黑白名单来实现用户自己的范围微调charsetlist: []和charsetblacklist: [𰻝, 𰻞] +-- 功能E 字符集过滤,默认8105+𰻝𰻝,可以在方案中定义黑白名单来实现用户自己的范围微调addlist: []和blacklist: [𰻝, 𰻞] -- 功能F 由于在混输场景中输入comment commit等等之类的英文时候,由于直接辅助码的派生能力,会将三个好不想干的单字组合在一起,这会造成不好的体验 -- 因此在首选已经是英文的时候,且type=completion且大于等于4个字符,这个时候后面如果有type=sentence的派生词则直接干掉,这个还要依赖,表翻译器 -- 权重设置与主翻译器不可相差太大 @@ -26,9 +26,12 @@ local wanxiang = require("wanxiang") local M = {} +-- 性能优化:本地化字符串函数 local byte, find, gsub, upper, sub = string.byte, string.find, string.gsub, string.upper, string.sub +local utf8_codes = utf8.codes -- 本地化 utf8 迭代器 + +-- ================= 工具函数 ================= --- 工具 local function fast_type(c) local t = c.type if t then return t end @@ -46,16 +49,10 @@ local function has_english_token_fast(s) for i = 1, len do local b = byte(s, i) if b < 0x80 then - -- A-Z - if b >= 0x41 and b <= 0x5A then + -- A-Z (0x41-0x5A) or a-z (0x61-0x7A) + if (b >= 0x41 and b <= 0x5A) or (b >= 0x61 and b <= 0x7A) then return true end - -- a-z - if b >= 0x61 and b <= 0x7A then - return true - end - else - -- b >= 0x80: UTF-8 非 ASCII 字节,直接跳过 end end return false @@ -68,27 +65,28 @@ local function is_english_candidate(cand) if not has_english_token_fast(txt) then return false end - if string.find(txt, "[\128-\255]") then + -- 使用局部变量 find,而非 string.find + if find(txt, "[\128-\255]") then return false end return true end --- 文本格式化 +-- ================= 文本格式化 ================= + local escape_map = { ["\\n"] = "\n", -- 换行 ["\\r"] = "\r", -- 回车 ["\\t"] = "\t", -- 制表符 ["\\s"] = " ", -- 空格 - ["\\z"] = "\226\128\139", -- 零宽空格 (隐形阻断符) + ["\\z"] = "\226\128\139", -- 零宽空格 } local utf8_char_pattern = "[%z\1-\127\194-\244][\128-\191]*" local function apply_escape_fast(text) - -- 快速预检 - if not text or (not find(text, "\\", 1, true) and not find(text, "{", 1, true)) then - return text, false + if not text or (not find(text, "\\", 1, true) and not find(text, "{", 1, true)) then + return text, false end local new_text = text @@ -112,6 +110,7 @@ local function apply_escape_fast(text) end return new_text, new_text ~= text end + local function format_and_autocap(cand) local text = cand.text if not text or text == "" then return cand end @@ -121,13 +120,13 @@ local function format_and_autocap(cand) nc.preedit = cand.preedit return nc end + local function clone_candidate(c) local nc = Candidate(c.type, c.start, c._end, c.text, c.comment) nc.preedit = c.preedit return nc end - --- 包裹映射 +-- 包裹映射 local default_wrap_map = { -- 单字母:常用成对括号/引号(每项恰好两个字符) a = "[]", -- 方括号 @@ -157,14 +156,14 @@ local default_wrap_map = { y = "⟪⟫", -- 双角括号 z = "{}", -- 花括号 - -- 扩展括号族 / 引号 + -- 扩展括号族 / 引号 dy = "''", -- 英文单引号 sy = "\"\"", -- 英文双引号 zs = "“”", -- 中文弯双引号 zd = "‘’", -- 中文弯单引号 fy = "``", -- 反引号 - -- 双字母括号族 + -- 双字母括号族 aa = "〚〛", -- 双中括号 bb = "〘〙", -- 双中括号(小) cc = "〚〛", -- 双中括号(重复,可用于 Lua 匹配) @@ -191,7 +190,7 @@ local default_wrap_map = { yy = "⌠⌡", -- 数学 / 程序符号 zz = "⟅⟆", -- 数学 / 装饰括号 - -- Markdown / 标记 + -- Markdown / 标记 md = "**|**", -- Markdown 粗体 jc = "**|**", -- 加粗 it = "__|__", -- 斜体 @@ -212,7 +211,7 @@ local default_wrap_map = { br = "| ", -- 换行 cm = "", -- 注释 - -- 运算与标记符 + -- 运算与标记符 pl = "++", mi = "--", sl = "//", @@ -245,15 +244,7 @@ local function load_mapping_from_config(config) return symbol_map end -local function utf8_chars(s) - local chars = {} - for ch in s:gmatch("[%z\1-\127\194-\244][\128-\191]*") do - table.insert(chars, ch) - end - return chars -end - --- wrap_map 预编译为左右两部分 +-- 优化:删除 utf8_chars 函数,直接在预编译中使用 utf8_codes local function precompile_wrap_parts(wrap_map, delimiter) delimiter = delimiter or "|" local parts = {} @@ -261,177 +252,224 @@ local function precompile_wrap_parts(wrap_map, delimiter) if not wrap_str or wrap_str == "" then parts[k] = { l = "", r = "" } else - local pos = string.find(wrap_str, delimiter, 1, true) + local pos = find(wrap_str, delimiter, 1, true) if pos then - local left = string.sub(wrap_str, 1, pos - 1) or "" - local right = string.sub(wrap_str, pos + 1) or "" + local left = sub(wrap_str, 1, pos - 1) or "" + local right = sub(wrap_str, pos + 1) or "" parts[k] = { l = left, r = right } else - local chars = utf8_chars(wrap_str) - if #chars == 0 then + -- 优化:使用 utf8_codes 避免创建 table + local first, last + local count = 0 + for _, cp in utf8_codes(wrap_str) do + local char = utf8.char(cp) + if count == 0 then first = char end + last = char + count = count + 1 + end + + if count == 0 then parts[k] = { l = "", r = "" } - elseif #chars == 1 then - parts[k] = { l = chars[1], r = "" } - elseif #chars == 2 then - parts[k] = { l = chars[1], r = chars[2] } + elseif count == 1 then + parts[k] = { l = first, r = "" } + elseif count == 2 then + parts[k] = { l = first, r = last } -- 修正:双字时左右各一 else - parts[k] = { l = chars[1], r = chars[#chars] } + parts[k] = { l = first, r = last } -- 多字时首尾各一 end end end end return parts end --- 字符集过滤工具 --- 单个码点是否在 charset 里(带缓存,考虑白名单 + 黑名单) -local function codepoint_in_charset(env, codepoint) - if not env then - return true - end - local memo = env.charset_memo - if memo and memo[codepoint] ~= nil then - return memo[codepoint] - end +-- ================= 字符集过滤核心 ================= - -- 黑名单:优先级最高,命中就直接 false - if env.charset_block and env.charset_block[codepoint] then - if memo then memo[codepoint] = false end - return false - end - - -- 白名单:命中就直接 true - if env.charset_extra and env.charset_extra[codepoint] then - if memo then memo[codepoint] = true end - return true - end - - -- 没有主表(没配 wanxiang_charset),那就只靠黑白名单 - if not env.charset then - local ok = true -- 不在黑名单就算通过;白名单已经在上面处理过了 - if memo then memo[codepoint] = ok end - return ok - end - - -- 正常情况:用表滤镜查一遍 - local ch = utf8.char(codepoint) - local ok = env.charset:lookup(ch) ~= "" - - if memo then memo[codepoint] = ok end - return ok -end - ---[[ 整个 text 是否通过“字符集过滤” --- 规则:只检查「汉字」,非汉字(英文/符号)直接视为通过; --- 只要出现一个不在 charset 的汉字,就整条候选丢弃。 -local function in_charset(env, text) - if not env or not env.charset or not text or text == "" then - return true - end - for _, cp in utf8.codes(text) do - local ch = utf8.char(cp) - if wanxiang.IsChineseCharacter(ch) then - if not codepoint_in_charset(env, cp) then - return false - end +-- 检查交集 +local function check_intersection(db_attr, config_base_set) + if not db_attr or db_attr == "" then return false end + for i = 1, #db_attr do + -- 优化:使用局部变量 sub + local c = sub(db_attr, i, i) + if config_base_set[c] then + return true end end - return true -end]]-- --- 整个 text 是否通过“字符集过滤” --- 现在只对【单个汉字】做过滤,多字词/非汉字候选都直接通过 -local function in_charset(env, text) - if not env or not env.charset or not text or text == "" then - return true - end - -- 统计码点数,只要不是恰好 1 个码点,就不做过滤 - local cp, count = nil, 0 - for _, c in utf8.codes(text) do - cp = c - count = count + 1 - if count > 1 then - return true -- 多字词:直接通过 - end - end - if count ~= 1 or not cp then - return true - end - local ch = utf8.char(cp) - if not wanxiang.IsChineseCharacter(ch) then - return true -- 单个但不是汉字:直接通过 - end - -- 单个汉字:按 charset + 黑白名单过滤 - return codepoint_in_charset(env, cp) + return false end --- 当前 composition 的最后一个 seg 是否属于「反查/造词/标点」之类 -local function is_reverse_lookup_segment(env) - if not env or not env.engine or not env.engine.context then - return false - end - local comp = env.engine.context.composition - if not comp then - return false - end - local seg = comp:back() - if not seg then - return false - end - return seg:has_tag("wanxiang_reverse") - or seg:has_tag("add_user_dict") - or seg:has_tag("punct") -end --- 字符集过滤初始化 --- 从 schema 里读取 charsetlist / charsetblacklist + +-- 初始化字符集过滤配置 local function init_charset_filter(env, cfg) - -- 主字符集(表滤镜) + -- 1. 加载数据库文件 local dist = (rime_api.get_distribution_code_name() or ""):lower() - local charsetFile if dist == "weasel" then - -- 小狼毫:直接用相对路径,避免 Win 上绝对路径 + ReverseDb 的兼容问题 - charsetFile = "lua/charset.bin" + charsetFile = "lua/data/charset.reverse.bin" else - -- 其他前端:正常用 fallback 找到 user/shared 目录里的绝对路径 - charsetFile = wanxiang.get_filename_with_fallback("lua/charset.bin") or "lua/charset.bin" + charsetFile = wanxiang.get_filename_with_fallback("lua/data/charset.reverse.bin") or "lua/data/charset.reverse.bin" end - - env.charset = ReverseDb(charsetFile) - env.charset_memo = {} - env.charset_extra = {} -- 白名单 - env.charset_block = {} -- 黑名单 - - if not cfg then - return + + env.charset_db = nil + if ReverseDb then + local ok, db = pcall(function() return ReverseDb(charsetFile) end) + if ok and db then env.charset_db = db end end + env.db_memo = {} + env.filters = {} - -- 通用读取函数:把一个 list 里所有码点放入 target 表 - local function load_charset_list(key, target_table) - local ok_list, list = pcall(function() - return cfg:get_list(key) - end) - if not ok_list or not list or list.size <= 0 then - return - end + if not cfg then return end + + local root_path = "charset" + local list = cfg:get_list(root_path) + if not list then return end - for i = 0, list.size - 1 do - local item = list:get_value_at(i) - if item then - local v = item:get_string() - if v and #v > 0 then - for _, cp in utf8.codes(v) do - target_table[cp] = true + local list_size = list.size + for i = 0, list_size - 1 do + local entry_path = root_path .. "/@" .. i + + -- 解析开关 + local triggers = {} + local opts_keys = {"option", "options"} + for _, key in ipairs(opts_keys) do + local key_path = entry_path .. "/" .. key + local sub_list = cfg:get_list(key_path) + if sub_list then + for k = 0, sub_list.size - 1 do + local val = cfg:get_string(key_path .. "/@" .. k) + if val and val ~= "" then table.insert(triggers, val) end + end + else + if cfg:get_bool(key_path) == true then + table.insert(triggers, "true") + else + local val = cfg:get_string(key_path) + if val and val ~= "" and val ~= "true" then + table.insert(triggers, val) end end end end + + if #triggers > 0 then + -- 物理隔离变量 + local rule_base_set = {} + local rule_add = {} + local rule_ban = {} + + -- 解析 Base + local base_str = cfg:get_string(entry_path .. "/base") + if base_str and #base_str > 0 then + for j = 1, #base_str do + rule_base_set[sub(base_str, j, j)] = true + end + end + + -- 解析 Addlist (内联处理,避免闭包开销) + local function load_list_to_map(list_name, map) + local lp = entry_path .. "/" .. list_name + local sl = cfg:get_list(lp) + if sl then + for k = 0, sl.size - 1 do + local val = cfg:get_string(lp .. "/@" .. k) + if val and val ~= "" then + for _, cp in utf8_codes(val) do map[cp] = true end + end + end + end + end + + load_list_to_map("addlist", rule_add) + load_list_to_map("blacklist", rule_ban) + + table.insert(env.filters, { + options = triggers, + base_set = rule_base_set, + add = rule_add, + ban = rule_ban + }) + end end - -- charsetlist: 白名单 - load_charset_list("charsetlist", env.charset_extra) - -- charsetblacklist: 黑名单 - load_charset_list("charsetblacklist", env.charset_block) end --- 生命周期 +-- 核心判定逻辑 +local function codepoint_in_charset(env, ctx, codepoint, text) + if not env.charset_db then return true end + + local filters = env.filters + if not filters or #filters == 0 then return true end + + local active_options_count = 0 + + for _, rule in ipairs(filters) do + -- 检查开关 + local is_rule_active = false + for _, opt_name in ipairs(rule.options) do + if opt_name == "true" or ctx:get_option(opt_name) then + is_rule_active = true + break + end + end + + if is_rule_active then + active_options_count = active_options_count + 1 + + -- 1. 黑名单 (最高优先级) + if rule.ban[codepoint] then + -- 2. 白名单 (次高优先级) + elseif rule.add[codepoint] then + return true -- 显式白名单,直接放行 (Short-circuit) + + -- 3. Base 属性检查 + else + local attr = env.db_memo[text] + if attr == nil then + attr = env.charset_db:lookup(text) + env.db_memo[text] = attr + end + + if check_intersection(attr, rule.base_set) then + return true -- 属性符合,直接放行 (Short-circuit) + end + end + end + end + + -- 如果没有开启任何规则 -> 显示所有 + if active_options_count == 0 then + return true + end + + -- 开启了规则,但没有任何一个规则返回 true -> 隐藏 + return false +end + +local function in_charset(env, ctx, text) + if not text or text == "" then return true end + + local cp_count = 0 + local target_cp = nil + for _, cp in utf8_codes(text) do + cp_count = cp_count + 1 + if cp_count > 1 then return true end + target_cp = cp + end + + if cp_count == 0 or not target_cp then return true end + local char = utf8.char(target_cp) + + if not wanxiang.IsChineseCharacter(char) then return true end + + return codepoint_in_charset(env, ctx, target_cp, char) +end +local function is_reverse_lookup_segment(env) + if not env or not env.engine or not env.engine.context then return false end + local comp = env.engine.context.composition + if not comp or comp:empty() then return false end + local seg = comp:back() + return seg and (seg:has_tag("wanxiang_reverse") or seg:has_tag("add_user_dict") or seg:has_tag("punct")) +end + +-- 生命周期 function M.init(env) local cfg = env.engine and env.engine.schema and env.engine.schema.config or nil env.wrap_map = cfg and load_mapping_from_config(cfg) or default_wrap_map @@ -473,13 +511,13 @@ function M.init(env) local ok_win, win = pcall(function() return cfg:get_string("paired_symbols/sort_window") end) if ok_win and tonumber(win) then env.settings.sort_window = tonumber(win) end end - -- 字符集过滤 + -- 字符集过滤 init_charset_filter(env, cfg) end function M.fini(env) end --- 统一产出通道 +-- 统一产出通道 -- ctxs: -- charset : 字符集过滤 -- suppress_set : { [text] = true } 阻止镜像文本 @@ -493,8 +531,8 @@ local function emit_with_pipeline(cand, ctxs) local env = ctxs.env -- ① 字符集过滤:只有在 charset_strict = true 时才启用 - if ctxs.charset_strict and cand.text and cand.text ~= "" then - if not in_charset(env, cand.text) then + if ctxs.charset_active and cand.text and cand.text ~= "" then + if not in_charset(env, ctxs.ctx, cand.text) then return end end @@ -531,22 +569,19 @@ local function emit_with_pipeline(cand, ctxs) cand = ctxs.unify_tail_span(cand) yield(cand) end --- 主流程 +-- 主流程 function M.func(input, env) local ctx = env and env.engine and env.engine.context or nil local code = ctx and (ctx.input or "") or "" local comp = ctx and ctx.composition or nil - local option_extended = false - if ctx then - option_extended = ctx:get_option("charset_filter") or false - end - -- 当前是否在反查/自造词/标点段 + local in_reverse_seg = is_reverse_lookup_segment(env) -- 本次是否启用 charset 过滤 - local charset_strict = (env.charset ~= nil) - and (not option_extended) + -- 逻辑改为:只要有规则,且不在反查模式下,就激活检查。 + -- 具体到底显示还是隐藏,由 codepoint_in_charset 内部根据开关状态决定。 + local charset_active = (env.filters and #env.filters > 0) and (not in_reverse_seg) -- 状态清理 @@ -559,7 +594,7 @@ function M.func(input, env) local symbol = env.symbol local code_has_symbol = symbol and #symbol == 1 and (find(code, symbol, 1, true) ~= nil) - + -- segmentation:用于保持原有的包裹/分段逻辑 local last_seg, last_text, fully_consumed = nil, nil, false if code_has_symbol then @@ -624,6 +659,7 @@ function M.func(input, env) local emit_ctx = { env = env, + ctx = ctx, suppress_set = nil, suppress_mirror = env.suppress_mirror, code_ctx = code_ctx, @@ -631,7 +667,7 @@ function M.func(input, env) en_only = en_only, zh_only = zh_only, is_english = is_english_candidate, - charset_strict = charset_strict, + charset_active = charset_active, drop_sentence_after_completion = false, } @@ -659,7 +695,7 @@ function M.func(input, env) local start_pos = (last_seg and last_seg.start) or 0 local end_pos_full = (last_seg and last_seg._end) or #code - local base_text = left + local base_text = left local key = (right or ""):lower() if key ~= "" and env.wrap_map[key] then @@ -690,7 +726,7 @@ function M.func(input, env) return true end - -- 非分组路径 + -- 非分组路径 if not do_group then local idx = 0 for cand in input:iter() do @@ -706,7 +742,7 @@ function M.func(input, env) emit_ctx.drop_sentence_after_completion = true end end - + if env.locked and (not wrap_key) and env.cache then local start_pos = (last_seg and last_seg.start) or 0 local end_pos = (last_seg and last_seg._end) or #code diff --git a/wanxiang.schema.yaml b/wanxiang.schema.yaml index d373a66..81e393b 100644 --- a/wanxiang.schema.yaml +++ b/wanxiang.schema.yaml @@ -179,16 +179,48 @@ super_replacer: - lua/data/TWVariants.txt - lua/data/TWVariantsRevPhrases.txt +# 字符集过滤lua +# a,通用规范汉字表 +# b,GB2312, +# g,GBK, +# T,Big5,(台港澳常用) +# j,简体,OpenCC (t2s) +# f,通用繁体,OpenCC (s2t) +# h,香港繁体, OpenCC (s2hk) +# t,台湾繁体, OpenCC (s2tw) +# u,基本区,U+4E00 - U+9FFF +# A-I,扩展 A-I 区,U+3400 及各扩展区 (支持到 Ext-I) +# c,兼容区汉字 +# 你可以通过黑白名单微调你自己每个开关下面的字符集过滤清单,主数据库位于lua/charset.reverse.bin不可编辑 +# 你可以按上面提到的规则代号在base处填写上基础集,还可以在每一个开关的开白名单设置微调数据,就像默认添加的字符集过滤在8105基础上新增了一些 +# 你可以定义多个开关,多个开启状态的开关求并集,比如charset_filter开着,s2hk也开着,那么就会显示这两个集合的所有汉字 +# 优雅的地方在于s2hk开着,charset_filter关着 我们照样能使用 港繁能用到的所有字,是真正的本体,无关字会被过滤,而当都开着则是享受简体转换成繁体的后的结果 +# 这个设计真正的兼容了简繁转换与字符集过滤的矛盾,还能满足用户多种自定义需求,你可以在开关增加类别,并在charset下面新增option类去选择按照字区去过滤,等多种组合方式 +charset: + - option: charset_filter + base: a #可以填入多个类别如aj + addlist: + - "诶濛硷氽尛躝〇冇吔咗囧屌鲶芶咲畑垅𰻝𰻞" + blacklist: [] + - option: s2t + base: f + addlist: [] + blacklist: [] + - option: s2hk + base: h + addlist: [] + blacklist: [] + - option: s2tw + base: t + addlist: [] + blacklist: [] + # Tips 配置项 tips: # 禁用的 tips 类型,初始化 tips 数据库的时候会直接忽略相关规则,修改部署后生效 # 可选项为:偏旁,符号,化学式,时间,符号,组字,翻译,表情,货币,车牌 disabled_types: [] -#在8105基础上你可以通过黑白名单微调你自己的字符集过滤清单,主数据库位于lua/charset.bin不可编辑 -charsetlist: [] -charsetblacklist: [] - # 给 kp_number_processor 用的小键盘模式,能自动读取recognizer下面正则与之功能对齐 kp_number_mode: auto #小键盘数字处理逻辑 diff --git a/wanxiang_t9.schema.yaml b/wanxiang_t9.schema.yaml index 7b05043..bd3152a 100644 --- a/wanxiang_t9.schema.yaml +++ b/wanxiang_t9.schema.yaml @@ -78,7 +78,7 @@ engine: - table_translator@wanxiang_mixedcode #中英等混合词汇表导入 - table_translator@wanxiang_reverse #挂接部件组字和笔画反查 filters: - - reverse_lookup_filter@radical_reverse_lookup #部件拆字滤镜,放在super_comment前面,进一步被超级注释处理以获得拼音编码的提示 + - reverse_lookup_filter@reverse_lookup #部件拆字滤镜,放在super_comment前面,进一步被超级注释处理以获得拼音编码的提示 - lua_filter@*super_lookup #字词输入中反查辅助筛选 - lua_filter@*super_filter #功能太多详见Lua文件 - lua_filter@*super_replacer #用来替代OpenCC的处理器 @@ -88,6 +88,41 @@ engine: t9: isDisplayOriginalPreedit: false +# 字符集过滤lua +# a,通用规范汉字表 +# b,GB2312, +# g,GBK, +# T,Big5,(台港澳常用) +# j,简体,OpenCC (t2s) +# f,通用繁体,OpenCC (s2t) +# h,香港繁体, OpenCC (s2hk) +# t,台湾繁体, OpenCC (s2tw) +# u,基本区,U+4E00 - U+9FFF +# A-I,扩展 A-I 区,U+3400 及各扩展区 (支持到 Ext-I) +# c,兼容区汉字 +# 你可以通过黑白名单微调你自己每个开关下面的字符集过滤清单,主数据库位于lua/charset.reverse.bin不可编辑 +# 你可以按上面提到的规则代号在base处填写上基础集,还可以在每一个开关的开白名单设置微调数据,就像默认添加的字符集过滤在8105基础上新增了一些 +# 你可以定义多个开关,多个开启状态的开关求并集,比如charset_filter开着,s2hk也开着,那么就会显示这两个集合的所有汉字 +# 优雅的地方在于s2hk开着,charset_filter关着 我们照样能使用 港繁能用到的所有字,是真正的本体,无关字会被过滤,而当都开着则是享受简体转换成繁体的后的结果 +# 这个设计真正的兼容了简繁转换与字符集过滤的矛盾,还能满足用户多种自定义需求,你可以在开关增加类别,并在charset下面新增option类去选择按照字区去过滤,等多种组合方式 +charset: + - option: charset_filter + base: a #可以填入多个类别如aj + addlist: + - "诶濛硷氽尛躝〇冇吔咗囧屌鲶芶咲畑垅𰻝𰻞" + blacklist: [] + - option: s2t + base: f + addlist: [] + blacklist: [] + - option: s2hk + base: h + addlist: [] + blacklist: [] + - option: s2tw + base: t + addlist: [] + blacklist: [] # Tips 配置项 tips: @@ -289,7 +324,7 @@ wanxiang_reverse: tips: "〔反查:部件|笔画〕" # 部件拆字滤镜 -radical_reverse_lookup: +reverse_lookup: tags: [ wanxiang_reverse ] #起作用tag范围 overwrite_comment: true #是否覆盖其他提示 dictionary: wanxiang #带音调的词典 @@ -370,8 +405,9 @@ speller: - derive/^ng$/eng/ - xform/^n$/en/ - xform/^m$/me/ - - abbrev/^([a-z]).+$/\U$1/ - - abbrev/^([zcs]h).+$/\U$1/ + - derive/^(.*)$/\U$1/ + - abbrev/^([A-Z]).+$/$1/ + - abbrev/^([zcs]h).+$/$1/ - derive/^([nl])ve$/$1ue/ - derive/^([jqxy])u/$1v/ - derive/un$/uen/ @@ -382,8 +418,15 @@ speller: - derive/ong$/on/ - derive/ao$/oa/ - derive/([iu])a(o|ng?)$/a$1$2/ - - xform/^(.*)$/\L$1/ - - xlit/abcdefghijklmnopqrstuvwxyz/22233344455566677778889999/ + - derive/[ABC]/2/ + - derive/[DEF]/3/ + - derive/[GHI]/4/ + - derive/[JKL]/5/ + - derive/[MNO]/6/ + - derive/[PQRS]/7/ + - derive/[TUV]/8/ + - derive/[WXYZ]/9/ + grammar: language: wanxiang-lts-zh-hans