中文输入不是「能打出汉字」就算完成

中文输入不是「能打出汉字」就算完成

砚最开始就要读中文 Markdown,也要输入中文。这个需求如果等界面都搭完才补,后面会不断在坐标、删除和撤销上返工。

"能输入你好"只覆盖了很小的一部分。按词移动、选区替换、全角标点、组合字符、候选框位置,以及组字时突然切换标签,都在这条链路里。

先把三个坐标系分开

一个汉字的 UTF-8 字节数,不等于它在终端里占的格数;一个用户看见的字符,也未必只含一个 Unicode 码点。

所以砚内部的字节偏移、字素边界和显示宽度各有职责:文本修改用字节,光标移动与删除尊重字素,布局计算显示宽度。终端布局尽量和 tcell 使用相同的宽度规则,减少两边对同一字符算出不同位置。

即便如此,实际终端的设置仍然要验证。尤其是中英文混排、弯引号、省略号、破折号这些内容,不能只用 ASCII 的测试文件判断光标没问题。

终端输入法与窗口输入法是两条链路

终端版里,组字和候选界面主要由终端及系统输入法负责。砚需要把真实终端光标放到插入点,并处理最终送来的文本。

这也解释了为什么"画一个像光标的色块"不够。用户看到的插入点和系统认识的光标位置如果不同,候选框就可能跑偏。

窗口版则会接到组字过程里的事件。砚接入 MyGo 后,把预编辑和正式提交分开:组字中的文字不直接当作正式编辑记录,提交时使用 OriginIME,一次组字对应一个撤销步骤。

最初 Gio 方案讨论过临时事务模型;当前 MyGo 路径已经不同。不能把旧方案里"如何处理预编辑"的描述原封不动贴到现在的实现上。

一个不容易想到的情况:组字时换标签

假设正在 A 文件里输入拼音,文字还没提交,这时切到了 B。紧接着系统发来了输入法提交事件。

如果事件处理只读取"当前标签",这段文字就会跑到 B 里。

现在的处理是记录开始组字时的输入目标。提交仍然回到那个目标;如果原标签已关闭,显示提示,而不是悄悄写进另一个文件。

这种错误未必每天遇到,但编辑器一旦发生,用户很难相信自己刚才看见了什么。和简单的输入测试相比,它更值得成为一个固定回归用例。

输入法测试也要写清楚测到了哪一层

当前发布报告记录了模拟 MyGo 组字事件的覆盖:预编辑不正式写入、提交、取消、替换选区、一次提交一次撤销、组字中切标签。

这些验证的是应用如何处理事件。系统拼音是否在真实窗口里给出正确候选位置,微信输入法、搜狗、Rime 是否行为一致,仍然需要真实输入法来测。

alpha.1 的发布报告明确把真实键盘和系统拼音窗口体验列为未验证项。后续功能变多,也不会自动让这项变成通过。

这篇我愿意把边界写得具体一点:砚已经为中文处理建立了内核约定和模拟测试,但还不能说所有输入法、所有输入框、所有位置都已验证完成。

对我最有用的经验

中文支持应该从文本模型开始,一直延伸到系统事件和真实设备。把最后一屏截图里出现汉字当成验收,很容易漏掉最影响使用的部分。

下次再做文本输入相关的工具,我会更早准备混合文本和操作场景:行尾组字、滚动后组字、选区覆盖、连续提交再撤销。这些场景比单纯多准备几句中文,更容易找到问题。


相关推荐
敲代码的玉米C1 小时前
把熟悉的操作带回来:快捷键和 Markdown 预览
go
敲代码的玉米C1 小时前
从打开一个文件,到打开一个项目
go
敲代码的玉米C1 小时前
终端里的小细节:选中复制、截图粘贴和项目提醒
go
敲代码的玉米C1 小时前
一个内核,两张脸:先把终端编辑器跑起来
go
敲代码的玉米C1 小时前
编辑器的第一块砖:文本、快照和撤销
go
敲代码的玉米C1 小时前
路线拐了个弯:接入 MyGo,借鉴 Mayoi
go
敲代码的玉米C1 小时前
写到 alpha.6:现在有什么,还有哪些账没还
go
敲代码的玉米C1 小时前
自动换行和多项目:看着是 UI,背后都是状态
go
敲代码的玉米C1 小时前
第一次打出 DMG:能运行,离能发布还有多远
go