VIM 插件使用

2015-07-04 Saturday    


Vim 是一个功能强大、高度可定制的文本编辑器,在 Vi 的基础上改进和增加了很多特性。与其相匹敌的是 Emacs ,这两个都是不错的编辑器,在此不再比较两者的优劣,仅介绍 Vim 相关的内容。

vim logo

简介

常用的插件列表可以参考。

插件管理
  1. Vundle           --- the plug-in manager for Vim
  2. Vim-Plug         +++ Minimalist Vim Plugin Manager

语法检查
  1. ALE              +++ syntax checking and semantic errors

自动格式化
  1. vim-autoformat   +++ code formatting

自动补全
  1. YouCompleteMe    +++ visual assist for vim
  2. Deoplete         --- asynchronous completion framework
  3. UltiSnips        +++ ultimate snippets
  4. Emmet            --- hi-speed coding for html/css

导航与搜索
  1. CtrlP            --- fast file finder
  2. LeaderF          +++ asynchronous fuzzy finder
  2. NERDTree         +++ file navigation
  3. Tagbar           +++ tag generation and navigation
  4. Taglist          --- source code browser

其它
  1. Tabularize       +++ align everything
  2. vim-airline      +++ lean & mean status/tabline for vim that's light as air
  3. NERDCommenter    +++ comment++

  2. Easymotion       - jump anywhere
  4. Surround         - managing all the "'[{}]'" etc
  5. Gundo            - time machine
  6. Sessionman       - session manager
  7. Powerline        --- ultimate statusline utility

其中 taglist 和 tagbar 类似,不过其关注点有所区别,后者比较适合面向对象。

通常可以使用 vundle 管理所有的插件,通常插件为了防止多次加载,会在开始的时候检测是否已经加载。

一些经典的配置可以参考 vim.spf13.com,该 vim 配置,在 github 中有 1W+ 的 Star,可以通过如下方式进行配置:

----- 直接下载安装,实际上就是github中的bootstrap.sh脚本
$ curl https://j.mp/spf13-vim3 -L -o - | sh

可以通过 scriptnames 命令查看已经加载的插件列表。

插件管理

比较经典的是 Vundle ,也可以使用 Vim-Plug 。

Vundle

vim 缺少默认的插件管理器,所有插件的文件都散布在 ~/.vim 下的几个文件夹中,无论是配置、更新、删除,都需要手动配置,很容易出错。

vundle 把 git 操作整合进去,用户需要做的只是去 Github 上找到自己想要的插件的名字,安装,更新和卸载都可有 vundle 来完成了,可以查看 github,可以通过如下方式安装。

$ git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle

vim-scripts 在配置时,可以直接打仓库名,相关的插件可以从 官网 查看,或查看 Github,此时可以直接使用 Bundle 'L9' 。在配置文件中,主要是配置安装哪些插件,Vundle 支持如下的格式:

Bundle 'gmarik/vundle'          " 使用Vundle来管理Vundle,这个必须要有
Bundle 'tpope/vim-fugitive'     " Github上其他用户的仓库,非vim-scripts账户里的仓库
Bundle 'file:///path/to/plugin' " 使用自己的插件
Bundle 'git://vim-latex.git.sourceforge.net/gitroot/vim-latex/vim-latex'

自己写的插件也可以通过如上方式管理,如自己写了一个 test 插件,并放到了 .vim/myplugin 目录中,那么可以在 vim 的配置文件中加入下面的命令 set rtp+=~/.vim/myplugin/

Vundle 常用的命令如下。

BundleList             列出所有已配置的插件
BundleInstall(!)       下载(更新)插件
BundleUpdate           更新插件
BundleClean            清除不再使用的插件
BundleSearch(!) foo    查找(先刷新cache)foo

对于 Vundle 插件,如果使用 call vundle#begin() 时发现很多插件无法使用,可以使用 call vundle#rc() ,暂时不确认为什么。

Vim-Plug

相比来说,所有的插件更新和安装都是并行的,比 Vundle 的效率要高很多,而且可以按需加载。

直接从 Github vim-plug 下载,然后将 plug.vim 文件保存在 ~/.vim/autoload/plug.vim 中即可,如下是添加 Nerdtree 。

call plug#begin('~/.vim/plugged')
Plug 'scrooloose/nerdtree'
call plug#end()

