VIM 自动对齐配置

2020-04-03 vim develop

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

空格 VS. 制表符

tabs spaces funny

使用空格还是 Tab 在 Coders 中争论已久,使用空格代码格式就已经固定了,不会再因为设置的 Tab 宽度不同而影响美观;如果使用 Tab 且提前约定好了宽度,其实也是可以的,还会节省字节。

在 VIM 中,主要通过如下几个配置项来设置:

  • tabstop 设置 Tab 字符的显示宽度,并不影响 Tab 键的行为,需要关闭 expandtab 选项,否则看不出来。
  • softtabstop 会影响 Tab 键的行为,但是不修改 Tab 字符的宽度。
  • expandtab 把插入的 Tab 转换为特定数目的空格。

其中 softtabstop 会影响插入模式中按下 Tab 键实际得到的字符,可能是插入指定数目的空格,也有可能就是一个 Tab 字符,根 tabstopexpandtab 的设置有关。

  • 只使用空格,需要设置 expandtab 选项,插入模式中写入 Tab 会转换为 tabstop 个字符。
  • 只使用 Tab,需要关闭 expandtab 选项,同时将 softtabstoptabstop 设置为相同值。
  • 混合模式,需要关闭 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 会自动将当前行的缩进拷贝到新行,如果在新行没有输入任何字符,那么这个缩进将自动删除。
  • smartindentautoindent 进行了一些改进,可以识别一些基本的语法,例如遇到 } 则取消缩进,注释开头则不使用缩进。
  • 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