阅读 1979

Vim配置之进阶篇

在上一篇博文Vim配置之入门篇中,只是大略介绍了 Vim 的基本配置以及几个常用的使用插件,但是在后面的使用中发现该配置的Vim并不是很好用,特别是 minibuffer,taglist,fileexplore 直接存在冲突,而且它的插件管理也比较麻烦。本篇博文主要就是解决这两个问题以及尝试一些更适合码农的插件。

简介

之前使用 Vim 的初衷一方面是其插件的强大,更主要的方面是适合装 13 。但是随着对 Vim 更多的了解,才发现Vim的强大还是有缘由的,从下面的评价足以看出:

  • 世界上只有三种编辑器,EMACS、VIM和其它
  • VIM is the God of editors, EMACS is God’s editor
  • EMACS is actually an OS which pretends to be an editor

根据上篇博文中的配置在日常使用的出现的问题,在此给出解决方案,对于插件间的冲突问题是用 tagbar 取代 taglist,而插件管理是采用 bundle 插件。对于 Vim 里面实用方便的插件的确有不少。

高效插件

vim的插件很多,而且功能很强大,非常强大。官网的插件地址在这里

vundle

vundle是个用来管理vim插件的插件,它高效的利用了git,使得vim插件的安装,更新和卸载都交由vundle管理,从而将使用者从vim安装配置中解放出来。

  1. 安装vundle

    git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle
    复制代码
  2. 使用 vundle 管理 Vim 插件

    1. Vim Script 选好想要使用的插件

    2. 在 Vim 配置文件 .vimrc 中添加 Plugin plugin_name

    3. 执行 vundle 初始化命令 :PluginInstall,插件就安装好了

    4. 常用命令

      # 更新插件
      :PluginInstall!
      # 清除不再使用的插件
      :PluginClean
      # 列出所有插件
      :PluginList
      # 查找插件
      :PluginSearch
      复制代码
    5. vundle在.vimrc中的配置

      " 文件类型检测关闭[必须](/usr/share/vim/vim74/filetype.vim)
      filetype off
      " 设置runtime path包含Vundle的路径并且初始化
      set rtp+=~/.vim/bundle/Vundle.vim
      " 设置plugins安装地址
      call vundle#begin('~/.vim/bundle/')
      " 安装Vundle,让其管理插件[必须]
      Plugin 'gmarik/Vundle.vim'
      
      """"""""""""""""""""""""""""""""""
      " Vundle插件安装样例:
      " 插件在github上
      " Plugin 'tpope/vim-fugitive'
      " 插件来自网页http://vim-scripts.org/vim/scripts.html
      " Plugin 'L9'
      " Git插件,但插件不在Github上
      " Plugin 'git://git.wincent.com/command-t.git'
      " 插件在本地机器上 (i.e. when working on your own plugin)
      " Plugin 'file:///home/gmarik/path/to/plugin'
      " The sparkup vim script is in a subdirectory of this repo called vim.
      " Pass the path to set the runtimepath properly.
      " Plugin 'rstacruz/sparkup', {'rtp': 'vim/'}
      " 使用用户名来避免插件冲突 ie. L9
      " Plugin 'user/L9', {'name': 'newL9'}
      """"""""""""""""""""""""""""""""""
      
      " 所有插件的添加在end之前[必须]
      call vundle#end()            
      " 文件类型对应的插件[必须](/usr/share/vim/vim74/ftplugin.vim)
      filetype plugin on
      " 文件类型对应的缩进文件
      filetype indent on
      复制代码

The-NERD-tree

