编写一份好的 Vimrc

编写一份好的 Vimrc

翻译来自: https://dougblack.io/words/a-good-vimrc.html

发布日期: 2014年2月21日

更新日期: [2016-12-11 周日]

How To Vimrc

在炮制你自己的.vimrc配置时, 这里只有一个原则.

不要把任何你不理解的一行放到你的vimrc中.

互联网上有以吨计的入门手册, 诸如这篇文章. 它们之中包含各种令人惊叹的Hack技巧, 这可以记你的Vim更好, 但为了让你的环境更好完全从别人那儿照搬那些配置, 完全是 最糟糕 的做法.

真真切切地花一些时间来学习你的编辑器的构造, 其价值无可估量. 从投影仪上手抄下来通常会有且于增多的信息逐渐保留, 同样的道理, 将特性一个一个地添加到你的vimrc有助于提高你对Vim的总体理解程度.

因此, 这篇文章余下部分将会是我来解释我当前vimrc中的全盘使用的每一行, 希望你能在其中找到你此前没有见到的技巧. 但, 我的vimrc离完美还差得远. 我也一直在寻找可以使我的环境更好的东西添加进来, 所以如果你认为我遗漏了什么重要的东西, 敬请告之: @duogblackio.

我将按逻辑分成几个部分

  • 颜色
  • 空格与制表
  • UI配置
  • 搜索
  • 折叠
  • 自定义移动
  • 自定义Leader按键
  • Ctrlp设置
  • 启动配置
  • Tmux配置
  • Autogroups
  • 备份
  • 自定义函数
  • 组织
  • 折叠起来

这篇文章几乎肯定会落后于我最近的vimrc, 你可以在 github 上找到最新的vimrc版本.

Colors

colorscheme badwolf         " awesome colorscheme
            

颜色! 配色方案是主观的, 我当前是安顿在Steve Losh所写的badwolf上了. 我发现solarized难以至信的完整, 但也发现就我的品味而言它也那么点儿乏味. 我的大量的时间也是和 molokai 度过的. 并且我仍然认为 molokai 是一个非常好的配色方案, 只是当前更偏好 badwolf.

继续前进

syntax enable           " enable syntax processing
            

注释足以说清它的意思. 我将借这点时间, 尽可能地添加注释, 以避免你的vimrc没有此中的任何一行. 如果你像我一样, 文件写得很长, 基本上你不会一直记住每一行在做什么, 所以添加注释有助于你以后能知道这些都是什么鬼.

另外, 许多 vim 中的设置既有长名又有短名. 例如 background 和 bg 是一样的. 为了此后的可读性, 我强烈建议使用长名.

Spaces & Tabs

要使 tabs/spaces 能像你期望那样正常工作, 你必须将如下像咒语一样的符号, 扔到你的vimrc中. 你可能对这串符号相当困惑, 所以这儿有让你快速进修的说明.

set tabstop=4       " number of visual spaces per TAB
            

tabstop 就是视觉上显示的一个 <TAB> 算作的空格个数. 所以, 当 vim 打开文件读取到一个 <TAB> 字符时, 就会使用这么多个空格来显示 <TAB>.

set softtabstop=4   " number of spaces in tab when editing
            

编辑时一个 <TAB> 算作的空格数. 所以这既是你插入 <TAB> 时插入的空格数, 也是你用 backspace 移除的 (译注: 连续的) 空格数.

set expandtab       " tabs are spaces
            

expandtab 会将 <TAB> 转换为多个空格. 仅此而已. 所以 <TAB> 仅仅成为了 "插入4个空格" 的快捷键.

(以上几个配置)一起拿走吧, 这些选项是非常不错, 对于编辑那些偏好空格而不是 tab的语言, 因为这可以确保不会使用 <TAB>. 我每天花大多数时间与python与bash打交道, 二者的规范中写明了要使用空格. 我喜欢它, 因为它意味着我的源代码在所有的机器上看起来都是一样的.

UI Config

这些选项会改变 vim 中那此散乱的视觉材料.

set number              " show line numbers
            

显示行号, 不解释.

set showcmd             " show command in bottom bar
            

showcmd 显示在最右下角展示最近输入的命令. 我虽然在这里设置了, 但实际上由于我使用powerline插件(稍后我们会涉及到), 所以在我的vim中找不到这一行的.

set cursorline          " highlight current line
            

cursorline 会突出显示(或加下划线, 取决于你的配色方案)你的光标当前所在水平行. 我发觉当你 vim 的多个窗口来回切换或离开 vim 后再切换回来, 这样更容易找到离开时那一行.

