Skip to content

macroxue/zigen

Repository files navigation

拓扑形声:Linux下自制汉字输入法

汉字拆分

所有GB2312的6763个汉字都在 breakdown.txt 文件中拆分。 (如果某些部件无法显示,则需要下载sim-ch_n5100字形。) 文件的开头是独体字以及复合部件的拆分,最直接的学习方法 就是看它们是怎么被拆的。下面是一些拆分原则。

取整优先、笔画可断

当一个字的结构明显,拆分是没有难度的,例如“邀” ⇒ “白方攵辶”。困难的是当一个字的笔画交叉重叠在一起, 比如“重”,要么如表形码不拆,要么如五笔拆得七零八落。 其实最直观的拆法是“重” ⇒ “千里”,然后再考虑“千”和 “里”各自怎么拆。这里“千”和“里”都是整字,所以是取整 优先。竖笔被从中断开,所以是笔画可断。

记得古时有这么一副对联:八刀分米粉,千里重金锺。一个 书生要进京赶考,其父觉得没戏,就以开米粉店的生计组字 出了上联考书生,没想到书生以金榜题名的理想组字对出了 下联,其父当然只能放行。千里为重,自古而然。

那么如何继续拆“里”呢?当然是“里” ⇒ “田土”。类似的例子 还有:“果” ⇒ “田木”,“男” ⇒ “田力”,“熏” ⇒ “千黑”。 这样的拆法自然直观,拆出的都是整字。

简单笔画、贯穿不拆

在部件归类时“大夫𡗗”归入同类,其中的规则是不在乎被 贯穿的是一笔、两笔还是三笔。再看一下复杂一些的情况, 比如“革”的下半部分是“中”加被贯穿的一横笔,又如“聿”是 “肀”加被贯穿的两横笔,那么这些横笔要不要拆出来呢? 拆出来当然可以减少字根数量,但是一个字里如果拆出过多 的部件,编码效率就会降低而导致重码。所以这里的规则是: 如果被基本形贯穿的只有简单笔画(横竖撇捺),就忽略 这些简单笔画而只取基本形。如果被基本形贯穿的不只有 简单笔画,所有被贯穿的部件都要拆出。

以“事”为例,其基本形是“肀”,被贯穿有“口”而非简单笔画, 所以被贯穿的部件都要拆出,于是得到 “一口肀”。以“肀” 为基本形的例子还有:“妻” ⇒ “肀女”,“疌” ⇒ “肀龰”。 以“木”为基本形的例子有:“未” ⇒ “木”,“束” ⇒ “木口”, “朿” ⇒ “木冂”。其它例子:“世” ⇒ “廿㇗”。

当贯穿的是重复部件,就直观地拆出重复的贯穿部件,而不必 考虑笔画是否折断。比如:“串” ⇒ “中中”,“出” ⇒ “山山”, “册” ⇒ “[丹-3][丹-3]”。

这里需要解释一下“[丹-3]”是指“丹”的前三笔,即不包括点 的部份。又如“[字-3]”或“[字1-3]”是前三笔宝盖头, “[字4-]”是第四笔以及后面的所有笔画也就是“子”。

像“丈史吏更曳”这样斜向贯穿的字,其基本形是“乂”而不是 “中”或“申”,所以:“丈” ⇒ “乂”,“史” ⇒ “口乂”, “吏” ⇒ “一口乂”,“更” ⇒ “一日乂”,“曳” ⇒ “日乂”。

以下是更多的同类:“艹廾卅井”,“扌𰀁丰”,“大夫𡗗”, “木未耒”,“𠂇[看2-4][寿-4]”,“弋戈戋”,“七[毛2-]”, “子[承-5]”,“土龶”,“干[拜5-]”,“龷𠀎[舞3-8]”, “中[革4-][囊-5]”,“申車”,“肀聿[妻-5]”,“巾巿[制2-6]”。

封闭不拆、包围可拆

封闭不拆是指像“女又田四皿曲巴𠃜耳”这样的封闭结构 不能拆开。如果被封闭的部件和封闭本身并无接触,这样 的部件是可以拆出来的,比如:“叉回图”。一些奇特的 字形可以有封闭区域,但其主体并非封闭,可以拆开, 如:“夷” ⇒ “大弓”主体为贯穿,“民” ⇒ “[民-3][弋-2]” 主体为包围。