如下是常见的命令。

PlugStatus             查看插件状态
PlugInstall            安装插件
PlugUpdate             更新插件
PlugClean              删除插件
PlugUpgrade            升级vim-plug自己

语法检查

常用的插件如 Syntastic ,随着 VIM8 开始支持异步,可以选择使用 neomake (最早支持异步)、ALE 等,这里使用 ALE 。

ALE

Asynchronous Lint Engine 一个异步的检查引擎,相比来说更加快速,不会感到明显的卡顿。

实际上是一个 Language Server Protocol 客户端,对应的 linter 都需要自己安装,不过大部分 (例如 gcc、gofmt 等) 都已经存在了,其它一些需要进行安装。

Plug 'dense-analysis/ale'

如果通过 g:ale_linters 设置了 linters 之后,例如 'c':['gcc'] ,而实际上,如果存在 clang 编译工具,那么仍然会使用,如果要严格按照这里的配置,需要增加 let g:ale_linters_explicit = 1 配置项。

Syntastic

一个语法检查工具,支持多种语言,提供了基本的补全功能、自动提示错误的功能外,还提供了 tags 的功能;采用 C/S 模式,当 vim 关闭时,ycmd 会自动关闭。

不过对于不同的语言需要安装相应的插件,详细内容可以查看 doc/syntastic-checkers.txt,安装方法可以参考 README.md 文件。

vim Syntastic

能够实时的进行语法和编码风格的检查,还集成了静态检查工具,支持近百种编程语言,像是一个集大成的实时编译器,出现错误之后,可以非常方便的跳转到出错处。

自动格式化

vim-autoformat

一个自动格式代码工具,这只是一个框架,需要相关的工具支持,例如 astyle、clang-format、python3-pep8 等等。

自动补全

YouCompleteMe 和 Deoplete 都支持异步的补全,前者相比来说速度更快,所以,对于像 C/C++ 建议使用前者。

UltiSnips

一个牛摆的引擎,在写代码时经常需要在文件开头加一个版权声明之类的注释,又或者在头文件中要需要 #ifndef... #def... #endif 这样的宏,亦或写一个 for switch 等很固定的代码片段。

该工具和 YouCompleteMe 以及 neocomplete 都很好的整合在一起了。

不过 UltiSnips 只是个引擎,需要搭配预设的代码块才能运转起来,很多模版可以参考 honza/vim-snippets,不过建议自己再维护一套。

YouCompleteMe

当通过 Plugin 'Valloric/YouCompleteMe' 安装 YCM 后,经常会出现 no module named future 的报错,可以通过如下方式进行安装。

----- 可以通过Vundle安装,或使用如下方式下载,后者用于下载相关的依赖
$ git clone --recursive https://github.com/Valloric/YouCompleteMe.git ~/.vim/bundle/YouCompleteMe
$ git submodule update --init --recursive

----- 通过该脚本安装,支持C、Go,如果要支持所有语言通过--all安装
$ ./install.py --clang-completer --gocode-completer

在安装时,可以通过 --system-clang 指定使用系统的 Clang 。

另外,UltiSnips 与 YCM 有按键冲突,很多都建议将 UltiSnips 的自动填充快捷键更换,不过仍无效,可以通过如下方式修改,此时 <C-N><C-P> 仍然有效。

let g:ycm_key_list_select_completion=[]
let g:ycm_key_list_previous_completion=[]

常用命令。

:YcmDiags          通过location-list显示诊断信息

配置文件

也就是 ~/.vim/ycm_extra_conf.py 配置文件,在 flags 中添加编译时的参数定义,例如 -Wall-Wextra 等,然后通过 -isystem 指定系统的头文件,通过 -I 指定自定义的头文件。

注意,在使用相对路径时是 YCM 的安装路径。

YCM错误日志及调试信息

在 vim 配置文件中加上下面的选项,打开调试信息。

let g:ycm_server_keep_logfiles = 1
let g:ycm_server_log_level = 'debug'

几个常用命令:

:YcmToggleLogs   查看到错误日志及调试信息,输出到哪些文件中
:YcmDebugInfo    可以查看ycm相关的信息,包括编译标志,版本等等
:YcmDiags        查看当前文件中的错误信息

然后调试时就可以通过 print 打印,然后输出到 stdout 指定的文件中。