NERDTree 是 Vim 最常用的插件之一,可以在 Vim 运行时显示目录和文件结构,类似 TextMate 左侧的文件浏览器,但操作起来更为方便,你可以在手不离开键盘的情况下快速浏览文件,并在文件和文件夹之间进行切换。其样例如下图所示: NERDTree

  1. 在vim中的安装和配置

    call vundle#begin('~/.vim/bundle')
    " 在Vim的编辑窗口中树状显示文件目录[The-NERD-tree]
    Plugin 'The-NERD-tree'
    call vundle#end()  
    
    """"""""""""""""""""""""""""""""""
    " The-NERD-tree配置
    """"""""""""""""""""""""""""""""""
    " 不显示缓冲文件,中间文件
    let NERDTreeIgnore=[ '.pyc$', '.pyo$', '.obj$', '.o$', '.so$', '.egg$', '^.git$', '^.svn$', '^.hg$' ]
    " 只剩一个NERDTree窗口时退出vim
    autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") &&b:NERDTreeType == "primary") | q | endif
    " <F9>打开/关闭文件管理器
    nnoremap <silent> <F9> :NERDTreeToggle<CR>
    复制代码

The-NERD-Commenter

这个插件也是必备的,主要自动注释内容。当你 xml 自然是 xml 注释,当你是 java 自然就是 java 的注释规则。其样例如下图所示: nerdcommenter

  1. 在 Vim 中的安装和配置

    call vundle#begin('~/.vim/bundle/')
    " 快速添加/去除注释
    Plugin 'The-NERD-Commenter'
    call vundle#end()  
    
    """"""""""""""""""""""""""""""""""
    " The-NERD-Commenter配置
    """"""""""""""""""""""""""""""""""
    " 注释的时候自动加个空格, 强迫症必配
    let g:NERDSpaceDelims=1
    " mm智能判断加上/解开注释
    map mm <leader>c<space>
    复制代码

ctrlp

