2009年9月2日星期三

Vim对中文编码的支持

1、支持中文编码的基础
Vim
要更好地支持中文编码需要两个特性:+multi_byte和+iconv,可以用|:version|命令检查当前使用的Vim是否支持,否则的话需要重新编译。
2、影响中文编码的设置项
Vim中有几个选项会影响对多字节编码的支持:

encoding(enc):encoding是Vim的内部使用编码,encoding的设置会影响Vim内部的Buffer、消息文字等。在Unix环境下,encoding的默认设置等于locale;Windows环境下会和当前代码页相同。在中文Windows环境下encoding的默认设置是cp936(GBK)。
fileencodings(fenc):Vim在打开文件时会根据fileencodings选项来识别文件编码,fileencodings可以同时设置多个编码,Vim会根据设置的顺序来猜测所打开文件的编码。
fileencoding(fencs)
:Vim在保存新建文件时会根据fileencoding的设置编码来保存。如果是打开已有文件,Vim会根据打开文件时所识别的编码来保存,除非在保存时重新设置fileencoding。
termencodings(tenc):在终端环境下使用Vim时,通过termencoding项来告诉Vim终端所使用的编码。

3、Vim中的编码转换
Vim内部使用iconv库进行编码转换,如果这几个选项所设置的编码不一致,Vim就有可能会转换编码。打开已有文件时会从文件编码转换到encoding所设置的编码;保存文件时会从encoding设置的编码转换到fileencoding对应的编码。经常会看到Vim提示[已转换],这是表明Vim内部作了编码转换。终端环境下使用Vim,会从termencoding设置的编码转换到encoding设置的编码。
可以用|:help encoding-values|列出Vim支持的所有编码。
4、具体应用环境的设置

只编辑GBK编码的文件

set fileencodings=cp936
set fileencoding=cp936
set encoding=cp936

只编辑UTF-8编码的中文文件

set fileencodings=utf-8
set fileencoding=utf-8
set encoding=cp936 或者 set encoding=utf-8

同时支持GBK和UTF-8编码

set fileencodings=ucs-bom,utf-8,cp936
set fileencoding=utf-8
set encoding=cp936 或者 set encoding=utf-8

如果在终端环境下使用Vim,需要设置termencoding和终端所使用的编码一致。例如:

set termencoding=cp936 或者 set termencoding=utf-8
Windows记事本编辑UTF-8编码文件时会在文件头上加上三个字节的BOM:EFBBBF。如果fileencodings中设置ucs-bom的目的就是为了能够兼容用记事本编辑的文件,不需要的话可以去掉。Vim在保存UTF-8编码的文件时会去掉BOM。去掉BOM的最大好处是在Unix下能够使用cat
a b>c来正确合并文件,这点经常被忽略。
5、FAQ
为什么在Vim中一次只能删除半个汉字?
因为encoding设置错误,把encoding设置为cp936就可以解决此问题。在Unix环境下Vim会根据locale来设置默认的encoding,如果没有正确设置locale并且没有设置encoding就会一次只能删除半个汉字。
VIM为什么不能输入繁体字?
把euc-cn或者GB2312改为cp936就可以了。euc-cn是GB2312的别名,不支持繁体汉字。cp936是GBK的别名,是GB2312的超集,可以支持繁体汉字。
VIM为什么提示不能转换?
因为在编译Vim时没有加入iconv选项,重新编译Vim才能解决。
如何打开一个GBK编码的文件并另存为UTf-8编码?
保存文件时运行命令|:set fileencoding=utf-8|就可以了。

vim的编码详解和中文环境设置

很惭愧,作为vim的忠实用户,自从2年多前从help里知道了:edit
++enc=xxx这个命令之后,我就没有去了解过vim的编码设定了。这些年来,我遇到编码出错,总是:edit
++enc=xxx。今天:help了一下encoding等,终于搞清楚了相关的各个变量的作用和关系。
简单的说,有三个设置。(我下面基本以中文环境来作为说明)
1) 在.vimrc或者_vimrc里加入set
fileencodings=utf-8,gb2312,gbk,gb18030,big5这句就基本OK了。vim会依次使用这些编码对文件进行编码的猜测。
2) 如果还是不行,那么在打开文件之后,用:edit
++enc=gbk这个命令强制使用某个编码。
3) 如果依然不行,请检查你的$LANG环境变量。
下面是详细的说明。
vim编码主要涉及三个变量。
encoding
vim的内部编码,包括内存数据的编码,vim配置文件的编码。encoding取自变量$LANG,如果$LANG为空,则取latin1。这个编码应该和你的终端编码保持一致的。
fileencoding
文件的编码。vim在加载文件的时候,会把这个编码转换成encoding参数的编码。同样的,保存文件的时候,内存的编码会由encoding转变为fileencoding。
需要注意的是,在vimrc里设置这个参数,不会起作用。因为打开一个文件的时候,fileencodings或者encoding会覆盖fileencoding。关于这个,可以看下面提到的打开文件流程。
fileencodings=utf-8,gbk,gb2312
vim在加载一个文件的时候,会依次尝试使用fileencodings里的编码作为fileencoding。如果全部失败,那么vim会使用encoding作为fileencoding。
另外,如果vim使用了错误的编码,可以使用edit
++enc=gbk这个命令。意思是,重新读取文件,并强制使用gbk作为fileencoding。这时候会忽略filencodings。
以下是一些vim操作的内部流程
打开文件
首先从文件读入数据到内存,然后从fileencodings里依次使用各个编码来尝试转换为encoding。如果有一个成功,则中止尝试。如果找不到,则取encoding作为fileencoding。也就是说,这里有一个从fileencoding转换为encoding的过程。
保存文件
把内存的数据,从encoding,转换为fileencoding,然后写入文件。
其实在这里最容易让人搞不清楚的就是encoding和fileencoding的区别。因为在大多数GUI特别是WINDOWS平台的编辑器里,encoding都是不需要设置的。通常这个encoding都是默认和GUI环境的编码保持一致。encoding是数据在内存里的存储编码,而fileencoding才是文件的编码。