包围可拆是指像“甩”这样的包围形是可以拆成““冂[毛2-]”的。 当然可拆并不是非拆不可,比如高频字根“月”和“用”就没 必要拆,拆了只会增加重码,所以包围可拆是给不常用的部件 配备的。再举几个例子:“冉” ⇒ “冂土”,“巨” ⇒ “匚コ”, “那” ⇒ “𠃌[那2-4]阝”。

拆单撇

很多部件加上一撇就是另一个部件,反过来拆掉单撇就能 得到更基础的部件,比如:“白” ⇒ “丿日”,“千” ⇒ “丿十”, “生” ⇒ “丿龶”,“龙” ⇒ “尢丿丶”,“老” ⇒ “土丿匕”, “少” ⇒ “小丿”。

撇笔组成单人旁或双人旁时就不再拆出,例如: “任” ⇒ “亻丿士”,“行” ⇒ “彳亍”。类似地撇笔是组成横向 人字头时也不拆出,例如:“每” ⇒ “𠂉母”,“午” ⇒ “𠂉十”。 当撇笔连续到另一笔画时就不再是单撇,因此拆单撇的规则 就不再适用,例如:“反” ⇒ “𠂆又”,“丘” ⇒ “丘”即不规则 封闭。

拆顶底横

拆掉顶横就能得到更基础的部件的例子有: “天” ⇒ “一大”而不是“二人”(因为后者把交叉给拆没了), “下” ⇒ “一卜”,“无” ⇒ “一尢”,“互” ⇒ “一彑”, “𤴓 ” ⇒ “一龰”,“开” ⇒ “一廾”,“兀” ⇒ “一儿”。 但是包含“工”形结构的,顶底横都不拆,例如:“工王正五”。

拆出顶上两横的例子有:“元” ⇒ “二儿”而不是“一兀”, “亏” ⇒ “二㇉”而不是“一丂”。

拆底横的也有,例如:“立” ⇒ “[立-4]一”,“业” ⇒ “[业-4]一”, “卫” ⇒ “[卫-2]一”。

取大优先、不破交叉

取大优先是指不破坏交叉的情况下尽量先取出大的部件。比如: “元” ⇒ “二儿”而不是“一兀”。“羊” ⇒ “䒑𰀁”而不是先取“丷”。

取大优先还体现于尽量不拆单点。比如:‘亠’是字根,其中的点 不单独拆出。“为” ⇒ “[两点]力”而不是“丶力丶”。

编码规则

最初的编码设计对表形码有多处借鉴,但后来发现字根和英文 字母之间的象形映射对字根的安排有太多的约束,不利于方案的 优化调整。比如十字交叉形,除了X键就没有其它合适的位置了。 又比如离散两笔类有很多高频字根,却只能放在分号键上,打起来 就很不顺手。

最终决定还是采用类似五笔的分区方法,把字根分成五个大类, 比较规整地分配在键盘上。这五个类是:

  • 离散,即笔画分散,不连不交;
  • 连接,即笔画相连或相接,但不相交;
  • 交叉,即笔画相交;
  • 包围,即该字根可以包围其它字根;
  • 封闭,即该字根呈现一个封闭的区间。

每个大类里又分若干个小类,如下图所示。字根键位的安排基本上 按照食指、中指、无名指、小指,从简到繁。这样明显的规律可以 减少记忆负担,有些需要特别留意的字根已用红色标注。

拓扑形

所有字根及其编码都在 group.txt 文件中。采用27键编码,实在 没有理由放着原位键上的分号不用, 写中文有几时用得到分号呢? 如果一定要只用26键,可以把十交叉和木交叉合并,把金字旁移到 折交叉。

编码规则是前三末一,不足四码时加拼音的前两个字母。最关键的 是:当取形超过四码时,单笔划的横、竖、撇、点将被忽略, 除非该笔划是第一码。

全码重码有164组332字,而出简不出全时的重码只有18组37字。 所有简码根据汉字使用频率自动生成,不会有重码,也没有 无理码。其中一简字27个,二简字700多个,三简和三码字4300多 个,总共有5000多个字可以三码以内输入。动态平均码长 (不含空格上屏)是2.02。