常见问题

对于 Your C++ compiler does NOT support C++11 错误,是由于要求最低 gcc 4.9 版本,该功能会在 third_party/ycmd/cpp/CMakeLists.txt 文件中进行检查,也就是 set( CPP11_AVAILABLE false ) 定义。

deoplete

通过标准的协议进行通讯,对于不同的语言需要不同的后端支持,可以参考 Completion Sources

emmet

原名为 Zen Coding ,后来改成了 Emmet 。

最简单的,新建一个文件,输入 html:5,然后按下组合键 Ctrl-y , ,既可以完成扩展,其基本的语法就是,输入简写模式,然后按下上述的快捷键,其中常见简写模式有:

  • E>N 代表N是E的子元素,例如 ul>li
  • E+N 代表N是E的同级元素,例如 div+

详细可以参考中文文档 Emmet.vim 教程

导航与搜索

包括了文件、代码的导航。

CtrlP

vim CtrlP

一个强大的搜索插件,可以模糊查询定位,包括了工程下的所有文件、打开的 Buffer、Buffer 内的 tag、最近访问的文件等,极大了方便了大规模工程代码的浏览。

LeaderF

相比 CtrlP 来说,其速度更快、匹配更准确,支持函数列表、文件、MRU、Buffer 等,然后通过配置文件定义如下快捷键:

  • CTRL-P 当前项目目录打开文件搜索;
  • CTRL-N 打开MRU搜索,搜索你最近打开的文件;
  • <leader>-F 查找函数;
  • <leader>-T 所有的Tag信息。

NERDTree

NERDTree 的作用就是列出当前路径的目录树,类似与一般 IDE,可以方便的浏览项目的总体的目录结构和创建删除重命名文件或文件名。

另外还有一个 NERDTreeTabs 插件,可以以 tab 形式显示窗口,用于方便浏览目录以及文件。

map <F2> :NERDTreeToggle<CR>          " 使用F2键快速调出和隐藏它
autocmd vimenter * NERDTree           " 打开vim时自动打开NERDTree

如下是一些常用的命令:

t   以Tab形式打开文件
i   分割成上下两个窗口显示文件
s   分割成左右两个窗口显示文件

C   将该目录设置为根目录
P   把有表移动到该目录的根目录
K   把有表移动到该目录的第一个
J   把有表移动到该目录的最后一个

p   切换到目录的下一层
u   切换到目录的上一层

m   通过NERDTree的选择菜单进行操作
I   是否显示隐藏文件切换
q   关闭NERDTree窗口
?   打开/关闭帮助指令

另外,比较好用的是提供的标签操作。

Tagbar

Tagbar 依赖于 ctags 命令,对于 CentOS 来说可以直接通过 yum install ctags 来安装。源码可以从 github tagbar 中查看,帮助文档可以查看 doc/tagbar.txt

常见问题

E257: cstag: tag not found

也就是说无法找到 tags 文件,此时需要通过如下参数进行设置,指定 tags 的查找路径。

----- 指定多个路径
set tags+=./tags,tags
set tags+=$HOME/.vim/systags

----- 或者允许自动切换路径,并使用当前目录下的文件
set tags=tags
set autochdir

杂项

注释

可以对代码快速注释,详细的配置可以参考 NerdCommenter 中的介绍,常用快捷键如下。

<leader>ca          在可选的注释方式之间切换,比如C的块注释/* */和行注释//

<leader>cc          加注释
<leader>cu          解开注释
<leader>c<space>    加上/解开注释, 智能判断

<leader>cs          对齐块方式,所谓的Sexy模式

Tabular

一个不错的对齐用的插件,可以从 tabular 下载,然后通过如下的方式安装,详细的资料可以参考 aligning text with tabular vim

$ git clone https://github.com/godlygeek/tabular.git
$ cd tabular/
$ mv after autoload doc plugin ~/.vim/

首先,通过 V v Ctrl-v 选取需要对其的内容,然后直接输入如下的命令即可。注意,在 Visual 模式中输入 : 后,会显示 :'<,'> 直接输入命令即可。

:Tabularize /=           使用=进行分割
:Tabularize /:\zs        ':'符号不动,只对其':'后面的字符

