如何优雅的使用 Vim(一):基本配置
Vim 十年,青春不再
转眼间,Vim 已用了十年。
从一开始的抵触、不解,到随之而来的习惯、喜欢,再到近几年编辑器层出不穷的盛况下对 Sublime Text 等短暂的尝试,以及最后即现在的回归,这是一个复杂的过程。
目前,我对 Vim 仍停留在配置和使用阶段,并没有为它开发过任何插件。希望接下来十年,能为它做一些贡献。
Vim 是一个难学难上手,即使熟悉了也会让你痛并快乐着的那种编辑器。要教别人用 Vim,就更是难上加难了。
从 如何评价GitHub准备推出下一代文本编辑器Xray? 一文,可以看到时下不少编辑器的尝试。软件行业发展到今天,编辑器远远没有达到一个完美的境界,包括 Vim,这本身就是一件很不可思议的事情。
基础设置
最最基本的一些设置,位于 vimrc 的开头。
" 首先设置 mapleader,后面键盘映射随时要用
" 基本上所有自定义的快捷键都以这个字符打头,比如映射`,w`为`:w`
let mapleader = ","
let g:mapleader = ","
" 不兼容 Vi,最大限度使用新特性
set nocompatible
" 写入文件时,不做备份
set nobackup
set nowritebackup
" 不用交换文件
set noswapfile
" 保存文件的快捷键
nmap w :w!
" 移除 Windows 文件结尾的 `^M`
noremap m :%s///ge
" 重新打开文件时,恢复上一次游标位置
" 通过View可以记住很多设置,比如高亮当前行、折行等等,但是往往比较让人费解
set viewoptions=cursor " 只记住游标
au BufWinLeave ?* mkview
au VimEnter ?* silent loadview
" 检测文件编码时,优先考虑 UTF-8
set fileencodings=utf-8,ucs-bom,gbk,gb2312,big5,latin1
" 不同平台,设置不同的行尾符,即 EOL
" 注意:在 Mac 平台,也是 unix 优先;自 OS X 始,行尾符与 Unix 一致,
" 都是 `\n` 而不是 `\r`
if has("win32")
set fileformats=dos,unix,mac
else
set fileformats=unix,mac,dos
endif
" 在断行、合并(join)行时,针对多字节字符(比如中文)的优化处理
set formatoptions+=mM
配色方案
目前主要使用 morhetz/gruvbox
,本文所有截图都是 gruvbox
的效果。
配色方案可以通过插件安装,这里先跳过,会有另一篇文章专门介绍插件。
set background=dark
syntax enable
colorscheme gruvbox
au BufEnter * :syntax sync fromstart
格式
缩进选项
" 采用 C 风格的缩进,适用于大多数语言
" 细节调整见下面的 `cinoptions`
" 你也可以尝试 smartindent 和 autoindent
set cindent
" 细节调整,主要为了适应 Google C++ Style
" t0: 函数返回类型声明不缩进
" g0: C++ "public:" 等声明缩进一个字符
" h1: C++ "public:" 等声明后面的语句缩进一个字符
" N-s: C++ namespace 里不缩进
" j1: 合理的缩进 Java 或 C++ 的匿名函数,应该也适用于 JS
set cinoptions=t0,g1,h1,N-s,j1
制表符 vs. 空格
让制表符智能一些。
set smarttab
对程序员来说,用制表符还是用空格,足以引发一场战争。
美剧《硅谷》中,Richard 因为不能接受女友用空格缩进而断然与之分手。
下面的设置并不优雅,各人需求不一样,需做相应调整。
" 先设置缺省情况,然后根据不同文件类型再次重新设置
set expandtab | set tabstop=4 | set shiftwidth=4 " Python, CSS, etc.
" 对 C/C++ 等,制表符和缩进都是两个空格
au FileType c,cpp,html,htmldjango,lua,javascript,nsis
\ set expandtab | set tabstop=2 | set shiftwidth=2
" Makefile 必须保留制表符,且习惯上占八个空格
" 不过,这年头谁还会写 Makefile?
au FileType make set noexpandtab | set tabstop=8 | set shiftwidth=8
文本宽度
除了缩进,另一个深具争议的话题就是 80列 限制。
虽然现在显示器大了很多,有些语言习惯上仍然遵守这一规则。
通过设置 textwidth
,Vim 可以帮我们在输入时或用gq
格式化时自动断行。
我发现,用 gq
格式化注释特别方便,超长的注释会自动重新排版,以保证不越过指定的长度。
目前,我仅对 C/C++/Python/Vim 做这种限制。
au FileType c,cpp,python,vim set textwidth=80
一般如果设定了宽度限制,最好能画一条竖线以警示。
设置 colorcolumn
即可。甚至可以设置为多列,比如 "81,101"。
我是所有文件类型都显示这么一条线。
set colorcolumn=81
折行
通常代码不需折行,前面有些语言设置了宽度限制就更不需要了。
实际操作下来,纯文本、Markdown、XML 等比较需要折行,因为它们常常一行太长了。
au FileType text,markdown,html,xml set wrap
" 折行时,以单词为界,以免切断单词
set linebreak
" 折行后的后续行,使用与第一行相同的缩进
set breakindent
用户界面
" 即使在终端,也尽量启用鼠标
if has("mouse") | set mouse=a | endif
" 显示输入中的命令,对 gqq/gcc 这种多个字符的命令特别有用
set showcmd
" 下面几个不解释,自行查看帮助
set scrolloff=7
set wildmenu
set wildmode="list:longest"
set ruler
" 命令行高度为两行
set cmdheight=2
" 永远显示行号
" 另有比较酷的相对行号(`relativenumber`),虽然我用不习惯
set number
set lazyredraw
" 切换缓存时不用保存
set hidden
" 输入模式下,退格键可以退一切字符
set backspace=eol,start,indent
set whichwrap+=<,>,h,l
高亮不想要的空格,比如行尾。
" See [http://vim.wikia.com/wiki/Highlight_unwanted_spaces]
" - highlight trailing whitespace in red
" - have this highlighting not appear whilst you are typing in insert mode
" - have the highlighting of whitespace apply when you open new buffers
highlight ExtraWhitespace ctermbg=red guibg=red
match ExtraWhitespace /\s\+$/
autocmd BufWinEnter * match ExtraWhitespace /\s\+$/
autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@
高亮当前行。
set cursorline
不过,我一般不用,因为闪烁的游标就已经很清楚了。
搜索
首先,搜索时忽略大小写(ignorecase
)。但是,如果搜索模式里有大写字母,就不再忽略大小写(smartcase
)。
set ignorecase
set smartcase
即时显示匹配结果(incsearch
),并高亮所有结果(hlsearch
)。
set incsearch
set hlsearch
map :nohlsearch
替换时,缺省启用g
标志,即,同一行里的所有匹配都会被替换。
set gdefault
切换窗口
切换窗口的键盘映射:
map j
map k
map h
map l
以及,直接用方向键切换缓存的键盘映射:
map :bn
map :bp
map :bf
map :bl
缩写(Abbreviation)
当前日期、时间、文件名这些内容,用缩写来输入是再方便不过了。
当然,缩写本身的名字不能太常见,下面这些都以 x 打头,一般不会出现在正常的文本中。
iabbrev xname " 改成你自己的名字
iabbrev xmail " 改成你自己的电邮
iabbrev xfile =expand("%:t")
if exists("*strftime")
iabbrev xdate =strftime("%Y-%m-%d") " 当前日期
iabbrev xtime =strftime("%H:%M:%S") " 当前时间
endif
删除行尾空格
前面用户界面一节已经提到如何高亮行尾空格,下面设置可以删除行尾空格。
# 这个函数通过替换命令删除行尾空格
func! DeleteTrailingWS()
exec "normal mz"
%s/\s\+$//ge
exec "normal `z"
endfunc
" 保存时自动删除行尾空格
au BufWrite * :call DeleteTrailingWS()
map W :call DeleteTrailingWS()
" 移除只包含空格的行里的空格(有点绕口)
" 貌似有了前面的函数,这个就没有什么必要了
map :%s/\s*$//g:noh''
结语
配置是无穷无尽的,是乐趣也是包袱。
这篇文章,并不是我的 Vim 配置的全部,而我的 Vim 配置,也经常性的在变。
此外,我主要写 C++ 和 Python,可能并不适合你。但是道理是一样的,总是免不了折腾。
所以,没有现成适用于所有人的配置,都是在别人的基础上不断收集和改进而成。
为了避免文章太长,常用插件的介绍就另起一篇吧。
<全文完>