这是个文件查找的插件,其功能和 NERDTree 有点类似,但是还是有点区别吧。其样例如下图所示: nerdcommenter

  1. 在vim中的安装和配置

    call vundle#begin('~/.vim/bundle/')
    " 文件搜索
    Plugin 'kien/ctrlp.vim'
    call vundle#end()  
    
    """"""""""""""""""""""""""""""""""
    " ctrlp配置
    """"""""""""""""""""""""""""""""""
    " 设置CtrlP的本地工作目录,0代表不设置该功能
    let g:ctrlp_working_path_mode=0
    " ctrlp窗口在底部
    let g:ctrlp_match_window_bottom=1
    " ctrlp窗口最大高度为15行
    let g:ctrlp_max_height=15
    " 窗口
    let g:ctrlp_match_window_reversed=0
    " 最近打开的文件的个数
    let g:ctrlp_mruf_max=500
    " 记录但去掉重复的软链接
    let g:ctrlp_follow_symlinks=1
    " <Ctrl-f>启动文件查找
    let g:ctrlp_map = '<c-f>'
    " Ctrlp启动文件查找
    let g:ctrlp_cmd = 'CtrlP'
    " 相当于mru功能,show recently opened files
    map <c-p> :CtrlPMRU<CR>
    " 忽略以下文件类型
    set wildignore+=*/tmp/*,*.so,*.swp,*.zip
    " 忽略以下文件目录
    let g:ctrlp_custom_ignore = {'dir':  '/].(git|hg|svn|rvm)$','file': '(exe|so|dll|zip|tar|tar.gz)$'}
    复制代码

ctags

ctags 可以建立源码树的标签索引(标签就是一个标识符被定义的地方,如函数定义),使程序员在编程时能迅速定位函数、变量、宏定义等位置去查看原形。

  1. 安装 exuberant-ctags 工具

    sudo apt-get install exuberant-ctags
    复制代码
  2. 创建 C++ 代码库索引

    1. 下载 libstdc++ 头文件,包含 C++ 中 STL,streams 等。

    2. 解压到 ~/.vim/tags 目录后执行 ctags 命令

      ctags -R --c++-kinds=+p --fields=+iaS --extra=+q --language-force=C++ cpp_src
      mv tags ~/.vim/tags/cpptag
      复制代码
    3. 在.vimrc中设置

      set tags+=~/.vim/tags/cpptag
      复制代码
  3. 创建 Gcc 代码库索引

    1. ubuntu中安装完build-essential后,会在/usr/include/c++目录下有C/C++的头文件。

      sudo apt-get install build-essential
      复制代码
    2. 拷贝/usr/include/c++/4.8里的文件到~/.vim/tags/gcc文件夹里后执行ctags命令

      cp -R /usr/include/c++/4.8 ~/.vim/tags/gcc
      ctags -R --c++-kinds=+p --fields=+iaS --extra=+q gcc
      mv tags ~/.vim/tags/gcctag
      复制代码
    3. 在.vimrc中设置

      set tags+=~/.vim/tags/gcctag
      复制代码

cscope

Cscope,一个应用程序,程式员使用它来协助程式撰写及追踪程式码,主要使用于C语言程式。最早起源于贝尔实验室,运作在 PDP-11 上,由 Joe Steffen 开始发展。

  1. 安装 cscope 工具

    sudo apt-get install cscope
    复制代码
  2. 创建gnu c库索引

    1. 下载 glibc 文件,它是 GNU 发布的 libc 库,即 C 运行库。glibc 是 linux 系统中最底层的 api,几乎其它任何运行库都会依赖于 glibc。

    2. 解压到 ~/.vim/tags 目录后执行 cscope 命令

      cd ~/.vim/tags/glibc-2.22
              cscope -Rbq
      复制代码
    3. 在 .vimrc 中设置

      """"""""""""""""""""""""""""""""""
      " cscope配置
      """"""""""""""""""""""""""""""""""
      if has("cscope")
          " 设置cscope的命令位置
          set csprg=/usr/local/bin/cscope
          " 设定quickfix来显示cscope的结果
          set cscopequickfix=s-,c-,d-,i-,t-,e-
          " 先搜索tags标签文件,在搜索cscope数据库
          set csto=1
          " 使用cstag查询,也就是同时搜索cscope数据库和tags标签文件
          set cst
          " 不显示添加数据库是否成功
          set nocsverb
          "
          if filereadable("cscope.out")
          " 添加当前目录下的cscope数据库
          cs add cscope.out
          else
          " 添加vim自带的cscope数据库
          " gnu c 数据库
          cs add ~/.vim/tags/glibc-2.22/cscope.out ~/.vim/tags/glibc-2.22
          endif
          " 显示添加数据库成功
          set csverb
      endif
      
      " 映射快捷键"<C-_>g的按法是先按"Ctrl+Shift+-", 然后很快再按"g"
      " 查找本 C 符号(可以跳过注释)
      nmap <C-_>s :cs find s <C-R>=expand("<cword>")<CR><CR>
      "查找本定义
      nmap <C-_>g :cs find g <C-R>=expand("<cword>")<CR><CR>
      "查找调用本函数的函数
      nmap <C-_>c :cs find c <C-R>=expand("<cword>")<CR><CR>
      "查找本字符串
      nmap <C-_>t :cs find t <C-R>=expand("<cword>")<CR><CR>
      "查找本 egrep 模式
      nmap <C-_>e :cs find e <C-R>=expand("<cword>")<CR><CR>
      "查找本文件
      nmap <C-_>f :cs find f <C-R>=expand("<cfile>")<CR><CR>
      "查找包含本文件的文件
      nmap <C-_>i :cs find i ^<C-R>=expand("<cfile>")<CR>$<CR>
      "查找本函数调用的函数
      nmap <C-_>d :cs find d <C-R>=expand("<cword>")<CR><CR>
      复制代码

tagbar

tagbar 插件是和 taglist 功能类似的插件,但是它比 taglist 更优秀,并且能和 NERDTree 完美配合。

  1. tagbar的优势

    • 支持头文件的函数列表显示

    细心的读者可能会发现,tagbar对函数的可见级别也是做了区分的,分别用+ – # 并配合着色来做了区分

    • 对面向对象的支持更好

    taglist虽然也会列出类列表,但是整体还是很不直观

    • 自动根据文件修改时间来重建

    taglist在这一点上体验就很不好,其实明明可以通过这种时间戳的方式来实现

  2. 在vim中的安装和配置

    call vundle#begin('~/.vim/bundle/')
    " 替换taglist的插件[tagbar]
    Plugin 'majutsushi/tagbar'
    call vundle#end()  
    
    """"""""""""""""""""""""""""""""""
    " tagbar配置
    """"""""""""""""""""""""""""""""""
    " 启动时自动focus
    let g:tagbar_autofocus=1
    " <F10>打开/关闭Tagbar
    nnoremap <silent> <F10> :TagbarToggle<CR>
    复制代码

rainbow

这个插件也是必备的,该插件的主要功能是给配对的(){}[]不同的颜色来区别,非常方便看括号的作用域

  1. 在 Vim 中的安装和配置

    call vundle#begin('~/.vim/bundle/')
    " 括号显示增强
    Plugin 'luochen1990/rainbow'
    call vundle#end()  
    
    """"""""""""""""""""""""""""""""""
    " rainbow配置
    """"""""""""""""""""""""""""""""""
    " rainbow激活
    let g:rainbow_active = 1
    复制代码
  2. 给 rainbow 添加自动启动功能

    if (exists('g:rainbow_active') && g:rainbow_active)
        auto syntax * call rainbow#hook()
        auto colorscheme * call rainbow#show()
        " 下面这命令使rainbow在vim启动时被打开
        autocmd VimEnter * nested call rainbow#toggle()
    endif
    复制代码

syntastic

这是一个非常有用的插件,它能够实时的进行语法和编码风格的检查,利用它几乎可以做到编码完成后无编译错误。并且它还集成了静态检查工具:lint,可以让你的代码更加完美。更强大的它支持近百种编程语言,像是一个集大成的实时编译器。出现错误之后,可以非常方便的跳转到出错处。其样例如下图所示: nerdcommenter

  1. 在vim中的安装和配置

    call vundle#begin('~/.vim/bundle/')
    " 语义高亮
    Plugin 'scrooloose/syntastic'
    call vundle#end()  
    
    """"""""""""""""""""""""""""""""""
    " syntastic配置
    """"""""""""""""""""""""""""""""""
    " 首次打开和保存时都要进行语义检查
    let g:syntastic_check_on_open = 1  
    " 设置错误提示符'x'
    let g:syntastic_error_symbol = 'x'  
    " 设置警告提示符'!'
    let g:syntastic_warning_symbol = '!'  
    " 当鼠标放在错误行则显示错误信息
    let g:syntastic_enable_balloons = 1  
    " 保存退出时不用进行语义检测
    let g:syntastic_check_on_wq = 0
    " 编译有误则错误窗口显示,否在不显示
    let g:syntastic_auto_loc_list = 1
    " 错误总会填充到错误窗口
    let g:syntastic_always_populate_loc_list = 1
    复制代码

YouCompleteMe

YouCompleteMe 对代码的补全完全达到了编译器级别,绝不弱于 Visual Assist。它是基于 LLVM/clang,一个 Apple 公司为了代替 GNU/GCC 而支持的编译器,正因为 YouCompleteMe 有了编译器的支持,而不再像以往的插件一样基于文本来进行匹配,所以准确率才如此之高。而且,它是C/S架构,会在本机创建一个服务器端,利用 clang 来解析代码,然后将结果返回给客户端,所以也就解决了 VIM 是单线程而造成的各种补全插件速度奇慢的诟病,在使用时,几乎感觉不到任何的延时,体验达到了 Visual Assist 的级别。
YouCompleteMe 除了补全以外,还有一个非常重要的作用:代码跳转,同样可以达到编译器级别的准确度,媲美 Visual Assist 与 Source Insight 。其样例如下图所示: nerdcommenter

  1. 安装必备软件

    sudo apt-get install clang llvm cmake python python-dev
    复制代码
  2. 手动编译

    cd ~/.vim/bundle/YouCompleteMe
    ./install.sh --clang-completer
    复制代码
  3. 在vim中的安装和配置

    call vundle#begin('~/.vim/bundle/')
    " 自动补全
    Plugin 'Valloric/YouCompleteMe'
    call vundle#end()  
    
    """"""""""""""""""""""""""""""""""
    " YouCompleteMe配置
    """"""""""""""""""""""""""""""""""
    " 设置YCM配置文件的路径
    let g:ycm_global_ycm_extra_conf='~/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/.ycm_extra_conf.py'
    " 开启关键字语法检测
    let g:ycm_seed_identifiers_with_syntax = 1
    " 自动触发补全
    let g:ycm_auto_trigger = 1
    " YCM触发的条件
    let g:ycm_semantic_triggers = {  
    \ 'c' : ['->' , '.'],
    \ 'cpp,objcpp' : ['->','.','::'],
    \ 'java,javascript,python,scala' : ['.'],
    \ 'ruby' : ['.','::'],
    \}
    " 不用每次询问.ycm_extra_conf.py位置
    let g:ycm_confirm_extra_conf=0
    " YCM也从tags文件中收集标识符
    let g:ycm_collect_identifiers_from_tags_files=1
    " 当输入注释的时候不用弹出提示
    let g:ycm_complete_in_comments=0
    " 当输入字符的时候弹出提示
    let g:ycm_complete_in_strings=1
    复制代码

TIps:Tab无效
如果出现安装 YouCompleteMe 后,虽然看到 YouCompleteMe 的提示框,但是无法使用 < Tab > 进行自动补全,只能使用上下方向键+回车来选择时,就要检查一下 .vimrc 是否打开了粘贴模式,即设置了set paste.该模式会屏蔽所有映射和缩写.(对于 ultisnips 也有同样的问题)

ultisnips

这个插件也是必备的,该插件的主要功能是用来快速输入固定的代码块,像文件开头的版权声明,#ifndef... #def... #endif这样宏定义,markdown 写 jekyll 博文的 head 信息.最关键的是可以按照自己的习惯自定义代码块,这样就不用按照 IDE 的习惯培养自己了.其动态效果如下所示: ultisnippets

  1. 在vim中的安装和配置

    call vundle#begin('~/.vim/bundle/')
    " ultisnips
    Plugin 'SirVer/ultisnips'
    " Snippets are separated from the engine
    Plugin 'honza/vim-snippets'
    call vundle#end()  
    
    """"""""""""""""""""""""""""""""""
    " ultisnips配置
    """"""""""""""""""""""""""""""""""
    " 如果使用了Valloric/YouCompleteMe,就别设置为<tab>
    let g:UltiSnipsExpandTrigger="<c-j>"
    " 前选片段
    let g:UltiSnipsJumpForwardTrigger="<C-f>"
    " 后选片段
    let g:UltiSnipsJumpBackwardTrigger="<C-b>"
    " 使用:UltiSnipsEdit打开片段定义文件时分屏位置
    let g:UltiSnipsEditSplit="vertical"
    复制代码
  2. 自定义代码块

我们注意到安装 ultisnips 过程中,除了安装自身以外,还安装了 honza 的 vim-snippets,而它的一大作用是提供了大量(目前是80个)的程序片段,像 c,python,markdown,make,sh,sql 等。而这些 snippets 都在 .vim/bundle/vim-snippets/snippets 文件夹中。除此之外,我们还可以自定义自己的代码块,建议是放在 .vim/UltiSnippets 目录下(和 bundle 同等级),一方面是 .vim/bundle/vim-snippets/snippets 下的代码块是别人的 git 项目。另一方面 .vim/UltiSnippets 下的文件可以覆盖 vim-snippets 里的配置,这样更符合 DIY 的目的。关于如何编写 snippets,网上找到的资源不多,给出如下建议: * 查看 .vim/bundle/vim-snippets/snippets 里的代码 * 通过 :help snippets 查看 ultisnips 的帮助文档 * 博文自定义自己的代码块中的样列

    ```sh
    ## head Jekyll写博文时插入的头文件信息
    snippet head "Jekyll post header" b # b代表begin(snippet should be expanded only at the beginning of a line )
    ---
    layout:       default
    title:        ${1:blog_name}
    category:     [${2:cate1,cate2}]
    comments:     true
    date:         `!v strftime("%Y-%m-%d %H:%M:%S")`
    ---
    ${0}        # 代表tab最终停留的位置

    endsnippet
    ```
复制代码

tabular

这是一个处女座或码农必备的插件,因为当你看到代码/文字杂乱的排版--等号,冒号,表格等不能对齐时,应该会抓狂吧。而 tabular 这个插件能完美的解决这个问题。就像下面的图例一样,只需要输入命令 :Tabularize /* (*代表对齐的符号)即可:
tabular

  1. 在 Vim 中的安装和配置

    call vundle#begin('~/.vim/bundle/')
    " tab对齐
    Plugin 'godlygeek/tabular'
    call vundle#end()  
    
    """"""""""""""""""""""""""""""""""
    " tabular配置
    """"""""""""""""""""""""""""""""""
    " 目前还尚在摸索中
    复制代码

vim-markdown

vim-markdown 是一款用来对原生 markdown 和扩展 markdown 语法进行语义高亮和规则匹配的插件。

  1. 在 vim 中的安装和配置

    call vundle#begin('~/.vim/bundle/')
    " markdown语义高亮
    Plugin 'plasticboy/vim-markdown'
    call vundle#end()
    
    """"""""""""""""""""""""""""""""""
    " tabular配置
    """"""""""""""""""""""""""""""""""
    " vim识别md
    autocmd BufNewFile,BufReadPost *.md set filetype=markdown
    let g:vimmarkdownfoldingdisabled=1 "取消代码折叠
    let g:vimmarkdownnodefaultkeymappings=1 "取消默认的键对应
    let g:vimmarkdownmath=1 "使用数学符号
    let g:vimmarkdownfrontmatter=1 "高亮YMAL frontmatter
    复制代码

[markdown同步预览][markdown-preview]

markdown-preview 是一款用来将 vim 打开的 markdown 文件翻译为 html 显示在浏览器里的插件,该插件的亮点在于实时更新。

  1. 在 Vim 中的安装和配置

    call vundle#begin('~/.vim/bundle/')
    " markdown同步显示
    Plugin 'iamcco/mathjax-support-for-mkdp'
    Plugin 'iamcco/markdown-preview.vim'
    call vundle#end()
    
    """"""""""""""""""""""""""""""""""
    " markdown-preview.vim配置
    """"""""""""""""""""""""""""""""""
    " 设置启动chrome浏览器的命令
    let g:mkdp_path_to_chrome = "open -a Google\\ Chrome"
    " 设置为1则打开markdown文件时自动打开浏览器
    let g:mkdp_auto_start = 1
    " 设置为1则在编辑markdown的时候预览窗口是否打开,未开则自动打开
    let g:mkdp_auto_open = 1
    " 切换buffer时自动关闭预览窗口,设置为0则在切换buffer时不自动关闭
    let g:mkdp_auto_close = 1
    " 设置为1则只有在保存文件或退出插入模式时更新预览,默认为0,实时更新预览
    let g:mkdp_refresh_slow = 0
    " 设置为1则所有文件都使用MarkdownPreview进行预览,默认只有markdown文件可以
    let g:mkdp_command_for_global = 0
    复制代码

emmet-vim

Emmet 的前身就叫做 Zen Coding,它是个前端插件。官方支持很多软件,像 Sublime Text、Notepad++、Dreamweaver、Eclipse、Adobe Brackets 等,而 Emmet.vim 并非 Emmet 亲生,而是由日本 Yasuhiro Matsumoto 开发。对于前端开发者而言它是一件神器,能够节省大量的重复 coding 劳动。鉴于前端开发的少,这里只是 mark 一下。

参考文献

  1. 有趣的vim游戏
  2. Vim学习指南
  3. vim plugin
  4. Vim Script
  5. Vim配置及说明——IDE编程环境
  6. 高效vim插件
  7. VIM助记图
  8. Vimer的程序世界
  9. vimium
  10. youcompleteme
  11. syntastic
  12. python IDE
  13. ultisnips
  14. 自定义自己的代码块
  15. 前端开发神器Emmet
  16. Emmet教程
  17. 对齐神器-tabular
  18. vim-markdown

如果该文章对您产生了帮助,或者您对技术文章感兴趣,可以关注微信公众号: 技术茶话会, 能够第一时间收到相关的技术文章,谢谢!

技术茶话会

本篇文章由一文多发平台ArtiPub自动发布

文章分类
后端
文章标签