作为一个比较“事儿多”的五笔用户,在使用过几乎所有的主流输入工具后,我最终选择了定制性非常高(同时也比较难以上手)的Rime。刚开始是在Windows下使用小狼毫0.9.30版,这个工具在上屏速度、热键定制还有诸多功能设定方面,都令我非常满意。但是唯一美中不足的是,要使用自动造词功能,就必须开启用户词典,而开启之后,就会出现词序无法固定的问题。举个例子,新世纪五笔中的“去、支、云”三个字为重码项,而rime对于重码项的排序并不是按照常规的词频排序,开始一直以为是程序中存在bug,但后来发现是作者刻意而为,也许是在其他输入法中有用处吧,但是在五笔中真的不合适。经过一两个月断断续续的折腾之后,终于通过修改源代码解决了这个问题,所以决定写个博客记录一下。
1、最终效果
修改之后的程序,能够在开启自动造词之后,依然将单字固定在词组前面。有人说五笔不需要自动造词,这一点本人无法苟同。在前一段时间写毕业论文是,就用到了大量的自定义长词组,比如“支持向量机”。如果不开启自动造词,想要以词组的方式把“支持向量机”打出来, 就必须把这个词组加入词库文件.dict.yaml中(不需要指定词组编码,程序会自动根据单字编码反查并组合,这一点很强大),然后“重新部署”才可以,但对于每个自定义词组都这么做未免太麻烦。如果开启了自动造词,第一次按单字输入之后,以后就可以直接按词组输入,这么简单何乐不为?
2、librime源代码修改
经过长时间的琢磨,终于发现了问题在librime中。librime是Rime输入工具的内核,对于Windows、Linux、MacOS三个平台是通用的,正是它负责记录用户词组和词序调整。仔细观察用户词库文件.userdb.txt,可以发现词序是按候选项中的d值排序的,而d的值会在源代码中librime/src/rime/dict/user_db.cc和user_dictionary.cc两个模块中修改,这两个模块都调用了librime/src/rime/algo/dynamics.h中的formula_d函数,这个函数原本是这么定义的:
inline double formula_d(double d, double t, double da, double ta) { return d + da * exp((ta - t) / 200); }
结合user_dictionary.cc中的调用代码:
v.dee = algo::formula_d(commits, (double)tick_, v.dee, (double)v.tick);
可以看出来,d值会随着时间有一个指数衰减,这就解释了为什么一个候选项的d值本来很大,但长时间不输入,会导致下一次之后d值变的很小。通过修改formula_d,问题迎刃而解:
inline double formula_d(double d, double t, double da, double ta) { return d + da; }
修改之后,每次候选项上屏之后,d值都会+1,然后通过给重码设定不同的d值,就可以近似达到固定排序的目的,比如分别为“去、支、云”指定7500、5000、2500,那么“支”要比“去”多上屏2500次才能排在前面,因此说是近似固定排序。这个方法的另一个好处是,只为单字指定词频,而不为词组指定(默认为0),那么就可以保证重码单字排在词组之前,而词组之间会按输入频率排序。
3、Windows下weasel编译
虽然很不喜欢Windows,但是不得不承认Windows做的很傻瓜式,很容易上手。对于程序的编译也是这样,装上VS,事情就搞定一大半了。然后再安装cmake和boost函数库,就可以编译了。但同时,Windows下出了问题也比较难以解决,比如编译脚本build.bat里编译器环境变量命名的错误,就害我找了好久。
4、Ubuntu下编译安装
Ubuntu下编译虽然麻烦一些,要安装很多的工具和函数库,但是出现问题基本上Google一下就能搞定。这里有几点需要记录一下,以方便以后查阅:
1)以源码形式编译和安装,似乎只能在每台机子上现编现装,在其他机子上make好的似乎不能直接make install
2)编译时需要的大部分工具和函数库,都可以通过apt-get install的方式安装,但有两个函数库不在默认的安装源中,分别是GoogleLog(glog)和OpenCC,已上传到百度网盘中备用
3)目前Linux下的输入界面似乎还不能修改,有待研究