Loading
0

灼雪|十二个小时写一个属于你自己的输入法

Yours--不仅仅是一个柚子输入法



歌曲欣赏

子弥-灼雪


写在前面的话

“没钱上网的花大爷”之前所写的文章,以及收集的脚本,大抵都是追求一个使用性,可编辑性,即下载就能用,就能实现脚本的功能,不需要用户所了解脚本的工作原理等等。所以缺少对脚本内部的语法以及一些代码的解释说明,在这里我就此类文章分类到《谢芳菲》系列里面,谢芳菲取自歌名,各位ahkor可以细细欣赏一下。

   而今天的篇文章,加入对其代码的解释说明,方便各位的理解与学习,希望能在这篇文章里面学到知识,并能自我编写类似的脚本或者实现类似的功能,所以我为其分类为《灼雪》,同样是一首歌曲,但是我希望的是灼其雪,得其意,知其用,望各位能学到知识,会其用法。


简介

这篇文章收集自简书的srf作者,他写了15篇文章来解释了他的柚子输入法的开发过程,以及开发过程中的某些代码的用法,外加一篇关于输入法里面的五笔输入的四码唯一自动上屏的功能的文章。

而现在“没钱上网的花大爷”对上述的15篇文章的整合引用,让内容更加紧凑结实,方便各位的学习。

对于autohotkey(AHK)来说,拥有着其特有优点,其一就是变量定义定义的方便比如  a=工 这在其他的编程语言里面绝对是不可思议的,引用srf作者的话:”Autohotkey非常适合用来模拟输入法,除了它本身能简单和轻易模拟键盘的键击外,还源于它相比传统编程语言来说,相对来说不正规的变量赋值方式。不过,如果你有学过其他语言,然后看到“a=工”这种变量赋值方式,估计有点崩溃。”所以ahk非常适合对输入法的编写,比如文章提到的柚子输入法,以及河许人编写的功能强大的影子输入法 ,再读完这篇文章后,各位ahkor也能写个属于自己的输入法,不仅仅是柚子输入法,或者是影子输入法了。

下面开始打造一个属于自己的输入法。。。


柚子输入法

(花大爷只进行红色标注解读)

(蓝色为作者解释)

第一小时:关于对按键的屏蔽

1、打开Autohotkey.ahk,输入下面的代码:一个字母a加两个英文冒号。(对于ahkor来说,打开SciTE4AutoHotKey,新建一个脚本)

a::

2、保存,保存,保存,一定要先保存。

3、运行Autohotkey.exe,系统任务栏上会出现程序图标,鼠标移动到图标上,会出现提示信息:Autohotkey.ahk,说明该文件的代码已经顺利载入。(在SciTE4AutoHotKey里面按F5 运行脚本即可运行)

4、在任何可以输入的界面,点击键盘上的a键,你会发现:键盘没反应。

恭喜,你成功干掉了a键!只要程序处于运行状态,无论什么时候按a键,它都没有反应。建议你先退出程序压压惊,太TM吓人了。

便携绿色免安装的autohotkey.exe主程序,启动的时候,默认调用同目录下的同名.ahk文件。所以文件名你可以自由命名,只要保证一样就行了。比如可以改为sos.exe和sos.ahk)

对于某些时候屏蔽win键的写法:win::return

可令win键失效



第二小时:赋予按键新功能

我们现在要改一下代码,有个事情要先说下:每次修改完代码,先保存,然后reload(重新载入),新的代码才会生效。

任务栏程序图标的右键菜单

现在把代码改一下:

Lshift::srf_mode := !srf_mode

注意:最前面的数字(1.2.3.4.5)是gvim程序自动显示的行号,不属于代码内容。

1、在第3行和第5行,我们做了一个用变量srf_mode来做了一个模式,把第4行重定义a键的代码围起来。(这个语法格式非常重要,后面我们经常要用到)

2、在第1行,我们给srf_mode模式设置了一个开关Lshift键(即键盘左边的shift键)。

