-
-
Save lotem/3076166 to your computer and use it in GitHub Desktop.
# default.custom.yaml | |
# 全局範圍識別輸入串爲 rime + 任意數字序列,以及形如 rimeime-1.2.3 的常用西文短語 | |
# 也可將本組 patch 寫入 <輸入方案ID>.custom.yaml 使這組規則僅在一款輸入方案中有效 | |
# | |
# 第一例,輸入 rime 之後,再輸入任意一個數字,則立即識別爲西文輸入 | |
# 再加上 default.yaml 原有的 email 規則,識別包含 @ 字符的郵箱,於是可以一氣呵成 [email protected] | |
# 第二例,輸入到 rimeime 時,立即識別爲西文輸入,並可跟隨任意位數字及指定的符號 | |
patch: | |
recognizer/patterns/rime123: "^rime[0-9]+$" | |
recognizer/patterns/rimeime: "^rimeime[-_.0-9]*$" |
有没有什么方法能把z键反查和临时英文结合起来呢,最理想的情况是我按完z键输入英文后按回车(退而求其次别的键也行),就可以自动把z去掉留下英文。再不济可以在候选栏中专门留个位置给英文。有可能实现这个功能吗?
@jiapeng123456 新加的segmentor要在matcher后面punct_segmentor前面,按一下分号出现tips里的提示才是真的改好了。你部属完可以到build/xxx.schema.yaml里看一眼有没有搞对。给你我的patch设置
"recognizer/patterns/quickeng": "^;.*$"
"engine/segmentors/@before 2": affix_segmentor@temp_en
temp_en:
tag: quickeng
prefix: ";"
tips: "〔英文〕"
前一段时间折腾了一下这个功能, 除了英文输入下因为easy_en辞典问题带来的一些问题之外(主要是英文输入下单引号作为省略符与作为选词键的冲突, 不过基本与本贴问题无关), 认为已经比较完美的重现了之前极点五笔的临时英文功能.
把配置分享一下.
engine:
Processors:
- ascii_composer
- key_binder
- recognizer
- speller
- punctuator
- selector
- navigator
- express_editor
segmentors:
- ascii_segmentor
- matcher
- abc_segmentor
- affix_segmentor@temp_en
- punct_segmentor
- fallback_segmentor
translators:
- punct_translator
- reverse_lookup_translator
- table_translator
- lua_translator@date_translator # 自定义系统变量输出
- lua_translator@calculator # 计算器:二元运算,coco 开头,如 coco56*34 coco24/1024
- table_translator@temp_en
filters:
- simplifier@tradition
- lua_filter@append_original_filter # append original text
- uniquifier
key_binder:
import_preset: default
bindings:
- { when: always, accept: Control+period, toggle: full_shape } # control+. switch中英标点
- { when: has_menu, accept: semicolon, send: 2 } # 候选2 用分号
- { when: has_menu, accept: apostrophe, send: 3 } # 候选3 用单引号
editor:
bindings:
Return: commit_composition
以上配置中, 修改了几个地方.
-
调整了key_binder和recognizer的顺序这个是因为我使用主流五笔输入法的分号键进行临时英文引导, 同时也使用分号键进行第二个备选词的选择. 所以需要让选词的key_binder的优先词比recogizer更高, 否则的话, 选词时的分号会被识别为分隔符. 从而无法使用分号选词.
-
如前面各位所述, 分别添加了
segmentor- affix_segmentor@temp_en
translators
- table_translator@temp_en
filters
- lua_filter@append_original_filter # append original text
其中引用的temp_en定义如下
temp_en: tag: starts_with_semicolon dictionary: easy_en enable_completion: true prefix: ";" tips: "[EN]" # 定义了一个affix_segmentor,affix_segmentor可以指定多个实例(所以前面声明时使用了@来指明具体是哪个项) # 声明使用的引导前缀(或后缀?)
这里添加了easy_en做为临时英文的外挂词库, 使用分号键引导, 其中的tag指定了 recognizer 所识别的模式如下
recognizer: import_preset: default patterns: # punct: "^/([0-9]+[a-z]*|[a-z]+)$" # 注意前方需要有4个空格,跟下面对齐 calculator: "^coco.*$" # 计算器 reverse_lookup: "^z[a-z]*$" # 反查词条的正则 starts_with_semicolon: ';[A-Za-z_<>\[\]\-\\]*$'
这里的 starts_with_semicolon定义的正则表达式对输入序列进行识别, 如果以分号开始的时候, 就会进入临时英文. 注意该临时英文中同时支持下划线, 尖括号, 方括号, 短线, 反斜杠等等不同的字符, 如果不需要的话可以根据自己的需要来删减.
-
支持挂载英文词库中不存在输入词的情况.
function append_original_filter(input, env) local composition = env.engine.context.composition local segmentation = composition:toSegmentation() local schema = env.engine.schema if(not composition:empty()) then local seg = composition:back() if schema.schema_id == "easy_en" then yield(Candidate("string", seg.start, seg._end, segmentation.input, "")) elseif segmentation.input:sub(1, 1) == ";" then yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), "")) end end for cand in input:iter() do yield(cand) end end
在rime.lua中添加以上函数. 因为我这个方案挂载了easy_en的这个词库, 那么在临时英文中进行输入的时候, 如果输入的是一个新单词, 那么挂载词库中没有该新词, 备选中不会出现, 这样就无法使用空格键进行上屏, 因此添加这个函数在备选列表中增加了了一个与输入串完全一致的备选. 同时因为输入序列实际上是以分号开始的, 所以需要路过第一个位置, 也就是下面两行.
elseif segmentation.input:sub(1, 1) == ";" then yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), ""))
这两行, 这两行判断当输入的序列以分号开头(临时英文)的时候, 生成的候选把分号去掉.
-
修改return键为commit_composition
editor: bindings: Return: commit_composition
这个主要是为了让回车上屏的时候, 同样上屏正常, 不会把前置的分号输出出来.
这样基本上就比较完美了.
前一段时间折腾了一下这个功能, 除了英文输入下因为easy_en辞典问题带来的一些问题之外(主要是英文输入下单引号作为省略符与作为选词键的冲突, 不过基本与本贴问题无关), 认为已经比较完美的重现了之前极点五笔的临时英文功能.
把配置分享一下.
engine: Processors: - ascii_composer - key_binder - recognizer - speller - punctuator - selector - navigator - express_editor segmentors: - ascii_segmentor - matcher - abc_segmentor - affix_segmentor@temp_en - punct_segmentor - fallback_segmentor translators: - punct_translator - reverse_lookup_translator - table_translator - lua_translator@date_translator # 自定义系统变量输出 - lua_translator@calculator # 计算器:二元运算,coco 开头,如 coco56*34 coco24/1024 - table_translator@temp_en filters: - simplifier@tradition - lua_filter@append_original_filter # append original text - uniquifier key_binder: import_preset: default bindings: - { when: always, accept: Control+period, toggle: full_shape } # control+. switch中英标点 - { when: has_menu, accept: semicolon, send: 2 } # 候选2 用分号 - { when: has_menu, accept: apostrophe, send: 3 } # 候选3 用单引号 editor: bindings: Return: commit_composition
以上配置中, 修改了几个地方.
调整了key_binder和recognizer的顺序这个是因为我使用主流五笔输入法的分号键进行临时英文引导, 同时也使用分号键进行第二个备选词的选择. 所以需要让选词的key_binder的优先词比recogizer更高, 否则的话, 选词时的分号会被识别为分隔符. 从而无法使用分号选词.
如前面各位所述, 分别添加了
segmentor
- affix_segmentor@temp_en
translators
- table_translator@temp_en
filters
- lua_filter@append_original_filter # append original text
其中引用的temp_en定义如下
temp_en: tag: starts_with_semicolon dictionary: easy_en enable_completion: true prefix: ";" tips: "[EN]" # 定义了一个affix_segmentor,affix_segmentor可以指定多个实例(所以前面声明时使用了@来指明具体是哪个项) # 声明使用的引导前缀(或后缀?)
这里添加了easy_en做为临时英文的外挂词库, 使用分号键引导, 其中的tag指定了 recognizer 所识别的模式如下
recognizer: import_preset: default patterns: # punct: "^/([0-9]+[a-z]*|[a-z]+)$" # 注意前方需要有4个空格,跟下面对齐 calculator: "^coco.*$" # 计算器 reverse_lookup: "^z[a-z]*$" # 反查词条的正则 starts_with_semicolon: ';[A-Za-z_<>\[\]\-\\]*$'
这里的 starts_with_semicolon定义的正则表达式对输入序列进行识别, 如果以分号开始的时候, 就会进入临时英文. 注意该临时英文中同时支持下划线, 尖括号, 方括号, 短线, 反斜杠等等不同的字符, 如果不需要的话可以根据自己的需要来删减.
支持挂载英文词库中不存在输入词的情况.
function append_original_filter(input, env) local composition = env.engine.context.composition local segmentation = composition:toSegmentation() local schema = env.engine.schema if(not composition:empty()) then local seg = composition:back() if schema.schema_id == "easy_en" then yield(Candidate("string", seg.start, seg._end, segmentation.input, "")) elseif segmentation.input:sub(1, 1) == ";" then yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), "")) end end for cand in input:iter() do yield(cand) end end
在rime.lua中添加以上函数. 因为我这个方案挂载了easy_en的这个词库, 那么在临时英文中进行输入的时候, 如果输入的是一个新单词, 那么挂载词库中没有该新词, 备选中不会出现, 这样就无法使用空格键进行上屏, 因此添加这个函数在备选列表中增加了了一个与输入串完全一致的备选. 同时因为输入序列实际上是以分号开始的, 所以需要路过第一个位置, 也就是下面两行.
elseif segmentation.input:sub(1, 1) == ";" then yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), ""))
这两行, 这两行判断当输入的序列以分号开头(临时英文)的时候, 生成的候选把分号去掉.
修改return键为commit_composition
editor: bindings: Return: commit_composition
这个主要是为了让回车上屏的时候, 同样上屏正常, 不会把前置的分号输出出来.
这样基本上就比较完美了.
确实比较完美实现了临时英文,但是如果确实需要分号时怎么办呢?极点和qq五笔中印象中是如果需要分号了,就按两个分号,上屏一个分号。
engine:
Processors:
这里面的P应该小写。
engine: Processors:
这里面的P应该小写。
嗯, 这是个typo
@redleafnew 感谢反馈, 之前没有注意到, 对, 这里有一个bug. 修改了一下.
把上面的rime.lua中的函数, 中间的做一个修改. 改为下面的函数.
function append_original_filter(input, env) local composition = env.engine.context.composition local segmentation = composition:toSegmentation() local schema = env.engine.schema if(not composition:empty()) then local seg = composition:back() if schema.schema_id == "easy_en" then yield(Candidate("string", seg.start, seg._end, segmentation.input, "")) elseif segmentation.input:sub(1, 1) == ";" and segmentation.input:len() > 1 then yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), "")) end end for cand in input:iter() do yield(cand) end end这样就可以实现, 双击分号输入分号了.
其它地方需要修改吗?好像不行啊,用原来的代码,我把\
定义为分号了,也定义了自定义短语,zf
输出为分号。
@redleafnew 具体不很确定, 看起来你的符号字义和我不一样, 我这边按下分号键, 就算不使用这一套字义, 应该也只有一个备选, 你这个还有个全角的备选在. 猜是因为这个.
哪个配置中可以看到吗?我基本上用得这个配置:https://github.com/KyleBing/rime-wubi86-jidian
挂载的这个码表:https://github.com/GuoBinyong/wubixinshiji
我只用了jidian五笔的配置, 你查下. 应该是在default.custom.yaml中, 把分号相关的行注掉.
就是这种 ";" : { commit: ";" }
我试了一下, 两个分号上屏我也没搞定, 应该有一个lua确认函数, 我现在不知道是啥, 不过输入分号, 目前可以输入一个分号, 然后使用空格或者回车来解决.
连续多个分号, 会有问题.
这里问题的核心是, 不能触发候选框, 不然分号的语义就成为了第二选词键而不是分号内容本身.
所以必须在lua函数中处理. 同时第二个分号后面的分号必须被所有模式组捕获. 理想情况是这样的.
starts_with_semicolon: ';[;A-Za-z_<>\[\]\-+=~@.#?!%^&$*()\\]*$'
function append_original_filter(input, env)
local envengine = env.engine
local composition = envengine.context.composition
local segmentation = composition:toSegmentation()
local schema = envengine.schema
if(not composition:empty()) then
local seg = composition:back()
if schema.schema_id == "easy_en" then
yield(Candidate("string", seg.start, seg._end, segmentation.input, ""))
elseif segmentation.input:sub(1, 1) == ";" and segmentation.input:len() > 1 then
if segmentation.input:sub(2, 2) == ";" then
envengine:commit_text(";")
return
else
yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), ""))
end
-- yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), ""))
end
end
for cand in input:iter() do
yield(cand)
end
end
但是我试了一个, commit_text这个函数应该不是最终上屏键, 这样做的话, 输入序列会有一个分号被append_original_filter这个处理器后面的处理器处理. 于是出现输入冗余.
目前暂时只能用.
starts_with_semicolon: ';[A-Za-z_<>\[\]\-+=~@.#?!%^&$*()\\]*$'
同时
function append_original_filter(input, env)
local envengine = env.engine
local composition = envengine.context.composition
local segmentation = composition:toSegmentation()
local schema = envengine.schema
if(not composition:empty()) then
local seg = composition:back()
if schema.schema_id == "easy_en" then
yield(Candidate("string", seg.start, seg._end, segmentation.input, ""))
elseif segmentation.input:sub(1, 1) == ";" and segmentation.input:len() > 1 then
yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), ""))
end
end
for cand in input:iter() do
yield(cand)
end
end
来搞. 如果要输入分号 就使用 分号+空格或分号加回车来输入
好的, 你这个(同时存在半角和全角)确实无法做到双分号上屏, 因为这里有一个二元语义, 逻辑上冲突了, 第二个分号到底是要上屏备选2, 全角分号. 还是第二个分号只想做为一个顶格键直接上屏.
感谢反馈, 这样我也修复了一个自己使用的bug.
好的, 你这个(同时存在半角和全角)确实无法做到双分号上屏, 因为这里有一个二元语义, 逻辑上冲突了, 第二个分号到底是要上屏备选2, 全角分号. 还是第二个分号只想做为一个顶格键直接上屏.
是用来上屏中文(全角)分号的,我没有用冒号和分号作为候选上屏的。用的以前极点的逻辑,1个分号临时英文,2个分号输入分号,有时输入中文时确实需要分号。
搞定了. 对我这边是完美了. 不过不知道你适用不适用,
放出来供其他朋友参考.
参见上面的考虑.
最后的模式组
starts_with_semicolon: ';[;A-Za-z_<>\[\]\-+=~@.#?!%^&$*()\\]*$'
最后的函数
function append_original_filter(input, env)
local envengine = env.engine
local envcontext = envengine.context
local composition = envcontext.composition
local segmentation = composition:toSegmentation()
local schema = envengine.schema
if(not composition:empty()) then
local seg = composition:back()
if schema.schema_id == "easy_en" then
yield(Candidate("string", seg.start, seg._end, segmentation.input, ""))
elseif segmentation.input:sub(1, 1) == ";" and segmentation.input:len() > 1 then
if segmentation.input:sub(2, 2) == ";" then
envengine:commit_text(";")
envcontext:clear()
return
else
yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), ""))
end
end
end
for cand in input:iter() do
yield(cand)
end
end
这样就可以使用分号上屏分号了, 空格, 回车也同样上屏分号.
作者大大,麻烦整理一下最终版?从最开始的评论依次跟着评论调整下来,效果还是差强人意。
这两天制作空明码并击方案时想要实现这个英文引导输入的功能,查了下最后实现了,放在这里供参考
engine: processors: - recognizer # 确保启用了recognizer segmentors: # 添加下面这项 - affix_segmentor@temp_en recognizer: patterns: # 添加一个标签 starts_with_single_quote_tag: "^'.*$" # 向recognizer指明 要匹配的模式和标注的tag名,tag可以为后面translator等指定作用分段范围 # 声明了一种标签的模式:由单引号打头 temp_en: tag: starts_with_single_quote_tag prefix: "'" #suffix: ";" tips: "〔 英文 〕" # 定义了一个affix_segmentor,affix_segmentor可以指定多个实例(所以前面声明时使用了@来指明具体是哪个项) # 声明使用的引导前缀(或后缀?)好像是在贴吧看到的,帖子链接如下: 如何配置敲分号后进入临时英文?
这个方案模仿原来的搜狗输入法的 v 英文模式挺好。但是输入 @ 的时候会打断这个模式(估计是被 email 模式给打断了),然后就是按空格后,能不能让它自动在后面追加一个空格呢。不然得按两次空格,一次上屏一次是单词之间的空格。
我试了一下, 两个分号上屏我也没搞定, 应该有一个lua确认函数, 我现在不知道是啥, 不过输入分号, 目前可以输入一个分号, 然后使用空格或者回车来解决.
连续多个分号, 会有问题.
这里问题的核心是, 不能触发候选框, 不然分号的语义就成为了第二选词键而不是分号内容本身.
所以必须在lua函数中处理. 同时第二个分号后面的分号必须被所有模式组捕获. 理想情况是这样的.
starts_with_semicolon: ';[;A-Za-z_<>\[\]\-+=~@.#?!%^&$*()\\]*$'function append_original_filter(input, env) local envengine = env.engine local composition = envengine.context.composition local segmentation = composition:toSegmentation() local schema = envengine.schema if(not composition:empty()) then local seg = composition:back() if schema.schema_id == "easy_en" then yield(Candidate("string", seg.start, seg._end, segmentation.input, "")) elseif segmentation.input:sub(1, 1) == ";" and segmentation.input:len() > 1 then if segmentation.input:sub(2, 2) == ";" then envengine:commit_text(";") return else yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), "")) end -- yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), "")) end end for cand in input:iter() do yield(cand) end end但是我试了一个, commit_text这个函数应该不是最终上屏键, 这样做的话, 输入序列会有一个分号被append_original_filter这个处理器后面的处理器处理. 于是出现输入冗余.
目前暂时只能用.
starts_with_semicolon: ';[A-Za-z_<>\[\]\-+=~@.#?!%^&$*()\\]*$'同时
function append_original_filter(input, env) local envengine = env.engine local composition = envengine.context.composition local segmentation = composition:toSegmentation() local schema = envengine.schema if(not composition:empty()) then local seg = composition:back() if schema.schema_id == "easy_en" then yield(Candidate("string", seg.start, seg._end, segmentation.input, "")) elseif segmentation.input:sub(1, 1) == ";" and segmentation.input:len() > 1 then yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), "")) end end for cand in input:iter() do yield(cand) end end来搞. 如果要输入分号 就使用 分号+空格或分号加回车来输入
我参考了另一个常见问题,就是如何输入当前时间的,解决方法是提供了一个 lua 脚本来提供“时间”的候选词。我实验了以下,发现它也可以用来模拟原来搜狗输入法早期的 v 模式(临时输入英文模式,而非现在的大写数字输入的 v 模式)。可以在 rime.lua 中这样写:
function time_translator(input, seg)
if (input == "date" or input == "rq") then
--[[ 用 `yield` 产生一个候选项
候选项的构造函数是 `Candidate`,它有五个参数:
- type: 字符串,表示候选项的类型
- start: 候选项对应的输入串的起始位置
- _end: 候选项对应的输入串的结束位置
- text: 候选项的文本
- comment: 候选项的注释
--]]
local cand = Candidate("date", seg.start, seg._end, os.date("%Y-%m-%d"), "(iso)")
cand.quality = 1
yield(cand)
local cand2 = Candidate("date", seg.start, seg._end, os.date("%Y 年 %m 月 %d 日"), "")
cand2.quality = 2
yield(cand2)
elseif (input == "now" or input == "sj") then
local cand = Candidate("time", seg.start, seg._end, os.date("%Y-%m-%d %H:%M:%S"), "(iso)")
cand.quality = 1
yield(cand)
local cand2 = Candidate("time", seg.start, seg._end, os.date("%Y 年 %m 月 %d 日 %H:%M:%S"), "")
cand2.quality = 2
yield(cand2)
local cand3 = Candidate("time", seg.start, seg._end, os.date("%H:%M:%S"), "")
cand3.quality = 3
yield(cand3)
--[[ V 模式输入英文 --]]
elseif (string.len(input) > 1 and string.sub(input, 1, 1) == "v") then
local cand = Candidate("string", seg.start, seg._end, string.sub(input, 2), "[EN]")
cand.quality = 1
yield(cand)
--[[ "d" 的首个候选词为 "=" --]]
elseif (input == "d") then
local cand = Candidate("string", seg.start, seg._end, "=", "<跳转到原帖>")
cand.quality = 1
yield(cand)
end
end
然后把这个脚本中的函数加入到 <schema_name>.custom.yaml 中,再重新部署,就可以在输入 v 以后进入临时输入英文的状态了:
__merge:
engine:
translators/+:
- lua_translator@time_translator
但是一旦输入空格,就会使得输入字符上屏,因为空格键已经被定义成上屏了。所以在 v 模式里连续输入英文句子目前还是不行的。
function append_original_filter(input, env)
local envengine = env.engine
local envcontext = envengine.context
local composition = envcontext.composition
local segmentation = composition:toSegmentation()
local schema = envengine.schema
if(not composition:empty()) then
local seg = composition:back()
if schema.schema_id == "easy_en" then
yield(Candidate("string", seg.start, seg._end, segmentation.input, ""))
elseif segmentation.input:sub(1, 1) == ";" and segmentation.input:len() > 1 then
if segmentation.input:sub(segmentation.input:len(), segmentation.input:len()) == ";" then
envengine:commit_text(string.sub(segmentation.input, 2))
-- envengine:commit_text(";")
envcontext:clear()
return
else
yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), ""))
end
end
end
for cand in input:iter() do
yield(cand)
end
end
return append_original_filter
我把函数改了一行,可以按分号后将前边输入的英文也顶屏了。
@gfgkmn 大牛厉害,完美解决,谢谢。
输入带点的会重复,如输入 分号data.doc上屏的会是datadata.data.doc
输入带点的会重复,如输入 分号data.doc上屏的会是datadata.data.doc
-- 原始字符串输出,用来实现分号临时英文,再输入分号顶屏上字
function append_original_filter(input, env)
local envengine = env.engine
local envcontext = envengine.context
local composition = envcontext.composition
local segmentation = composition:toSegmentation()
local schema = envengine.schema
if(not composition:empty()) then
local seg = composition:back()
if schema.schema_id == "easy_en" then
yield(Candidate("string", seg.start, seg._end, segmentation.input, ""))
elseif segmentation.input:sub(1, 1) == ";" and segmentation.input:len() > 1 then
if segmentation.input:sub(segmentation.input:len(), segmentation.input:len()) == ";" then
envengine:commit_text(string.sub(segmentation.input, 2))
-- envengine:commit_text(";")
envcontext:clear()
return
-- else
-- yield(Candidate("space", seg.start, seg._end, string.sub(segmentation.input, 2), ""))
end
end
end
for cand in input:iter() do
yield(cand)
end
end
return append_original_filter
对lua不熟悉,暂时改成这样先用着了。
谢谢。可能是我设置的问题,这次不出现点了,直接上屏的是句号。
有一个注意事项:engine/segmentors 里把 affix_segmentor@temp_en 放在 punct_segmentor 前面,这样才会有效果