Comment #25 on issue 123 by
suxp...@gmail.com: 关于 标准字库 vimim.cjk.txt
的黑框问题
http://code.google.com/p/vimim/issues/detail?id=123
- -|| 敢情上面发了这么多都白说了……
我的 OS 是更加有名的 Windows XP,在 cmd 下写过程序(cl.exe && gcc.exe)、写
过论文、课件(LaTeX),vim 目前用 7.3,因为曾经折腾 enc=UTF8 铩羽而归所以保
持默认的 GBK 不敢动。
作为一个“伪程序员”,作为一个没有编译过 Vim 的“伪”Vimmer,根据使用时的表
现等做出如下猜测(Windows 平台):
1. Gvim 要通过 vimrun.exe 来执行外部程序;
2. vimrun.exe 将通过启动 Cmd 进程/线程来运行外部命令(cmd /c command);
3. vimrun.exe 在启动命令时会接管它的 stdout,然后(混合自己的信息?)输出到
stdout;
4. (G)vim 中 :make 等会通过将 cmd 的输出重定向到某个临时文件来给 Quickfix 使
用;
5. vim 中由于跟 cmd 共用窗口所以直接将输出传递给 cmd 来显示;
下面分情况讨论如下假想实验并实际操作来验证:
1. Gvim set enc=gbk(默认),执行 :make,此时根据 vim 里面相关变量的设定,
Gvim 执行 !make,将输出重定向到临时文件(嗯,编码自然应该是 GBK 了,由于这
个临时文件太临时,试了 N 次没有顺利得到临时文件的内容,但通过直接 cmd /c
make > tmp.txt 2>&1,可以测试输出结果确实是 GBK 编码),过滤到 quickfix 缓
冲区,Gvim 的末行根据 language 的设定显示相应 message(目前也是 GBK 编码)
,其中加入执行命令的返回值,从而显示出:第一行执行的命令;第二行返回值;
第三行添加行号等的错误信息;末行Vim本身的提示信息。由于编码都是 GBK 所以无
所谓转码,也就没出现乱码问题,见附图 1;
2. Gvim set enc=utf8, 同时设定其他选项修正提示信息的乱码问题(:lan mes
zh_CN.UTF-8),再次执行 :make,依然是上面的步骤:Gvim执行 !make,输出重定向
到临时文件(应该仍然是 GBK 编码),过滤到 quickfix 缓冲区,Gvim末行显示
UTF8 的 message:第一行执行的命令;第二行 shell 返回值;第三行添加行号后追
加 quickfix 缓冲区的错误信息(这儿跟其他三行不同,错误信息是 GBK 编码),最
后一行 Vim 的提示信息。由于 quickfix 缓冲区没有转码成 UTF8,从而第三行会将
GBK 的字串按照 UTF8 方式显示出来,——于是乱码。见附图 2 以及作为对比的以
UTF8 方式显示 GBK 字串的附图 3。(由于 Gvim 执行外部命令会开 cmd,实际上是
vimrun 的窗口,在 cmd 内部也无所谓转码问题,因而这种实验就没有必要“做”了
,——即使做了自然也是正常,没乱码)。
3. vim set enc=gbk(默认),执行 :make,没所谓转码问题,无乱码,第一屏显示
shell 返回值,提示信息“请按 Enter 或其他命令继续”,但不知何故该提示信息不
是在最下面,而且光标的位置有点反常,见附图 4(更加诡异的问题在于,当 :make
之前没有 cls 清屏,输出信息跟光标的位置将无所定位,原因不明)。按 Enter 或
者 Space 后,显示第二屏,前面的输出仍然保留,下面显示 quickfix 缓冲区的错误
信息及行号等,末行是 Vim 提示信息,见附图 5。
4. vim set enc=gbk(默认),执行 :!dir,第一屏显示执行结果及提示信息“请按
Enter 或其他命令继续”(附图 6),按 Enter 或者 Space 后退回 Vim 界面,无乱
码。
5. vim set enc=utf8, lan mes zh_cn.utf-8, set tenc=gbk,执行 :make,第一屏
仍然是显示 shell 返回值跟提示信息(那个诡异的定位问题依然存在),由于这些信
息由 Vim 输出,根据设定应该是 UTF8 的文本,——而 CMD 将他们当作 GBK 输出,
于是成了这个样子:附图 7。作为对比,附图 8 跟 9 分别演示了在 Gvim 中开 UTF8
文件并 set enc=gbk,以及在 cmd 中直接 type 一个 UTF8 的文件时的表现。第二屏
,上面的信息依然存在,下方显示 quickfix 行号跟错误信息,末行 Vim 本身的提示
信息,见附图 10。这里 quickfix 看上去仍然是前面的问题,实际上 Vim 因为
tenc=gbk 的原因,本身将字串按照 utf8 编码先转换到 GBK 才传给 CMD 显示出来,
但令人疑惑的是,为什么前面的 shell 返回值没有转码?(或许 Vim 认为那个不属
于自己的窗口而只是简单的将 UTF8 的字串输出?)
6. 同上设定,执行 :!dir,由于 dir 本身的输出是 GBK,所以前面的输出结果正常
;后面 Vim 会添加自己的信息,这个信息就不正常了,——依然是 cmd 中 type
utf8 编码的文件那种问题,见附图 11。
猜测/结论:
1. Gvim 执行外部命令通过 vimrun.exe 并获取返回值,vimrun.exe 作为一个简单的
Win32 console 应用程序,本身输出是 GBK 编码(它的作用似乎仅限于后面追加一个
暂停功能);Gvim 本身的编码转换处理没太大问题,但在 Quickfix 中不作编码转换
而是直接使用字串,于是造成 Gvim 中 :make 时的那个乱码;
2. vim 本身没有窗体,“寄生”在 cmd 上,似乎也不需要 vimrun 这个追加暂停以
用于让用户看见命令输出的鸡肋,直接通过启动它的 shell 运行命令。在 enc 跟
tenc 不同时,vim 会将自身窗体的所有内容进行转码再传递,但是对于直接输出到
stdout 的信息,Vim 没做任何手脚,——直接按照 language message 的设定来输出
,于是会看到 cmd 中显示乱码。对 Quickfix,跟 Gvim 一样。
如何解决?
1. Quickfix 为什么不可以做编码转换?
2. vim 在 print message 时为什么不按照 tenc 的设定来做必要的转换?
以上两点解决,那么我认为 set enc=utf8 时 Vim 完全有能力显示正常,不再有乱
码。
当然上面大部分仍然是我的猜测,具体是否真的如此,有待大牛爆料。
Attachments:
gvim-gbk-make.png 25.1 KB
gvim-utf8-make.png 30.3 KB
gvim-utf8-on-gbk-file.png 18.3 KB
vim-gbk-make-1.png 23.2 KB
vim-gbk-make-2.png 24.0 KB
vim-gbk-dir-1.png 26.4 KB
vim-utf8-make-1.png 23.0 KB
gvim-gbk-on-utf8-file.png 17.6 KB
cmd-type-utf8-file.png 25.0 KB
vim-utf8-make-2.png 24.4 KB
vim-utf8-dir-1.png 26.5 KB