本来想把一些示例放在项目的 wiki 页上的,但是我还想说一些其他的闲话,而且目前扩展虽然有一些实用性了,却缺乏执行保护,可以把输入法弄得不稳定,所以这些内容就放到这里好了。如果你只想看看如何使用输入法的扩展,请向下找到 表情后从那里开始看。
似乎扩展是很流行的样子,各种浏览器,foobar2000,谷歌拼音,WPS,都可以用扩展。
其中,有的软件成功了,令人爱不释手,比如像 Firefox,foobar2000。有的软件却没有因为扩展成功,比如谷歌拼音。或者说扩展没有给人带来好感,比如 IE 浏览器。
我觉得作为一个支持扩展的软件,最重要的就是扩展要比较有用,可以做一些事情,这一点上谷歌拼音做得就不好,由于扩展而变得比较成功的软件在这方面做得都比较好。其次,扩展要容易开发,再往后,出于安全的考虑,扩展的能力要受到约束。这两点 IE 相比 Firefox 就弱了一些,不过 Firefox 的扩展写起来还是挺麻烦的,比如其中的多国语言化就非常麻烦,对于不同的地方要使用不同的方法,总共有三种。而由于 Firefox 的灵活性,出现了 Mozilla Jetpack 和 GreaseMonkey 等,都可以让扩展写起来方便一些。
在很长的一段时间内,我觉得编写软件,技术含量是最重要的, 一个更好的算法可以带来更快的速度,或者更好的结果,当然用户体验就会好。但是现在看法有些改变,因为目前,很多东西不是需要从头做起的,除非出于学习、版权目的,或者是原先的项目代码烂到不能看而没法维护,没有必要重新实现别人已经实现的东西。大部分软件应该在乎实用性,在不违反版权的情况下,尽量使用已有的东西。
从一开始,我觉得 ibus-sogoupycc 这样一个输入法的技术含量肯定不如 sunpinyin,Linux 下的输入法用 sunpinyin 就不错了,一度怀疑是否要有将 ibus-sogoupycc 写下去的必要。但是现在,我觉得是有必要的,因为在中国大部分有网络的地方,这样一个输入法用起来是更舒服的,至少对我自己来说。
出于同样的实用性的考虑,我提供了输入法扩展能力。本来我想提供一个完全兼容谷歌拼音的接口,但是后来觉得谷歌拼音的扩展接口设计得并不好,和目前输入法的无需选词流畅输入有冲突,没有遵循的必要。
开头提到的这个表情在这里: ,不难找吧。
扩展的设置应该放在用户配置文件中,目前添加一个扩展的方法是:
ime.register_command(key, modifiers, caption, script) |
这里,key 和 modifiers 都是数字类型,后两者是字符串类型。
修改用户配置文件后一般要重新启动输入法才能生效,可以右击任务栏上的 ibus 图标,选择重新启动。
Hello world
下面的代码注册了一个用 Alt + H 可以激活的扩展,只要输入法被激活,无论处于中英文状态,都可以用这个热键运行这个扩展。
ime.register_command(("h"):byte(), key.MOD1_MASK, "hello", "ime.notify('hello world')") |
重新启动 ibus 之后,按下方形的扩展按钮(ibus-1.2.0.20090927 版本下,方形按钮会消失,这是 ibus 的已知问题,此时通过热键仍然可以运行扩展),可以看到一个标题为 hello 的菜单项,单击它,就可以运行扩展。
这里,第一个参数是按键,
("h"):byte()
表示 h 的 ASCII 码,"ime.notify('hello world')"
是一段字符串表示的 lua 代码,它利用输入法提供的 ime.notify
方法显示了一些内容。
插入系统时间
ime.register_command(key.Shift_R, 0, "插入系统时间", "ime.commit(os.date())") |
这里的 ime.commit
也是输入法提供的方法,用来直接向客户端程序输入文字,os.date
是 Lua 标准库函数。这段代码注册了一个用 右Shift 激活的插入系统时间的功能。
Lua 的标准库函数在扩展中都是可以用的,比如可以用 os.execute('mousepad &')
在后台运行一个 mousepad。
执行 Lua 代码
ime.register_command(('L'):byte(), key.SHIFT_MASK + key.MOD1_MASK , "执行 Lua 代码", "ime.execute('ime.notify('..ime.get_selection()..')')") |
这段代码注册了一个用 Shift + Alt + L 热键,把选中内容当做 Lua 脚本执行,并用桌面提示显示结果的扩展,这里因为有了 Shift 辅助键,所以要取大写字母 L 的 ASCII 码。其中使用方法 ime.get_selection
获得选定文字的内容,ime.execute
用来把一个字符串当做 Lua 脚本运行,双点号是字符串连接操作。
这个扩展可以比较有用,比如当选定 315+23*6145
这样的表达式之后,运行一下扩展就可以知道计算结果,也可以选定 ime.VERSION
这样的内部变量,查看其内容。甚至可以选定一段 ime.register_command
代码,动态添加扩展
“回音”效果
不知道从什么地方开始流行这种效果,我想说明的是,声明一个函数并且在扩展中调用是可以的:
function echo_effect() local s = ime.get_selection() for i = 1, #s, 3 do ime.commit((i == 1 and '' or ',')..s:sub(i)) end end ime.register_command(('E'):byte(), key.SHIFT_MASK + key.CONTROL_MASK, "产生回音", "echo_effect()") |
这里简单地使用了 3 个字节 作为步长,所以只能处理纯中文。对文字 “这是回音你懂吗” 使用这个扩展会得到:”这是回音你懂吗,是回音你懂吗,回音你懂吗,音你懂吗,你懂吗,懂吗,吗”
全半角切换
输入法本身没有提供全半角切换功能,但是通过扩展可以实现类似功能:
ime.second_punc_map = {} function toggle_punc_map() ime.second_punc_map, ime.punc_map = ime.punc_map, ime.second_punc_map ime.apply_settings() ime.notify('已切换到' .. (ime.punc_map['.'] and '全' or '半') ..'角') end ime.register_command((','):byte(), key.CONTROL_MASK , "全半角切换", "toggle_punc_map()") |
注册了 Ctrl + 逗号 作为切换热键,并会用桌面提示显示切换结果。
全双拼切换
可以仿造上例写出:
ime.register_command(0, 0, "全双拼切换", "ime.use_double_pinyin = not ime.use_double_pinyin ime.apply_settings()") |
前面填写的两个 0 表示这个扩展没有热键,你也可以再加上一句 ime.notify
,使得切换的时候有桌面提示。
对缓存的操作
缓存是存在全局的 request_cache
中的,可以直接对其操作:
function show_request_cache() for i,v in pairs(request_cache) do ime.commit('"'..i..'" => "'..v..'"\n') end end ime.register_command(0, 0 , "查看缓存", "show_request_cache()") ime.register_command(0, 0 , "清空缓存", "request_cache = {}") |
其中的 ime.commit
方法用来向客户端插入文本,还有一个方法是 ime.request
,用来向输入法提交一个拼音请求,比如下面这段代码片段将向输入法提交《春晓》的拼音:
for _, v in pairs {'chun mian bu jue xiao', 'chu chu wen ti niao', 'ye lai feng yu sheng', 'hua luo zhi duo shao'} do ime.request(v) ime.commit('\n') end |
给自己发送飞信
输入法全局配置文件默认加载了 socket.http
和 socket.url
模块,可以用它们来访问网络。
比如,下面的代码通过 api.bz 这个在线接口把选定文字内容通过飞信发送给自己:
function send_sms(content) http.TIMEOUT = 2 local res = http.request('https://sms.api.bz/fetion.php?username=15566119320&password=nevermind&sendto=15566119320&message='..url.escape(content)) ime.notify(res or '飞信发送失败', content, 'info') end ime.register_command(('m'):byte(), key.CONTROL_MASK + key.MOD1_MASK, "飞信发送", "send_sms(ime.get_selection())") |
以上填写的飞信用户名和密码皆为虚构,实际用的时候需要改一下。
简繁体转换和翻译
使用 Google API 来翻译文字,从简体中文翻译成繁体中文就实现了转换成繁体
function google_translate(text, langpair) local url = 'http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q='..url.escape(text)..'&langpair='..url.escape(langpair) http.TIMEOUT = 1 local res = http.request(url) if res then res = res:match('"translatedText":"(.-)"}') end return tostring(res or text) end ime.register_command(('t'):byte(), key.CONTROL_MASK + key.MOD1_MASK , "转换成繁体", "ime.commit(google_translate(ime.get_selection(), 'zh-CN|zh-TW'))") ime.register_command(('e'):byte(), key.CONTROL_MASK + key.MOD1_MASK , "翻译成英文", "ime.commit(google_translate(ime.get_selection(), 'zh-CN|en'))") |
写在最后
这是一个悲剧。
Lua 作者根本不相信多线程,原因是现在的主流语言中连 a = a + 1
都不是原子的,谈什么多线程呢?
我曾经做过一些尝试,确实让程序多线程地执行 Lua 代码,又共享一些全局数据,不是轻松的事情。我也想到一些解决办法,但是都太麻烦了,于是就偷懒不管那么多了。
这有什么影响呢?影响就是目前输入法执行 Lua 代码是单线程的,扩展中的 Lua 代码会造成阻塞。在有网络请求等操作的时候,要注意控制超时,否则程序可能被认为没有响应了,各种死法都有可能出现
目前输入法的自由程度到了可以随意 AOE,比如用 os.execute('pkill Xorg')
,就可以干掉许多无辜者。正所谓权力越大,责任越大。到底安全与否,就看扩展中的代码自我约束得如何了
抢个沙发,求你这套表情,打包发给我吧。
@hzqtc : -,- 自己动手下载
头一回看到“回音效果”这个词,楞了一下,看了示例之后冷汗遍地流……
ym 灰长好玩的样子,找个时间试试
@liancheng : 似乎是出自某个视频的,我也是听别人说才知道
@watashi : ym 学长。我觉得我要补充声明一下:玩扩展把输入法玩崩了不算 Bug,没有 bg -,-
>>我觉得 ibus-sogoupycc 这样一个输入法的技术含量肯定不如 sunpinyin,Linux 下的输入法用 sunpinyin 就不错了,
很明显Sunpinyin没你想象的那么有技术含量。技术上说,你这个不比sunpinyin差。。。
可扩展的设计不错啊!输入法已经强大的可以当个shell了
@Xue : 嗯,确实不错。但是我本意并不是想把它当做是 Shell ,我只是想,像发送飞信或者是一些翻译之类的东西,在这里实现使用起来会比较方便。
不过目前看来扩展容易把程序弄挂,还没有专心仔细看看是怎么回事
现在还是不太相信国内的“云”服务,谁知道你打字的时候有没有gd在监视呢。。。
@xiooli : 我也不相信,当然除了云之外,其他的邮件什么的都不相信。
不过日常使用云输入法感觉非常好 以至于这是我目前停留在 Linux 而不是 Windows 的首要原因。
至于监视什么的,我觉得也没什么敏感的信息,爱看就看吧 -,-
虽然不明白,但还是支持,坚决支持
我觉得你还是写篇介绍文章去linuxtoy投稿的好,你有点太低调了,不能“酒香不怕巷子深”。另外archlinux的community里已经有编译好的ibus-sogoupycc包了
@ggarlic :
Archlinux 官方源是把 ibus-* 都加进去了。我知道这件事情,因为我也是 AUR 上软件包的管理者,被移到 community 的时候我收到了通知邮件的。
至于要不要宣传,我觉得目前还是维持现状比较好。一是现在还有2个Bug在最新版本中Fixed了,还没有发布,不知道有没有其他的问题;二是我确实是比较喜欢低调一些的;还有我毕竟不是搜狗官方,不知道用户数多了起来之后服务器会不会受不了,因为有时候在高峰期明显感觉到服务器那边压力比较大。
嗯,感谢你的关注,我会在合适的时候考虑向 LinuxToy 投稿的
腾讯这回又抄云输入法了,看来因搜狗原因导致这个项目可能做不下去的可能性不大了!哈哈!这个输入法是我用过的最好用且有趣的一个了!楼主加油!