通过 VIM 可以自动设置对齐方式,例如使用 Tab 还是空格,使用四个字节还是八个字节等等,而且,可以根据不同的语言设置不同的格式。
空格 VS. 制表符

使用空格还是 Tab 在 Coders 中争论已久,使用空格代码格式就已经固定了,不会再因为设置的 Tab 宽度不同而影响美观;如果使用 Tab 且提前约定好了宽度,其实也是可以的,还会节省字节。
在 VIM 中,主要通过如下几个配置项来设置:
tabstop设置 Tab 字符的显示宽度,并不影响 Tab 键的行为,需要关闭expandtab选项,否则看不出来。softtabstop会影响 Tab 键的行为,但是不修改 Tab 字符的宽度。expandtab把插入的 Tab 转换为特定数目的空格。
其中 softtabstop 会影响插入模式中按下 Tab 键实际得到的字符,可能是插入指定数目的空格,也有可能就是一个 Tab 字符,根 tabstop 和 expandtab 的设置有关。
- 只使用空格,需要设置
expandtab选项,插入模式中写入Tab会转换为tabstop个字符。 - 只使用
Tab,需要关闭expandtab选项,同时将softtabstop和tabstop设置为相同值。 - 混合模式,需要关闭
expandtab选项,同时将softtabstop设置为小于tabstop的值,下面将详细介绍。
对于前两种方式不做过多介绍了,这里仅介绍最后一种场景,这种方式的使用场景不多,一般是,希望在编辑模式时使用 4 个空格宽度,但是对于一些注释等信息,仍然使用 8 个空格宽度。
例如配置为 softtabstop=4 tabstop=8 时,第一次按下 Tab 键会转换为 4 个空格,再次按下 Tab 键之后会显示一个 Tab 字符,宽度为 8 个空格。
制表符和空格转换
可以通过 :set expandtab/noexpandtab 命令设置使用空格替换/不进行替换 Tab,对于已保存的文件,可以使用下面的方法进行空格和 Tab 的替换。
----- TAB替换为空格
:set ts=4
:set expandtab
:%retab!
----- 空格替换为TAB
:set ts=4
:set noexpandtab
:%retab!
加 ! 用于处理非空白字符之后的 TAB,即所有的 TAB,若不加 !,则只处理行首的 TAB。假设配置文件中使用了 set expandtab,如果想要输入 TAB,Linux 下使用 Ctrl-V + TAB,Win 下使用 Ctrl-Q + TAB 。
缩进模式
包括了 autoindent smartindent cindent 几种方式,也就是在新增一行时如何进行处理,包括了在 insert 状态用回车新增一个新行,或者在 normal 状态用 o/O 插入新行,都会根据配置的不同模式,进行不同的缩进。
autoindent会自动将当前行的缩进拷贝到新行,如果在新行没有输入任何字符,那么这个缩进将自动删除。smartindent对autoindent进行了一些改进,可以识别一些基本的语法,例如遇到}则取消缩进,注释开头则不使用缩进。cindent会识别语言的语法,自动地调整缩进的长度。
可以与上述配置共存。比如,当输入了半条语句然后回车时,缩进会自动增加一个 TABSTOP 值,当你键入了一个右花括号时,会自动减少一个 TABSTOP 值。
另外,可以通过 indentexpr 设置不同的模式,在此不详述,详见 vim reference manual 。
简介
通过 set list 可以在文本中显示当前格式,包括了 Tab、空格、换行等,与对齐相关配置可以通过如下方式配置。
set autoindent " 设置自动缩进
set smartindent " 对autoindent进行了一些改进
set shiftwidth=4 " 自动缩进所使用的空白长度
set tabstop=4 " 定义tab所等同的空格长度
set softtabstop=4 " 详见如下的解释
set expandtab " 将TAB自动替换为空格
set listchars=tab:▸\ ,trail:-,extends:>,precedes:<,eol:¬ " 设置不可见字符的显示方式
set nolist " 不显示TAB、空格、回车等不可见字符
filetype indent on " 可以通过如下的设置,根据文件类型自动进行设置
autocmd FileType python setlocal expandtab smarttab shiftwidth=4 softtabstop=4
autocmd FileType javascript,less set shiftwidth=2 | set tabstop=2 | set shiftwidth=2 | set expandtab
设置对齐方式
通过如下方式设置 C 语言的缩进方式,具体配置可查看 Vim documentation: indent 。
set cinoptions={0,1s,t0,n-2,p2s,(03s,=.5s,>;1s,=1s,:1s
常用命令
----- 执行缩进,前面可以加数字进行多节缩进
>> # Normal模式下,增加当前行的缩进
<< # Normal模式下,减少当前行的缩进
CTRL+SHIFT+T # Insert模式下,增加当前行缩进
CTRL+SHIFT+D # Insert模式下,减小当前行缩进
= # Visual模式下,对选中的部分进行自动缩进
: set list # 查看不可见字符,包括TAB、空格、回车等
问题排查
自动对齐失效
上述介绍的 cindent smartindent autoindent 是不依赖插件的,而通常根据代码类型的缩进是针对插件的,例如 /usr/share/vim/vim74/indent/c.vim 是针对 C 语言的,可以通过如下方式确认已经开启。
----- 默认会根据后缀自动识别,可以查看并手动设置
:set filetype
:set filetype=html
----- 默认不会开启根据文件类型加载缩进插件
:filetype indent on
有时候会发现自动对齐失效了,那么可以通过如下方式查看。
----- 确认是否正确时别文件类型
:set filetype
----- 文件类型缩进是否打开
:filetype
----- 对应文件类型是否加载,可以过滤或者导出到某个文件中
:filter /indent/ scriptnames
:redir > /tmp/vim.txt
:scriptnames
:redir END
----- 重新识别
:filetype detect
最佳实践
针对不同的语言会分别进行设置,如下是常见的规范。
" 两字节对齐,使用空格
autocmd FileType html setlocal expandtab ts=2 sw=2 sts=0
" 四个字节对齐,使用Tab
autocmd Filetype javascript,coffeescript setlocal ts=4 sw=4 sts=0 noexpandtab