快速录入,是任何一个输入法,以及输入人员(无论是否专业)的追求目标之一。现实中,由于各种输入法在录入文本时,都无法完全避免重码的问题,所以在输入过程中都或多或少的需要进行选字/选词操作。这在根本上导致了在快速录入场景下,无法根本上避免错误词汇上屏;另一种错误是在快速击键的过程中,存在错误的击键,这更是无法避免的会录入错误的词汇。
当代办公室场景下,电子办公是绝对的主流,文本沟通,电子会议,都面临着大量的文本录入的需求。那么在发生录入错误时,如果上屏的词汇是 不雅 或者 不恰当 的词汇,则会面临着社死的尴尬。
👇如下,如果我们快速的输入了 koko
,在 五笔・拼音 输入方案下,会有一个 咪咪 的词条出现在候选列表中,如果不慎上屏了 咪咪 并发送了聊天,则瞬间社死。
👇如下,那如果我们把此类词汇进行脱敏处理成 * 号,并在排序上使其靠后处理,则一方面避免了误选敏感词项,另一方面即使误选误发了,影响也完全可控。
在 rime
中州韵小狼毫输入法中,我们可以通过 lua
定义 Filter
滤镜来实现以上敏感词脱敏的功能。
phraseReplace.txt
首先,我们需要有一个文档来整理/管理敏感词,以使Filter
滤镜知道哪些字/词是敏感词,我们使用文档 phraseReplace.txt
来管理敏感词。phraseReplace.txt
文档的内容截取如下👇:
👆上图中,我们可以看到:
- 文档
phraseReplace.txt
可以使用符号#
来进行注释 - 文档
phraseReplace.txt
第一列是要脱敏的敏感词 - 文档
phraseReplace.txt
第二列是脱敏后的替代词,如果没有,则默认处理成 * 号
phraseReplaceModule.lua
有了 phraseReplace.txt
文档,我们还需要一个 lua
脚本来将 phraseReplace.txt
文档里的敏感词加载到 lua
程序中。phraseReplaceModule.lua
脚本文档中所定义的脚本就是负责加载文档 phraseReplace.txt
中的内容的。phraseReplaceModule.lua
脚本内容如下👇:
-- phraseReplaceModule.lua
-- Copyright (C) 2023 yaoyuan.dou <douyaoyuan@126.com>
local M={}
local dict={}
local dbgFlg = false
--引入系统变更处理模块
local ok, sysInfoRes = pcall(require, 'sysInfo')
local currentDir = sysInfoRes.currentDir
local userName = sysInfoRes.userName
--设置 dbg 开关
local function setDbg(flg)
dbgFlg = flg
sysInfoRes.setDbg(flg)
print('phraseReplace dbgFlg is '..tostring(dbgFlg))
end
--将文档处理成行数组
local function files_to_lines(...)
if dbgFlg then
print("--->files_to_lines called here")
end
local tab=setmetatable({},{__index=table})
local index=1
for i,filename in next,{...} do
local fn = io.open(filename)
if fn then
for line in fn:lines() do
if not line or #line > 0 then
tab:insert(line)
end
end
fn:close()
end
end
if dbgFlg then
print("--->files_to_lines completed here")
end
return tab
end
local function dictload(...) -- filename)
if dbgFlg then
print("-->dictload called here")
end
local lines=files_to_lines(...)
local thisDict={}
for i,line in next ,lines do
if not line:match("^%s*#") then -- 第一字 # 为注释行
local key,val = string.match(line,"(.+)\t(.+)")
if nil == key then
key = string.match(line,'(%S+)')
val = ''
end
if nil ~= key then
--此处,如果key 已经存在,则使用后来的值顶替旧的值
thisDict[key] = val
end
end
end
if dbgFlg then
print("-->dictload completed here")
end
return thisDict
end
--===========================test========================
local function test(printPrefix)
if nil == printPrefix then
printPrefix = ' '
end
if dbgFlg then
print('phraseReplace test starting...')
sysInfoRes.test(printPrefix..' ')
for k,v in pairs(dict) do
if dbgFlg then
print(printPrefix..k..'\t'..v)
end
end
end
end
--获取字典中的phrase
local function getShownPhrase(k)
if nil == k then
return ''
elseif '' == k then
return ''
end
--尝试获取 dictPhraseList 中 k 的列表
return dict[k]
end
function M.init(...)
local files={...}
--文件名不支持中文,其中 # 开始的行为注释行
table.insert(files,"phraseReplace.txt")
for i,v in next, files do
files[i] = currentDir().."/".. v
end
dict= dictload(table.unpack(files))
--抛出功能函数
M.getShownPhrase = getShownPhrase
M.userName = userName
M.setDbg = setDbg
M.test = test
end
M.init()
return M
👆以上的脚本中,我们将指定的 phraseReplace.txt
文档的内容加载到一个 dict
字典中,并给出了一个 getShownPhrase
的方法来对字典 dict
进行查询。
phraseReplace_Filter.lua
phraseReplace_Filter.lua
脚本将上述 phraseReplaceModule.lua
所定义的模块封装成了 Filter
方法,以便可以在 rime
引擎中正确的被调用和运行。phraseReplace_Filter.lua
文档内的脚本如下👇:
-- phraseReplace_Filter.lua
-- Copyright (C) 2023 yaoyuan.dou <douyaoyuan@126.com>
--[[
这个过滤器的主要作用是,对于候选项中命中的选项(OR 内容),用其指定的内容来代替,如果没有指定,则使用 * 替换
由于这个过滤器会改变候选项的内容(主要是会减少候选项数量),所以请将这个过滤器放在其它过滤器的最前端使用
]]
local phraseShown = ''
local ok, res = pcall(require, 'phraseReplaceModule')
local getShownPhrase = res.getShownPhrase
--最长的comment长度限制
local maxLenOfComment = 250
local function phraseReplace_Filter(input, env)
--获取选项敏感词替换开关状态
local on = env.engine.context:get_option("phraseReplace")
local candsHasBeenHidden = {}
local candStart,candEnd
for cand in input:iter() do
candStart = cand.start
candEnd = cand._end
local candTxt = cand.text:gsub("%s","") or ""
phraseShown = getShownPhrase(candTxt)
if nil ~= phraseShown then
--不管是否开启选项替换,如果该选项是被命中的替换项,则加上替换标记 👙
cand.comment = '👙'..cand.comment
if '' ~= phraseShown then
if on then
--如果开启了选项替换功能,且存在替换内容
yield(Candidate("word", cand.start, cand._end, phraseShown, cand.comment))
else
--如果未开启选项替换功能
yield(cand)
end
else
if on then
--如果开启了选项替换功能,且这个选项应该被隐藏
table.insert(candsHasBeenHidden,candTxt)
else
--如果未开启选项替换功能
yield(cand)
end
end
else
yield(cand)
end
end
--如果有被隐藏的选项,则抛出一个 * 选项提示
if 0 < #candsHasBeenHidden then
yield(Candidate("word", candEnd-1, candEnd, '*', '👙'))
end
end
return phraseReplace_Filter
👆以上的脚本中,我们返回了一个 phraseReplace_Filter
的滤镜方法。该方法可以对候选项逐一进行检查并进行脱敏处理。
💣注意:
phraseReplace.txt
、phraseReplace_Filter.lua
、phraseReplaceModule.lua
以及被引用的模块脚本 sysInfo.lua
,均应在 用户文件夹下的 lua 文件夹内:
rime.lua
想必大家对 rime.lua
已经不陌生了,在 rime.lua
文档中,我们添加 phraseReplace_Filter
滤镜接口,如下👇:
help_translator = require("help")
inputShow_translator = require("inputShow")
inputShow_Filter = require("inputShow_Filter")
Upper_Filter = require("Upper_Filter")
dic_4w_Filter = require("dic_4w_Filter")
phraseReplace_Filter = require("phraseReplace_Filter")
wubi_pinyin.custom.yaml
以上,我们已经完成了所有滤镜的功能定义,我们只需要在我们所使用的输入方案中配置 phraseReplace_Filter
滤镜,即可使用 phraseReplace_Filter
滤镜所提供的敏感词脱敏功能了。此处以 五笔・拼音 输入方案为例,我们在 五笔・拼音 输入方案的方案文档 wubi_pinyin.schema.yaml
的补丁文档 wubi_pinyin.custom.yaml
中增加配置一个 lua
滤镜 phraseReplace_Filter
,如下👇:
patch:
engine/filters: # 设置以下filter
- simplifier
- lua_filter@inputShow_Filter # 这个过滤器用于在特定场景下,增加候选项
# 上面的滤镜会调整候选词选项,或者增加,或者减少。原则上说,减少的滤镜,请放在前端
- lua_filter@phraseReplace_Filter # 词语替换滤镜,针对一些指定的关键字,将其替换为指定的内容,或者当没有指定内容时,替换为 *
# 上面的滤镜会减少或者改变候先词选项
- uniquifier # 过滤重复候选项,依赖 simplifier
phraseReplace.txt
/phraseReplaceModule.lua
/phraseReplace_Filter.lua
/sysInfo.lua
/rime.lua
/wubi_pinyin.custom.yaml
文档
👆上述 6 个配置文档,你可以在 rime中州韵小狼毫敏感词脱敏滤镜 取用。
交互欣赏
敏感词不太适合进行对比展示,此处展示一下脱敏后的效果吧。
以上👆,如果你也用的是五笔,你应该能猜到脱敏前是什么字/词。
小结
以上就是今天的分享,我们通过 1
个字典文档,5
个 lua
脚本文档,在rime
中州韵小狼毫输入法中配置了一个敏感词脱敏滤镜。通过对这 6
个文档的逐一讲解,相信大家也能够在理解每个文档的作用和使用方法的基础上可以灵活运用和配置更强大的功能词库。