业火输入法全角单双引号的实现
业火输入法在全角符号的模式下,转换全角引号(包括‘、’、“、”、『、「、」、』)一直都有问题,比如说没有办法输入右引号等,这篇文章介绍一下业火输入法如何处理这些个问题。
背景
业火输入法全角引号符号的有两个问题:
- 单引号(’‘)和双引号(”“)没有办法输入右引号。
- 没有办法输入单直角引号(「」)和双直角引号(『』)
这两个问题有不同的原因,首先,之所以没有办法输入右引号是因为单双引号在键盘上分别只有一个键位对应,在半角模式下,左右引号是一模一样的,所以在半角输入一个键位对应左右引号是没有问题的,但是全角符号不同,全角的单双引号,左右引号是不同的,这样,在一个键位严格对应一个符号的情况下,自然就没有办法输入右引号了,这一转换映射关系可参考业火输入法的实现。其次,之所以没有办法输入单双直角引号是因为业火输入法没有对应的半角符号转换为单双直角引号,此处也可查看上面映射关系的具体实现。
系统输入法和搜狗输入法的实现
可以站在巨人的肩膀上来看看系统输入法和搜狗输入法是如何解决这两个问题的,实际验证过程中,发现两个输入法的解决这两个问题的方法是一致的。
- 搜狗输入法是通过再次按单引号和双引号键来键入对应的右单双引号,具体如下图,通过这种方法把一个键映射为两个编码(’: ’‘,”: “”)完美解决了右单双引号的输入问题。
- 那搜狗输入法又是如何解决直角引号的输入问题的呢?搜狗输入法把左右大括号按键({})分别映射为左单双直角(「『)和右单双直角(」』)符号来输入直角引号的,具体的方案如下图,可以看到搜狗输入法也是把一个按键映射为两个编码来解决这个问题的,唯一不同的是右直角引号的编码依赖了最近一次左直角引号的输出这一点。
- 如果在输入过程中,输入框进行了切换,那输入法要怎么处理呢?比如说在输入框1中输入了左双引号,然后切到了输入框2,再次按双引号按键时,此时是应该输出左双引号还是右双引号呢?也就是说这个按钮的状态是全局的,还是输入框维度的呢?搜狗输入法的实现是,单双引号的输入是全局维度的,直角引号的输入又是输入框维度。
思考
到目前为止,问题一二可以参考系统和搜狗输入法的方案,我唯一有些异议的是状态是要跟全局还是要跟输入框,刚开始我觉得输入框维度会比较好,因为这里的符号都是成对出现的,所以输入框维度的状态更符合使用习惯。然而,再设想一种边缘场景,如果有一个输入框,只能输入一个右单引号或右双引号,这种场景下,输入框维度的状态就会出现要想输入右引号,必须先输入左引号,从而导致没办法输入符合条件字符的问题。
基于以上的原因,经过思考,业火输入法的单双引号的输入状态最终采用了全局状态的方案。
技术实现
关于技术上的实现,当然是单双引号会比较简单。
以单引号为例,可以用一个计数器记录单引号按下的次数,当前是奇数次时,输出左单引号的编码,当前是偶数次时,输出右单引号的编码。
然而,考虑到这个状态是全局的,所以随着使用的时间增长,这个数字可见会越来越大,所以要考虑到数字太大,最终溢出的问题,为了避免记录的次数随着使用的时间越来越大导致溢出,可以把记录的次数对2取余后再存储。
当实现了单双引号的输出后,直角引号的输出也就有了思路,只需要在左直角符号输出的时候,关联一下右直角符号的次数即可。
在实现上另外有一个点需要注意一下,就是为什么要用编码后的字符而不是原码来判断按键呢?这里主要是因为,每个符号按键转换为哪个符号在业火输入法中是可以由用户定义的,所以使用编码后的字符来处理就能让逻辑跟随用户定义的符号转换逻辑,而不是绑死在某个按键上。
总结
业火输入法的这两个问题一直都存在,但是我一直拖延,这次总算彻底处理了这个问题,过程比我想象得更顺利。