点击一下Lshift键,开启模式,这时候a键死球了,再点击一下Lshift键,关闭模式,a键恢复原来的功能。不断点击Lshift键,模式就不断在开启和关闭之间循环切换。胡乱点击几次Lshift后,除非你点击a键看下结果, 否则你都不知道a键挂没挂。(见第三步对a键挂没挂的判定)

详细解释:

1、#if srf_mode,当变量srf_mode逻辑值为true的时候,围起来的按键设置生效。

2、srf_mode是一个变量名,因为没有赋值,它是一个空变量,所有它的逻辑值是false。(当一个变量没有值,或者值为0,它的逻辑值就是false,反之为true)

3、srf_mode := !srf_mode,这是一个计算式,不是数学意义上的恒等式,点击Lshift一次,才会而且必须计算一次。这个式子从右往左看,“:=”右边的式子把计算结果传递给左边的变量,给它赋值。

4、 感叹号!是一个逻辑值的计算符号,有点类似数学上的负号。

这一篇很重要,你不一定要马上看得懂每个参数和命令,但是你要知道它运行后达到一个什么样的结果。

在Autohotkey之前,我有稍微了解过其他的语言,碰到过“n=n+1”这样的写法,我能看懂这个式子要干嘛,也能有样学样拿来用。但因为数学概念的干扰,始终理解不了,等到能理解了,已经是大半年以后了。



第三小时:点一盏灯

(此篇就是对输入法开启与关闭的判定,以及可以自定义输入法的小图片)

有了Lshift这个开关后,就能给它装上一盏灯。继续改代码,还是先保存,然后reload

前4行代码表示:我们打开cn1.png文件,然后建立了一个“透明+允许鼠标穿透+置顶在最前面”的窗口(其中X220 Y400是屏幕坐标位置),同时这个窗口命名为叫“srf_icon”。这句话的重点是“透明”,也就是一开始,你新建了一个看不见的东西。(cn1.png就是显示出来的输入法图标,可自定义:把自己喜欢的图片放进去,注意图片尺寸)

第6到12行对原来Lshift键进行改造,原来的计算式不变,增加了新的内容:

当srf_mode是true的时候,把 srf_icon 窗口给显示出来。

当srf_mode是false的时候,把 srf_icon 窗口再次给隐藏起来。

现在变成这样了:当不断点击Lshift键的时候,屏幕上会有一个色块,循环“显示”和“隐藏”,效果如下:

色块随着点击Lshift键,而显示或消失

你可以在色块显示/隐藏的情况下,分别按a键看下结果。

当色块显示的时候,说明srf_mode为true,模式中的代码生效:a键挂了

当色块消失的时候,说明srf_mode为false,模式中的代码无效:a键复活



第四小时:一个简单的快捷启动工具

我们用了12行代码轻松做了如下事情:

1、我们新建了一个模式srf_mode。