其中 Tabularize 可以简写为 Tab ;另外,tabular 可以自动识别,尤其是含有 {}()[] 的,因此可以不选择字符,也就是在某行中直接输入 :Tabularize /| 即可。

可以通过如下的示例进行测试。

|start|eat|left|
|12|5|7|
|20|5|15|

var video = {
    metadata: {
        title: "Aligning assignments"
        h264Src: "/media/alignment.mov",
        oggSrc: "/media/alignment.ogv"
        posterSrc: "/media/alignment.png"
        duration: 320,
    }
}

对于第二部分,执行 vi} 选择区域,执行 :Tab /: ,执行 :Tab /:\zs 则会使 : 不变。

$ vim ~/.vimrc                              # 在最后添加如下的内容
let mapleader=','
if exists(":Tabularize")
  nmap <Leader>a= :Tabularize /=<CR>
  vmap <Leader>a= :Tabularize /=<CR>
  nmap <Leader>a: :Tabularize /:\zs<CR>
  vmap <Leader>a: :Tabularize /:\zs<CR>
endif

inoremap <silent> <Bar>   <Bar><Esc>:call <SID>align()<CR>a
function! s:align()
  let p = '^\s*|\s.*\s|\s*$'
  if exists(':Tabularize')&&getline('.') =~# '^\s*|'&&(getline(line('.')-1) =~# p || getline(line('.')+1) =~# p)
    let column = strlen(substitute(getline('.')[0:col('.')],'[^|]','','g'))
    let position = strlen(matchstr(getline('.')[0:col('.')],'.*|\s*\zs.*'))
    Tabularize/|/l1
    normal! 0
    call search(repeat('[^|]*|',column).'\s\{-\}'.repeat('.',position),'ce',line('.'))
  endif
endfunction

上述前一部分表示绑定的快捷键;后一部分表示在输入时会自动检测,并设置格式。

Vim-Airline

主题在目录 autoload/Powerline/Themes 下,配色在 autoload/Powerline/Colorschemesvim-airlinevim-powerline 类似但是更小,更轻便。

推荐使用后者,可以参考 vim-airline,其中主题 themes 已经单独拆出来了。

NERDCommenter

用于快速,批量注释与反注释,适用于任何你能想到的语言,会根据不同的语言选择不同的注释方式,方便快捷。

Surround

一个专门用来处理这种配对符号的插件,它可以非常高效快速的修改、删除及增加一个配对符号,对于前端工程师非常有用。

通常可以和 repeat.vim 配合使用,如下是常见的操作示例。

