快速录入,是任何一个输入法,以及输入人员(无论是否专业)的追求目标之一。现实中,由于各种输入法在录入文本时,都无法完全避免重码的问题,所以在输入过程中都或多或少的需要进行选字/选词操作。这在根本上导致了在快速录入场景下,无法根本上避免错误词汇上屏;另一种错误是在快速击键的过程中,存在错误的击键,这更是无法避免的会录入错误的词汇。
当代办公室场景下,电子办公是绝对的主流,文本沟通,电子会议,都面临着大量的文本录入的需求。那么在发生录入错误时,如果上屏的词汇是 不雅 或者 不恰当 的词汇,则会面临着社死的尴尬。
👇如下,如果我们快速的输入了 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 = flgsysInfoRes.setDbg(flg)print('phraseReplace dbgFlg is '..tostring(dbgFlg))
end--将文档处理成行数组
local function files_to_lines(...)if dbgFlg thenprint("--->files_to_lines called here")endlocal tab=setmetatable({},{__index=table})local index=1for i,filename in next,{...} dolocal fn = io.open(filename)if fn thenfor line in fn:lines() doif not line or #line > 0 thentab:insert(line)endendfn:close()endendif dbgFlg thenprint("--->files_to_lines completed here")endreturn tab
endlocal function dictload(...) -- filename)if dbgFlg thenprint("-->dictload called here")endlocal lines=files_to_lines(...)local thisDict={}for i,line in next ,lines doif not line:match("^%s*#") then -- 第一字 # 为注释行local key,val = string.match(line,"(.+)\t(.+)")if nil == key thenkey = string.match(line,'(%S+)')val = ''endif nil ~= key then--此处,如果key 已经存在,则使用后来的值顶替旧的值thisDict[key] = valendendendif dbgFlg thenprint("-->dictload completed here")endreturn thisDict
end--===========================test========================
local function test(printPrefix)if nil == printPrefix thenprintPrefix = ' 'endif dbgFlg thenprint('phraseReplace test starting...')sysInfoRes.test(printPrefix..' ')for k,v in pairs(dict) doif dbgFlg thenprint(printPrefix..k..'\t'..v)endendend
end--获取字典中的phrase
local function getShownPhrase(k)if nil == k thenreturn ''elseif '' == k thenreturn ''end--尝试获取 dictPhraseList 中 k 的列表return dict[k]
endfunction M.init(...)local files={...}--文件名不支持中文,其中 # 开始的行为注释行table.insert(files,"phraseReplace.txt")for i,v in next, files dofiles[i] = currentDir().."/".. venddict= dictload(table.unpack(files))--抛出功能函数M.getShownPhrase = getShownPhraseM.userName = userNameM.setDbg = setDbgM.test = test
endM.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 = 250local function phraseReplace_Filter(input, env)--获取选项敏感词替换开关状态local on = env.engine.context:get_option("phraseReplace")local candsHasBeenHidden = {}local candStart,candEndfor cand in input:iter() docandStart = cand.startcandEnd = cand._endlocal candTxt = cand.text:gsub("%s","") or ""phraseShown = getShownPhrase(candTxt)if nil ~= phraseShown then--不管是否开启选项替换,如果该选项是被命中的替换项,则加上替换标记 👙cand.comment = '👙'..cand.commentif '' ~= phraseShown thenif on then--如果开启了选项替换功能,且存在替换内容yield(Candidate("word", cand.start, cand._end, phraseShown, cand.comment))else--如果未开启选项替换功能yield(cand)endelseif on then--如果开启了选项替换功能,且这个选项应该被隐藏table.insert(candsHasBeenHidden,candTxt)else--如果未开启选项替换功能yield(cand)endendelseyield(cand)endend--如果有被隐藏的选项,则抛出一个 * 选项提示if 0 < #candsHasBeenHidden thenyield(Candidate("word", candEnd-1, candEnd, '*', '👙'))end
endreturn 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中州韵小狼毫敏感词脱敏滤镜 取用。
另同步gitHub
仓库:dyyRime
效果欣赏
敏感词不太适合进行对比展示,此处展示一下脱敏后的效果吧。
以上👆,如果你也用的是五笔,你应该能猜到脱敏前是什么字/词。
小结
以上就是今天的分享,我们通过 1
个字典文档,5
个 lua
脚本文档,在rime
中州韵小狼毫输入法中配置了一个敏感词脱敏滤镜。通过对这 6
个文档的逐一讲解,相信大家也能够在理解每个文档的作用和使用方法的基础上可以灵活运用和配置更强大的功能词库。