2、我们可以用Lshift一键轻松进入/退出这个模式。(进入-开启输入法,退出-关闭输入法)(Lshift也可也自定义开启输入法的快捷键,比如shift+ctrl等等

3、我们有一个色块提示,是否处于模式中。

为了便于阅读,前面的12行代码折叠起来

上面代码中,我们举了三个例子,在srf_mode模式下,重定义了a键,f键,h键,用到了sendrun两个命令。

1、在autohotkey中,可以重定义单个按键,也可以重定义组合键。它们统称为热键

2、除了热键以外,常用的另外一种重定义叫做热字符串。(这个我们用不到)

3、send命令可以输出“数字、字母、符号、中文,以及按键(比如tab键、enter键)等”。

4、run命令可以打开网页、文件、文件夹等等。(具体用法可以见帮助文档)

5、Autohotkey支持控制鼠标移动、点击

6、前面举的例子为了简单,所有一个按键定义了一行代码,其实可以是一个按键运行一堆代码。

以上请具体查阅帮助文件。

就算你对后面的内容不感兴趣,在上面建立新模式的那十几行代码的基础上,你可以轻松制作一个属于自己的快捷启动工具。

如果你对输入法相当感兴趣的话,来吧,  柚子熟了,是该摘了。



第五小时:定义a-z键

要模拟输入法,最基本的,先定义a~z这26个按键:

26个按键的定义关在srf_mode中,当模式启动的时候,按键的设定才起作用(即开启输入法才起作用)

为了便于阅读,我们把b到y那24行折叠起来

srf_all_input := srf_all_input . A_ThisHotkey

1、是不是感觉有点眼熟,对,变量赋值运算式,而且26个按键共用,敲一次键,运算式就计算一次。

2、A_ThisHotkey是一个内置变量,用于存储最近执行的热键的按键名称。在这个例子中,你按a键,它的值就是a,按z键,它的值就变成z。(工作原理就是你按下a键,a键失效不作用(a::   ),再执行到srf_all_input := srf_all_input . A_ThisHotkey这句时,会输入一个值为你刚才按下去的那个键(a),由于脚本计算太快,类似于你按下a键就输入一个a键)

3、中间的英文句号是一个连接符。

也就是说srf_all_input这个变量存储了你当下的键击。不好理解的话,往下看。先说一句,不要拿这个工具来作恶。(本文章仅供学习使用,若有其他行为,后果自负)



第六小时:显示你的键击

现在,再加一行代码(见第48行),保存,reload以后:

先看运行效果:.

1、点击Lshift键,色块显示,表示已进入srf_mode模式

2、依次点击键盘上的“h、e、l、l、o”五个按键。

结果就是下面gif图看到的那样。是不是感觉已经快成功了,没错。

tooltip, % srf_all_input, A_CaretX + 10 , A_CaretY + 20, 16

1、这行代码涉及到tooltip命令,最后面的数字16,是给这个tooltip的编号(tooltip命令:显示你所打进去的字符)

2、百分号%在autohotkey中是一个很重要的运算符号,先用,后面慢慢领会。注意,这个例子中,%后面有个空格。你可以尝试把%拿到,看下运行结果。

3、A_CaretX 和 A_CaretY 是两个内置变量表示当前光标 (文本插入点) 的 X 和 Y 坐标。



第七小时:显示键击匹配码表的结果

(即是输入法里面变量的值,比如敲击he,会输入河里有妖怪等等)

大妖怪登场啦,继续改代码,保存,reload:

1、先看第1到第5行,这里我们定义了“h、he、hel、hell、hello”五个变量,同时给它赋值,等号右边的那一串,就是对应变量的值。(多说一句,这五个变量都有值了,所以它们的逻辑值就是true)

2、看第54行,我们在原来这行代码中间增加了. "n" . %srf_all_input%这个部分。(n是表示换行。)

基于这两点代码变更,运行效果如下:

Autohotkey非常适合用来模拟输入法,除了它本身能简单和轻易模拟键盘的键击外,还源于它相比传统编程语言来说,相对来说不正规的变量赋值方式。(不过,如果你有学过其他语言,然后看到“a=工”这种变量赋值方式,估计有点崩溃。)

我在网上找了一个王码86古董词库,大概3.5万行左右:

王码86古董词库

用gvim替换每行的第一个空格为等号,然后保存到一个utf-8格式的ahk文本文件中

柚子输入法的码表格式

把这个码表文件挂到代码里面,把原来第1到第6行的变量赋值代码删除,改为挂码表的代码(见第1行):(对外引用库-wubi96.ahk,用的是#include wubi96.ahk,或者也可以写成:#Include %A_ScriptDir%\wubi96.ahk )(wubi96.ahk要放在与脚本同一目录下)

下面是运行效果:

从第3个键击开始,因为码表中没有对应(hel、hell、hello)的定义项目,所以就没得显示。



第八小时:选择候选项

(显示可供选择的字)

有了候选项以后,当然就可以选字了:

上面的例子中,我们有一个变量srf_all_input,它的值是"cwyg",我们再用cwyg当做变量名去匹配码表,得到值“难 骓 騅”,这是一个字符串(3个汉字中间两个空格)。

再加一行代码(见第51行),保存,reload

第51行,用stringsplit命令,用空格当隔符,把“难 骓 騅”分解成一个数组,同时这个数组包含4个变量:

srf_for_select_array0=3       ;这个数组中子字符串的数量

srf_for_select_array1=难

srf_for_select_array2=骓

srf_for_select_array3=騅

也就是说当srf_for_select_array0这个变量大于等于0的时候,我们才有得选择。有值,并且值不为0,说明它的逻辑值是true,那么就可以用这个变量来新建一个模式(第20到24行):

在第20到24行,我们新设定了一个模式srf_for_select_array0,在这个模式下设置了3个选择候选项的按键:“空格 逗号 句号”。在这个例子中,按“空格键”会输出“”,按“逗号”键会输出“骓”,按“句号键”会输出“騅”。

在候选项状态,分别按空格键、逗号键、句号键

好吧,虽然快成功了,但这效果明显不是我们想要的。正常来说,当我们选了一个候选项以后,这次的打字就算结束了,要开始新的“敲键码、选择候选项”。所以,我们做一了个函数srf_select(list_num)(见第61到68行),每次选择完后都清空部分状态。同时之前设置的3个选择键改为调用这个函数(见20到24行):

改完以后的效果如下:



第九小时:设置修改键——backspace

(这篇引入退格键,对某些错误输入的修改)

输入法的框架是基本都弄完了,有几个地方要补充设置下:

首先在这个界面,输完“cwyg”之后,我们发现其实要输的是“cwya”,那就得改,所以这边还得补充定义backspcae后退键。在这个例子中,cwyg是变量srf_all_input的值,也就是说srf_all_input有值(它的值只能是a到z这26个字母的组合,所以不可能为0)的时候,backspcae才需要起作用,所以这里又增加了一个模式(见第28到43行):

这里用到了内置函数substr,以及加了if-else的判断,运行效果:

仔细看的话,会发现,其实定义backspace键的主要代码,以前有出现过,第33到35行在84到86行出现过,第39到40行在75到76行出现过:(建立一个区块,需要的时候进行调用即可)

所以我们把重复的代码抓出来,做成标签,谁想用,就自己去调用:

两个标签


第十小时:其他按键设定以及中文符号

在srf_all_input模式下,正常还得加3个键:

esc键:按键敲错了, 全部清空,待重新敲击

enter键:把当前的编码当作英文上屏,不改变srf_mode模式

Lshift键:把当前的编码当作英文上屏,退出srf_mode模式,即进入键盘的英文输入模式

而在srf_mode下面,除了定义a-z这26个字母外,正常还得定义3个键,

esc键:退出srf_mode,等同于按Lshift键

逗号键:用于输出中文逗号

句号键:用于输出中文句号

最后就是中文符号,中文符号的定义也是放到srf_mode模式下面,在定义中文符号之前,我们要先修正最开始的一个错误,  在第10行,加了一句代码,如果不加这句代码,在srf_mode下面,比如,按Lshift+5,是打不出%号的,其他类似5的按键也一样。加了这行代码以后,我们就可以定义中文符号了,见第100、101行,这里只举两个例子。



第十一小时:新鲜出炉的柚子输入法(完结篇)

总结一下:

3个模式的位置顺序很重要

整理一下就是:

1、3个模式,1个函数,2个标签

2、3个模式下各定义了一些按键

3、3个模式之间是层层包含的关系,因为某个按键可以在不同的模式中都有做定义(比如本例中的Esc键),所以最里面的模式的代码要写在最前面,中间的次之,最外面的模式的代码要写在最后面。想想如果顺序反了,会怎么样。

我们一直在讲模式,再做一个模式,整篇下来,我们一直在编辑代码,然后保存,接着reload,太累了,现在我们让它保存完后,自动reload。

自动reload

上面的代码表示:如果当前的窗口是AutoHotkeyU32.ahk,那么按ctrl+s保存完文件,200毫秒后,做一个reload重载代码的动作。

回到最开头说的,打开listary搜索框的时候,顺便切换到英文输入状态(!f表示alt+f,要先在listary程序中设置启动快捷键为alt+f):



第十二小时:四码唯一自动上屏(附加篇)

因为我自己并没有使用五笔输入法,所以关于五笔输入法的一些操作逻辑并不是很清楚。与 @Ubuntu_2017 的交流之后,了解了一些,我们来说说其中的几个操作如何实现:(本篇新增了一些代码,新文件下载地址:https://share.weiyun.com/5a3QZK0)

一、四码唯一自动上屏

二、空码清空已输编码

三、第五码顶前四码首选

第一跟第二比较简单,因为都是满足条件的话,就自动执行。直接看代码(见第119到125行,增加了两个条件判断)。

第三个相对复杂一点点,因为要涉及第5码,对于第5码,我们要加个模式。

在第21行到第57行,我们新加了一个模式StrLen(srf_all_input)=4,注意,这个模式是放在srf_for_select_array0模式前面的。

模式StrLen(srf_all_input)=4 跟 模式srf_mode 有点像,都要重定义a-z这26个按键(为了便于浏览,b到y键的定义折叠起来了。)

大概思路就是这样,额,又出现重复代码了,有时间再看看能不能精简一下。

 



总结:

全部代码如下:

编辑器的行号显示,用了136行代码,扣除空行、注释行,一眼就能看得懂的,我数了一下,需要花点力气才能看懂的,大概在40行左右。

现在你有了一个基本的绿色免安装的便携框架,挂上喜欢的码表,就可以打字了。等以后熟练掌握ahk的语法了,那么想要什么样的功能都可以加上。

比如,我自己加的功能:

上面的码表分别对应如下功能:

1、打出Autohotkey这个字符串

2、调用gvim打开ahk的配置文档

3、打开ahk在线帮助

4、打开workflowy中的ahk笔记页面

5、调用everything命令行工具搜索设定的唯一码,打开电脑上对应的ahk文件夹

可以看到, “中文输出与快捷启动”统一到了同一个入口,这也是我当初用autohotkey模拟输入法的一个出发点。

最后再说一次,不要拿这个软件来作恶,双击任务栏上的程序图标,会打开程序窗口,菜单项里有个key history,调试的时候可能会用到里面的信息

我用的时候,习惯在代码文件的最前面加一句,把key history关掉。

#KeyHistory 0

柚子输入法有很多缺点,我记录在案的就有如下一些:

1、在某些程序,打出来的是乱码,目前碰到的有anki,还有几个忘记了。

2、词库太小,另外好的词库可能不好找。

3、光标对位问题。

4、皮肤很丑。

5、越有个性的东西死的时候越惨。(比如Autohotkey程序如果挂了,你就跟着挂了)

6、有作恶风险。因为很容易记录键击。

7、一切都要定义,想要的功能都要自己写。

。。。

柚子输入法唯一的优点:一切如你所愿。(正如所有自己编写的输入法,一切的词库都可以自己导入以及修改)



写在结尾的话

经过这12个小时的学习,相信各位ahkor对打造一个属于自己的输入法应该是轻而易举了,也可也参考一下影子输入法的打造过程

希望各位各有所得。
(写在一个小角落的话:最近河许人联合他的布代团队正打造一系列优质的ahk中文视频教程,希望大家能够多多捧场)


鸣谢

上面教程由简书的srf作者提供,本文由“没钱上网的花大爷”大多转载其精华,并对其解释标注;

更多精彩脚本与文章,请关注ahk官方中文网:www.autoahk.com

或者请加入我们:QQ群:

1:3222783 (autohotkey高级群)

2:470710096(autohotkey终极群)

3:348016704(autohotkey高手群/RPA)此群付费但是内有众多高手,推荐加

 

本文为原创文章,未经同意禁止转载!!