Old text                  Command     New text ~
 "Hello *world!"           ds"         Hello world!
 [123+4*56]/2              cs])        (123+456)/2
 "Look ma, I'm *HTML!"     cs"<q>      <q>Look ma, I'm HTML!</q>
 if *x>3 {                 ysW(        if ( x>3 ) {
 my $str = *whee!;         vlllls'     my $str = 'whee!';
 <div>Yo!*</div>           dst         Yo!
 <div>Yo!*</div>           cst<p>      <p>Yo!</p>

如下是一个命令列表。

 Normal mode
 ds  - delete a surrounding
 cs  - change a surrounding
 ys  - add a surrounding
 yS  - add a surrounding and place the surrounded text on a new line + indent it
 yss - add a surrounding to the whole line
 ySs - add a surrounding to the whole line, place it on a new line + indent it
 ySS - same as ySs

 Visual mode
 s   - in visual mode, add a surrounding
 S   - in visual mode, add a surrounding but place text on new line + indent it

 Insert mode
 <CTRL-s> - in insert mode, add a surrounding
 <CTRL-s><CTRL-s> - in insert mode, add a new line + surrounding + indent
 <CTRL-g>s - same as <CTRL-s>
 <CTRL-g>S - same as <CTRL-s><CTRL-s>

cscope

:help if_cscop
:cscope show       查看已经加载的数据库
:cscope add        添加数据库
:cscope kill       关闭已加载的数据库
:cscope reset      重新初始化所有连接

可以将 cscope 看做是 ctags 的升级版本,提供交互式查询语言符号功能,如查询哪些地方使用某个变量或调用某个函数。

和 tags 一样,默认支持,可以通过 :version 查看,没有则增加 --enable-cscope 编译选项,详细可查看官方网址为 cscope.sourceforge.net

确定 Vim 已支持 Cscope 后,将文件 cscope_maps.vim 下载到 ~/.vim/plugin 目录下;也可以将其内容添加到 ~/.vimrc 配置文件中。

在 CentOS 中,可以通过 yum install cscope 安装,在第一次解析时扫描全部文件,以后再调用 cscope 只会扫描那些改动过的文件。

进入项目代码根目录运行命令生成 cscope 数据库文件:

cscope -Rbq -f cscope.out

常用参数:
  -R     表示递归操作,无该参数则进入基于cureses的GUI界面,通过方向键选择查找类
           型、TAB键搜索结果和搜索类型中选择、Ctrl-D退出;
  -b     生成数据库文件后直接退出,否则生成数据库之后会进入 cscope 界面;
  -q     表示生成 cscope.in.out 和 cscope.po.out 文件,加快 cscope 的索引速度;
  -C     在搜索时忽略大小写;
  -Ppath 默认是相对路径,可以在相对路径的文件前加上path。
  -Idir  在指定的目录中查找头文件;

默认只解析 C、lex 和 yacc 文件,如果希望解析 C++ 和 Java 文件,可以通过指定 cscope.files 文件,此时不再需要 -R 选项。

查看Linux Kernel

对于内核中感兴趣的文件通常需要去除文本、非x86源码、非驱动。

$ tar -Jxf linux-kernel.tar.xz
$ LNX=/home/andy/linux-kernel
$ find  $LNX                                                              \
    -path "$LNX/arch/*" ! -path "$LNX/arch/i386*" -prune -o               \
    -path "$LNX/include/asm-*" ! -path "$LNX/include/asm-i386*" -prune -o \
    -path "$LNX/tmp*" -prune -o                                           \
    -path "$LNX/Documentation*" -prune -o                                 \
    -path "$LNX/scripts*" -prune -o                                       \
    -path "$LNX/drivers*" -prune -o                                       \
    -name "*.[chxsS]" -print >/home/andy/cscope/cscope.files
$ cd /home/andy/cscope
$ cscope -b -q -k                             生成Cscope数据库文件
$ add some files and 'cscope -b -q -k'        添加新文件重新生成数据库

在 find 命令中 -o 表示 or-prune 表示不包含该目录,如果前面又添加了 ! 号,则表示只包含该目录。

常用快捷键

F2    替换末尾的空格
F3    Tagbar(左侧)
F4    Nerdtree(右侧)

其它插件

简单介绍一些常见的插件。

xterm-color-table

查看颜色列表,可从 color-table 下载,下载解压后可以放置到 $VIMRUNTIME/colors 目录下,通过 :XtermColorTable 命令即可查看。

其它可以查看 doc 目录下的帮助文件,也可以查看如下的图片 xterm color

number.vim

更好的显示行号,在 Normal 状态时会在主窗口中显示绝对/相对行号,插入状态时显示绝对行号,不需要进行任何配置。

let g:numbers_exclude = ['tagbar', 'gundo', 'minibufexpl', 'nerdtree']
nnoremap <F3> :NumbersToggle<CR>
nnoremap <F4> :NumbersOnOff<CR>

vim-startify

一个启动界面替换默认的 vim 启动界面,会显示一些最近打开的文件等信息。

fencview

对于 vim 打开文件时如何自动识别,可以使用如下设置:

set fileencodings=utf-8,gb2312,ucs-bom,euc-cn,euc-tw,gb18030,gbk,cp936

或者通过 fencview 插件,该插件主要用于自动识别汉字、日文等,主要有如下的命令。

:FencAutoDetect                  " 自动识别文件编码
:FencView                        " 打开一个编码列表窗口,用户选择编码reload文件

可以在 vimrc 中设置如下选项:

let g:fencview_autodetect = 1    " 打开文件时自动识别编码
let g:fencview_checklines = 10   " 检查前后10行来判断编码,或者'*'检查全文

可以将 autodetect 设置为 0,当发现为乱码时,那么可以使用 :FencAutoDetect 命令查看,然后通过 :set fileencoding 查看当前编码,并将其编码放置到 fileencodings 中。

可以参考 VIM 文件编码识别与乱码处理

其它

还有一些小众的常用。



如果喜欢这里的文章,而且又不差钱的话,欢迎打赏个早餐 ^_^