表形键盘

以上区位键盘也可以重组成表形键盘如下,其中大部分键位的安排 都是依据形似,只有‘S’和‘D’是依据读音,另外‘U’和‘;’是无理 安排。表形键盘的指标和区位键盘相似,出简不出全时的重码略多, 打字舒适度稍差。

Q W E R t Y U i O P
囗田 氵⺍ 山𰀂 大尢 土干 人丫 木未 讠亠 阝卩
A S D F g H J K L ;
又女 丶丿 扌中 弓刀 艹一 亻丁 䒑丬 乚厶 小水
Z X C V B n M , . /
子力 𠂇乂 匚凵 冫丷 日㠯 宀ㄇ 门用

码表生成

生成区位键盘编码的命令行是:

./gene.py

产生的编码文件是 code.txt。在命令行上添加‘-a’选项则可以 生成表形键盘编码。

另外值得一提的是‘-o’选项对字根归类的优化以减少重码。 可以指定优化一个、多个、甚至全部字根。

安装

先安装小企鹅输入法:

sudo apt-get install fcitx-table

拷贝配置文件:

mkdir -p ~/.config/fcitx/table
cp ./shape.conf ~/.config/fcitx/table

然后运行:

./install.sh

以后每次修改或新生成编码文件后,同样运行 ./install.sh 使改动生效。

前因

十几年前还是学生的时候,我对输入法的制作产生了浓厚的 兴趣。那时的拼音还不够智能,还比不上拼形编码。印象 最深的是表形码,它把汉字字根和英文字母以象形的方式 联系起来。这种联系是如此地深刻,以至于从未实际使用过 表形码的我在十几年后还记得口是O,女是A,门是N, 纟是W …… 等等。

当时是个万码奔腾的年代,我只会拼音,也打不快,但我会写 程序。于是萌生了一个想法,可不可以用程序自动生成一个 编码方案,并加以优化呢?热血一涌上头,我就开始了自己 的拆字工程。GB2312有6763个汉字,前后花了几个星期, 终于把容易的复合字拆完了。复合字都有明显的左右结构、 上下结构或包围结构,所以容易。剩下的独体字就难了, 不同的形码有不同的拆法。于是又花了几个星期,按照比较 熟悉的表形码规则拆完了它们。

拆字可以说是形码设计过程中最耗时、最耗体力的部份了, 因为汉字实在是太多了。我只拆了六千多字就累得半死, 更不必说拆几万字的大字库了。如果不同的设计者们能够 共享这个过程,他们就可以有更多的精力去优化编码方案。 这些都是后话。

字是拆完了,也产生了两百多个字根。当时简单地把它们 按起始笔划归类,分配到26个英文字母键上,然后写了个 Python程序把6763个汉字编码,最长四码。结果统计了一下, 竟然有将近1300个重码。于是我又写了一个优化程序,自由 地把字根分配到字母键上。即使这样完全不实用的编码, 也有将近500个重码。真是不动手就不知道难啊!

之后因为学业,就没有继续在编码上花时间了。这一放, 就放了十几年。当有一天整理以前写过的程序时,不经意 发现了这一段尘封的往事,又提起了我对输入法的兴趣。 时过境迁,拼音已不是当年的拼音,其智能输入方式早已把 大量形码远远地甩在了身后,摇身一变成为主流。搞形码的 越来越少,我又有什么理由再把以前未完成的形码捡起来呢?

有!就因为我能。这已经是一个个性化的时代了,人们做事 不再是为了生计或是图个名利。想做就做,更多的是为了 与众不同。

后果

这个形声码方案算是完成了,一些指标看上去也不错。有什么 前途吗?没有!有什么钱图吗?更没有!说白了这就是一个 很好的玩具,可以用来消磨业余时间,体会一下当年“万码奔腾” 的那种感觉。俱往矣!如今也就剩下输入法爱好者还在玩形码, 少数专业录入人员还在用形码。

令人欣慰的是,形码已经完成了中文信息化的历史任务,在 电脑上或是用手机输入中文早已不再是问题,在某些方面甚至 超过了英文输入。中文信息处理从编码时代进入智能时代已 不可阻挡。电脑啊,让人脑变得更懒一些吧!

About

Custom Chinese input method with fcitx on Linux

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published