filetype indent on      " load filetype-specific indent files
            

这既开启文件类型检测, 又开启基于此检测的与语言相关的缩进文件. 对于我来说, 这意味着, 每当我打开一个 *.py 文件, python 的缩进文件即 ~/.vim/indent/python.vim 将会被加载.

set wildmenu            " visual autocomplete for command menu
            

这是一个相当酷的特性, 我以前都不知道Vim有它. 你知道 Vim 会自动补全类似文件名的东西, 举例子, 运行 :e ~/.vim<TAB>? 那么它将会提供一个所有匹配项的图形菜单, 如果你开启了 wildmenu, 你就可以循环遍历它们.

set lazyredraw          " redraw only when we need to.
            

Vim 喜欢重绘屏幕, 即便是在它根本不必这样做的期间内 – 比如在宏(回放)的期间. 这告诉 Vim 不要费神地在这些场景下重绘屏幕, 以让宏更快.

set showmatch           " highlight matching [{()}]
            

当你的光标移动到 类似圆括号(译注: <([{都算)字符时, 与之配对的另外一个也会高亮显示.

Searching

我爱 Vim 的搜索. 如果有以下的设置, 我会更加爱它的.

set incsearch           " search as characters are entered
set hlsearch            " highlight matches
            

这些设置是自解释的. 它们使得搜索更棒.

" turn off search highlight
  nnoremap <leader><space> :nohlsearch<CR>
            

vim 从搜索开始直到你下一个搜索期间会保持高亮, 或者你可以手动停止旧有的搜索使用 :nohlsearch. 我发觉我一直运行这个命令, 所以我添加了一个映射.

Folding

Vim 折叠是一个不错但我不是那么重度使用的一个特性, 但当我想使用时, 我希望有一个合理的设置.

set foldenable          " enable folding
            

显示所有的折叠

set foldlevelstart=10   " open most folds by default
            

foldlevelstart 是打开一个新的 buffer 时的折叠级别. 如果设置为 0, 所有折叠都会被关闭. 设置为 99 可以确保折叠总是被打开的. 所以, 设置为 10 可以确保合适的嵌套代码块会被折叠起来, 当打开一个缓冲区时.

set foldnestmax=10      " 10 nested fold max
            

折叠是可以被嵌套的. 给折叠设置一个最大值, 能防止过多的折叠. 如果你需要超过 10 层的折叠, 你必须写一些 Javascript 的回调. 这让我对你印象不太好.

" space open/closes folds
  nnoremap <space> za
            

我经常改动 <space> 的按键映射, 但这是它当前的命令. za 打开/关闭 当前块的附近的折叠. 说点儿题外话, 我听说 vim 用 z 这个字符来表现折叠是因为它看起来就像一份折叠的报纸. 或许不是, 但这个故事还不错. :)

set foldmethod=indent   " fold based on indent level
            

这告诉 vim 基于缩进来折叠. 这对我尤其有用, 因为我用python. 其它的一些可接受的值有 marker, manual, expr, syntax, diff. 运行 :help foldmethod 来了解它们各自的意思.

Movement

这里我们开始涉及到自定义绑定. 这组绑定和移动命令相关.

" move vertically by visual line
  nnoremap j gj
  nnoremap k gk
            

这两行充许我们在可视行周围移动. 所以如果有一个较长的行被视觉上折叠成了两行, j 不会跳过 '伪' 行, 而直接跳到下一个真行.

  • in favor of 翻译难点
  • END
    " move to beginning/end of line
    nnoremap B ^
    nnoremap E $
    " $/^ doesn't do anything
    nnoremap $ <nop>
    nnoremap ^ <nop>
                        

    这些感觉像是我最受争议的绑定, 因为他们覆盖了已经存在的移动绑定. 我的认为敲击 ^ 和 $ 来跳转到一行的开始与结尾, 对于这么常用的移动功能有点不太舒服. 所以我重新绑定了 E 和 B, 二者经常用来向前, 向后移动一个视觉单词. 然后我绑定原来的方式到 <nop> 来训练自己使用之新的绑定.

    " highlight last inserted text
    nnoremap gV `[v`]
                        

    这相当酷. 它可视选择你上一次在插入模式下所添加的字符的区块.

Leader Shortcuts

到此可就是我的自定义键绑定的精华了. 这段内容将引进我自己使用众多的不同的插件和定制函数. 让我们开始吧.

let mapleader=","       " leader is comma
            

\ 距离 leader 有一点儿远. 我发觉',' 是一个好得多的替代品.

" jk is escape
inoremap jk <esc>
            

ESC 太远了. jk 替代它也好得多, 因为它在基准键位上, 而且我基本上在写文本时不会有需要打这两个字的时候. 除了现在我在写的这篇帖子的这个分段. 我是在 Vim 中写的. 如果你临时需要插入这些稀奇的序列, 变通方法就是键入 j , 等到 leader-check 超时失效后, 再键入 k.

" toggle gundo
nnoremap <leader>u :GundoToggle<CR>
            

Vim 最聪明的发明之一就是并不将 undo 建模为一个简单栈. vim中它是一个树. 这确保了你不会丢失在 Vim中的任何一个动作, 但也使得遍历整个树变得愈发困难. gundo.vim 修复了它, 通过在一个图形表单中展现一个撤销树. 获得它并不回头查看. 此处我将它映射到了 ,u, 我喜欢将其当作 'super udno'.

" edit vimrc/zshrc and load vimrc bindings
nnoremap <leader>ev :vsp $MYVIMRC<CR>
nnoremap <leader>ez :vsp ~/.zshrc<CR>
nnoremap <leader>sv :source $MYVIMRC<CR>
            

这是编辑和读取我的vimrc, zshrc配置的快捷按键. 就这么简单.

" save session
nnoremap <leader>s :mksession<CR>
            

一直想保存各式窗口, 以在下次打开vim时它们还在? :mksession 就是干这个的! 保存 vim 会话后, 重新打开时用 vim -S. 此处我将其映射到了 ,s, 我愿意将其当作 'super save'.

" open ag.vim
nnoremap <leader>a :Ag
            

Silver Searcher 是一个极妙的命令行工具, 来搜索项目中的源码. 他惊人地快. 这个工具的命令是 ag (就是化学元素银). 庆幸的是有一个不错的插件 ag.vim 可以让你不用离开vim就可以拉取搜索结果到 quickfix 窗口, 然后在匹配项之间轻松跳转. 此处我映射到了 ,a.

CtrlP

Ctrlp.vim 是我在Vim中的生活. 如果你从来没使用过模糊文件搜索器这会让你大开眼界. 如果你当前在使用commandt.vim, 那么你已经上道了, 但CtrlP 只是精神继承者. 它可能比 ComamndT 明显要快 (感谢 Reddit!). 不论怎么说, 这是我的 CtrlP 配置.

" CtrlP settings
let g:ctrlp_match_window = 'bottom,order:ttb'
let g:ctrlp_switch_buffer = 0
let g:ctrlp_working_path_mode = 0
let g:ctrlp_user_command = 'ag %s -l --nocolor --hidden -g ""'
            

这里设置了一些这些东西: 第一行我告诉 CtrlP 对匹配的文件按照从上到下排序也就是 'ttb'.
然后我告诉 CtrlP 总是在新的buffer中打开这些文件, 对应 'let ctrlpswitchbuffer=0'.
设置 "let g:ctrlpworkingpath=0" 让我们在 Vim 会话期间改变工作目录, 并让 CtrlP 遵守这一更改.

现在, 让我们谈谈速度. CtrlP 整个都是用 Vimscript 写的, (它相当令人印象深刻) 但 CommandT 有一部分是用C语言写的. 这意味着CommandT默认情况下是快于CtrlP. 然而, 我们可以告诉CtrlP来运行一个外部命令来寻找匹配文件. 现在既然我们已经安装了 ag, 我们可以将它与CtrlP 一起使用了, 这会让CtrlP惊人的快.. 我们可以通过以下几行做到:

let g:ctrlp_user_command = 'ag %s -l --nocolor -g ""'
            

如果一切进展顺序, 你应该注意到CtrlP的速度明显提升. 对此有两个警告:
"g:ctrlpshowhidden" 和 "g:ctrlpcustomignore" 都不能与自定制用户命令一起工作.
我只注意到了缺乏自定义的(文件)忽略. 还好, ag有它自己的忽略文件的惯例: 一个 .agitgnore
文件, 它和 .gitignore 遵循同样的惯例. 这真的太棒了! 我们在某个位置搜索时, 只需要定义我们要忽略的目录.

Launch Config

这些选项在启动时设置一些外部工具, 仅一次.

call pathogen#infect()                      " use pathogen
call pathogen#runtime_append_all_bundles()  " use pathogen
            

这些 pathogen 选项实际上会将所有位于 ~/.vim/bundles 目录下的插件, (注:按照插件类型)各自提取到(注:应该是映射)到 ~/.vim 目录下.

Tmux

" allows cursor change in tmux mode
if exists('$TMUX')
let &t_SI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=1\x7\<Esc>\\"
let &t_EI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=0\x7\<Esc>\\"
else
let &t_SI = "\<Esc>]50;CursorShape=1\x7"
let &t_EI = "\<Esc>]50;CursorShape=0\x7"
endif
            

这些设置, 当使用tmux的时候, 将光标的的形状从块状更改为水平的下划线. 如果没有这些行, tmux会一直使用块状光标模式(注:实际上依赖于终端的设置, 而不是tmux).

Autogroups

augroup configgroup
autocmd!
autocmd VimEnter * highlight clear SignColumn
autocmd BufWritePre *.php,*.py,*.js,*.txt,*.hs,*.java,*.md
\:call <SID>StripTrailingWhitespaces()
autocmd FileType java setlocal noexpandtab
autocmd FileType java setlocal list
autocmd FileType java setlocal listchars=tab:+\ ,eol:-
autocmd FileType java setlocal formatprg=par\ -w80\ -T4
autocmd FileType php setlocal expandtab
autocmd FileType php setlocal list
autocmd FileType php setlocal listchars=tab:+\ ,eol:-
autocmd FileType php setlocal formatprg=par\ -w80\ -T4
autocmd FileType ruby setlocal tabstop=2
autocmd FileType ruby setlocal shiftwidth=2
autocmd FileType ruby setlocal softtabstop=2
autocmd FileType ruby setlocal commentstring=#\ %s
autocmd FileType python setlocal commentstring=#\ %s
autocmd BufEnter *.cls setlocal filetype=java
autocmd BufEnter *.zsh-theme setlocal filetype=zsh
autocmd BufEnter Makefile setlocal noexpandtab
autocmd BufEnter *.sh setlocal tabstop=2
autocmd BufEnter *.sh setlocal shiftwidth=2
autocmd BufEnter *.sh setlocal softtabstop=2
augroup END
            

这里的大量的命令, 为某个特定filetype/文件的扩展, 所创始的语言特定的设置. 需要注意的是, 这些命令被包装在augroup中, 可以确保这些autocmd命令只被应用一次.
autocmd! 为当前这个group清除所有的已有autocmd命令.

Backups

如果你保持开着一个vim进程, 并且在其中更改了文件, vim会创建一个 "备份"(译注: 我想作者想说的是'swap'交换文件) 文件. 然后当你从另一个不同的vim会话中打开文件的时候, vim就会抱怨你在谋略编辑一个已经正在被编辑的文件. 此 '备份' 文件是通过在当前目录下的文件(名)后面追加一个 '~'符号来创建的. 这在你想要浏览器目录的同时会变得很烦, 所以我应用了以下的设置来移动备份文件到/tmp目录中.

set backup
set backupdir=~/.vim-tmp,~/.tmp,~/tmp,/var/tmp,/tmp
set backupskip=/tmp/*,/private/tmp/*
set directory=~/.vim-tmp,~/.tmp,~/tmp,/var/tmp,/tmp
set writebackup
            

'backup' 和 'writebackup' 启用了备份支持. 尽管这可能很惹人烦, 但总比丢失掉大量的已编辑但未保存的工作成果要好.

Custom Functions

我已经写了少量的自定义函数. 此处他们都带上了注释以解释其用途.

" toggle between number and relativenumber
function! ToggleNumber()
if(&relativenumber == 1)
set norelativenumber
set number
else
set relativenumber
endif
endfunc
            
" strips trailing whitespace at the end of files. this
" is called on buffer write in the autogroup above.
function! <SID>StripTrailingWhitespaces()
" save last search & cursor position
let _s=@/
let l = line(".")
let c = col(".")
%s/\s\+$//e
let @/=_s
call cursor(l, c)
endfunction
            

Organization

FIXME orgmode导出出了问题, 正在调试

Wrapping It Up

我希望能帮到你. 尽管有成吨的(现成)东西, 真实情况是, 我仍然信守我的老生长谈:

不要把任何你不理解的一行放到你的vimrc中.

那么, 如果你从这儿抓取了几行, 确保你添加了注释, 实实在在地解释它们在干嘛. 如果做不到, :help [setting] 是你最好的朋友.

感谢阅读! 别忘了把你的.vim 小建议发送给我, 地址在 @dougblackio.

更新:
  • [2019-03-16 周六 07:36] 解决拼写错误,修正导出文档的结构
上一篇:3.commonjs模块


下一篇:linux系统性能监控--CPU利用率