tig 是一个基于 ncurses 库的 git log、status 的浏览器,看 log 的时候非常方便,可以非常简单的查看每次 log 的 diff,同时方便的切换到其他视角例如 diff、blame、tree 等等。但是,tig 有一个问题,不支持搜索中文。

检查了相关的 issue 以后,确认了链接时使用 -lncursesw,支持中文这种宽字符的显示,实际应用中也可以显示,但就是没办法搜索中文。于是,我向作者报告了这个 bug:https://github.com/jonas/tig/issues/99

似乎作者不太在意 i18n 的问题,等了好几天都没有给答复,只好自己动手了。遇到问题的是搜索,按 search 关键字查找,定位到 REQ_SEARCH 上面去,这应该是 tig 内部状态机的一个状态。在 main 函数里,是一个很清晰的状态机,用 switch 语句切换不同的状态。可以看到,REQ_SEARCH 与 REQ_SEARCH_BACK 都调用到 read_prompt, 最终落到 prompt_input 读取输入。

看来 prompt_input 就是无法输入中文搜索的罪魁祸首了。得益于 tig 代码清晰的结构,定位这个 bug 还是比较容易的。为了确定用户输入的结束,prompt_input 通过一个外部参数 handler 确定一个字符是否是可见字符,如果是不可见字符,则不加入到 buf 中来。由于 utf8 的字符是变长的,兼容 ASCII 码,剩下的都是两字节字符和三字节字符。区分字长,则由第一个字符(又称引导字符)决定。

关于 utf8 的字符是如何区分两个字节和三个字节,可以参考这篇文章:

http://blog.csdn.net/cscmaker/article/details/7986968 (囧,看完才发现我修复的不完美)

根据这篇文章,我做了一个小的修复:

https://github.com/spin6lock/tig/commit/159eff692b24aa05f766f76922b0f2515fbbf415#tig.c

这里将 utf8 字符单独处理了,但是没有处理 utf8 标准里 4 个字节字符的情况。

不过作者一直没有 merge 到主分支上,残念啊。