启用 Vim 的特性

Vim编辑器相关的所有功能开关都可以通过.vimrc文件进行设置,.vimrc配置文件分系统配置和用户配置两种。

系统vimrc配置文件存放在Vim的安装目录,默认路径为/usr/share/vim/.vimrc。可以使用命令echo $VIM来确定Vim的安装目录。用户vimrc文件,存放在用户主目录下~/.vimrc,可以使用命令echo $HOME确定用户主目录。

1
$ vim ~/.vimrc

基础设置

双引号内的中文均为注释,其他视情况而定。

设置中文不乱码

与Vim编码有关的变量包括:encodingfileencodingtermencoding

encoding选项用于缓存的文本、寄存器、Vim 脚本文件等;fileencoding选项是Vim写入文件时采用的编码类型;termencoding选项表示输出到终端时采用的编码类型。

1
2
3
4
"设置编码
set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936
set termencoding=utf-8
set encoding=utf-8

显示行号

nu是number的缩写,两个配置命令是完全等效的

1
2
set nu
set number

突出显示当前行

1
set cursorline

启用鼠标

Vim编辑器里默认是不启用鼠标的,也就是说不管你鼠标点击哪个位置,光标都不会移动。通过以上设置就可以启动鼠标,不过对于高级玩家来说,用Vim就是为了解放双方不用鼠标,所以这个设置可以根据个人爱好选择.

1
2
3
set mouse=a
set selection=exclusive
set selectmode=mouse,key

设置缩进

1
2
3
4
5
6
"设置Tab长度为4空格
set tabstop=4
"设置自动缩进长度为4空格
set shiftwidth=4
"继承前一行的缩进方式,适用于多行注释
set autoindent

粘贴格式

显示空格和tab键在Vim中通过鼠标右键粘贴时会在行首多出许多缩进和空格,通过set paste可以在插入模式下粘贴内容时不会有任何格式变形、胡乱缩进等问题。Vim编辑器中默认不显示文件中的tab和空格符,通过上面的配置可以获得以下的显示效果,方便定位输入错误

1
2
set paste
set listchars=tab:>-,trail:-

显示状态栏和光标当前位置

1
2
3
4
"总是显示状态栏
set laststatus=2
"显示光标当前位置
set ruler

Vim配置变更立即生效

要让.vimrc变更内容生效,一般的做法是先保存.vimrc再重启vim,增加以下设置,可以实现保存 .vimrc 时自动重启加载

1
autocmd BufWritePost $MYVIMRC source $MYVIMRC

语法高亮

Vim 自带语法高亮显示功能,只需要打开 syntax 选项即可, 依赖于 Vim 的文件类型检测功能.

1
2
3
4
"打开文件类型检测
filetype on
"打开语法高亮显示
syntax on

插件功能

代码自动补齐

虽然 Vim自带自动补齐功能,但是这种自带的补齐功能其本质就是 猜:通过对文本进行正则表达式匹配,再根据字典文件和生成的tags文件实现自动补全的效果, 因此其功能相对也较为简单。

YouCompleteMe 简称 YCM,是一款 Vim 下非常流行的自动代码补齐神器。YouCompleteMe 基于 clang/llvm 等开源语法分析库进行构建,并整合了多种自动补齐引擎:an identifier-based engine that works with every programming language、a Clang-based engine that provides native semantic code completion for C/C++/Objective-C/Objective-C++/CUDA、a clangd-based experimental completion engine for the C-family languages、a Jedi-based completion engine for Python 2 and 3、an OmniSharp-based completion engine for C#、a combination of Gocode and Godef semantic engines for Go、an omnifunc-based completer that uses data from Vim’s omnicomplete system to provide semantic completions for many other languages (Ruby, PHP etc.)。由此可见,YouCompleteMe 几乎对现在所有流行的编程语言都提供了非常强大的补齐功能。

编译 YouCompleteMe 插件时需要依赖 cmake 构建 Makefile,且依赖 Python 源码头文件

安装Python依赖

1
$ sudo apt-get install build-essential cmake python-dev python3-dev

安装Clang

clang 是一个面向 C 族语言(C-family languages)的轻量级编译器,YouCompleteMe 插件依赖 clang 实现对 C 族语言的语义补全

1
$ sudo apt-get install clang

Clone

可以使用 Vundle 或 vim-plug 等 Vim 插件管理器从 github 获取 YouCompleteMe 最新的源码,这里推荐使用 Vundle。也可以直接使用

1
git clone https://github.com/Valloric/YouCompleteMe.git ~/.vim/plugged/

获取依赖

在源码目录执行:

1
git submodule update --init --recursive

编译安装

在源码目录执行:

1
$ python3 install.py --clang-completer

--clang-completer 参数是编译C族语言的补全,如果需要全部语言,换成--all 参数即可

安装Vundle插件管理器

Vundle插件是提供一个Vundle.vim文件,其下载地址为:https://github.com/VundleVim/Vundle.vim.git
将下载的Vundle.vim文件夹(之后的所有插件相同)保存到~/.vim/bundle然后修改配置文件即可完成Vundle的安装

配置Vundle

修改.vimrc 文件,添加下列配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"去除VIM一致性
set nocompatible
filetype off
"设置包括vundle和初始化相关的运行时路径
set rtp+=~/.vim/bundle/Vundle.vim

call vundle#begin()
"启用vundle管理插件
Plugin 'VundleVim/Vundle.vim'
"在此增加其他插件,安装的插件需要放在vundle#begin和vundle#end之间
"安装github上的插件格式为 Plugin '用户名/插件仓库名'
call vundle#end()

"加载vim自带和插件相应的语法和文件类型相关脚本
filetype plugin indent on

更多Vundle有关配置可以参考官方文档

使用Vundle安装插件

首先需要将要安装的插件,按照上面的配置格式将插件地址填写在vundle#beginvundle#end之间并保存设置好配置文件后,可通过下述两种方法安装插件:

  • 在Vim尾行模式下运行命令 :PluginInstall
  • 在终端命令行下通过命令 vim +PluginInstall +qall

删除插件

  1. 编辑Vim配置文件.vimrc文件,删除要移除插件所对应的Plugin一行
  2. 打开Vim,在Vim尾行模式执行命令:BundleClean即可删除对应Vim插件

Vim自带的代码补全功能

在插入模式下,Vim可以不借助任何插件实现自动补全功能。Vim自带有单词自动补全、行自动补全和基于用户自定义字典的自动补全。

  • Ctrl + n:当输入完第一个字母后,再按Ctrl + n,Vim会自动出现下拉菜单,且默认选中第一个单词
  • 继续按 Ctrl + n 可以上下选择,但如果缓冲区没有可选单词,那么下拉列表不会有任何选项
  • Ctrl + p:功能同上,只是默认选中的是列表最后一个单词
  • 在Vim插入模式下输入已经存在行的第一个单词,再按Ctrl + xCtrl + l命令,就会列出该整行出来实现Vim行自动补全

字典补全

假设有一个备选单词表,文件名为dict.txt,每行一个单词,里面包含以下内容:

  • Hello
  • Vim
  • editor
  • best
  • tool

若要实现基于该单词表的Vim自动补齐,需要设置以下步骤:

  1. /.vimrc配置文件中加入代码:`set dictionary-=/dict.txt dictionary+=~/dict.txt`
  2. 打开Vim,在插入模式下输入Ctrl + x后再输入Ctrl + k,就能看到dict.txt文件中定义的单词
  3. 若想直接通过Ctrl + n命令就显示其中的列表,再配置.vimrc文件,加入set complete-=k complete+=k

函数跳转

可以使用 Vim 插件 vim-gutentags 自动生成和更新 tags 文件进行跳转,得益于 Vim 8 提供的异步机制,vim插件vim-gutentags能够自动异步生成 tags 文件,当检测到同一个工程下面的文件有修改时,gutentags能自动增量更新对应工程的 tags 文件,而不用全部重新生成tags文件,是一个非常高效的tags生成工具。vim-gutentags的本质仍然是使用ctags生成tag标签来实现函数跳转等功能,只是在ctags的基础上进行了封装和简化,方便用户在vim中使用。由于vim-gutentags依赖ctags工具,因此在使用vim-gutentags插件的系统中必须安装ctags软件,否则会报错”Excutable ‘ctags’ can’t be found.”。

安装tags软件

1
$ sudo apt-get install exuberant-ctags

其次,vim-gutentags需要在vim8.0以上版本才能正常工作,因为vim-gutentags实现的是增量更新tags的方式,依赖于vim8提供的异步机制。在低于vim8.0的版本是运行vim-gutentags插件,会报错”this plugin requires the job API from Vim8 or Neovim”。 把相应vim文件放在~/.vim/bundle/下

在配置文件 ~/.vimrc 中增加配置项:

1
Plugin 'ludovicchabant/vim-gutentags'

再在vim的Normal模式下执行命令 :PlugInstall

vim-gutentags插件的基本工作原理可以这么理解:首先确定vim当前打开的文件是否需要自动生成tags标签,若需要则通过某种方式确定tag文件的路径,再基于tag标签文件完成函数跳转、结构体定义跳转等功能。

gutentags配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
" gutentags搜索工程目录的标志,碰到这些文件/目录名就停止向上一级目录递归
let g:gutentags_project_root = ['.root', '.svn', '.git', '.project']
" 所生成的数据文件的名称
let g:gutentags_ctags_tagfile = '.tags'
" 将自动生成的 tags 文件全部放入 ~/.cache/tags 目录中,避免污染工程目录
let s:vim_tags = expand('~/.cache/tags')
let g:gutentags_cache_dir = s:vim_tags
" 检测 ~/.cache/tags 不存在就新建
if !isdirectory(s:vim_tags)
silent! call mkdir(s:vim_tags, 'p')
endif
" 配置 ctags 的参数
let g:gutentags_ctags_extra_args = ['--fields=+niazS', '--extra=+q']
let g:gutentags_ctags_extra_args += ['--c++-kinds=+pxI']
let g:gutentags_ctags_extra_args += ['--c-kinds=+px']

变量 gutentags_project_root 是vim-gutentags提供的用于搜索工程目录的标志,gutentags插件启动后,会从文件当前路径递归往上查找 gutentags_project_root 中指定的文件或目录名,直到第一次找到对应目标文件或目录名停止。若没有找到 gutentags_project_root 变量指定的文件或目录名,则gutentags不会生成tag文件。

变量 gutentags_ctags_tagfile 和 gutentags_cache_dir 分别用于告诉ctags要使用的tag文件目录和tag文件名后缀,tag文件名的生成规则默认是根据生成tag文件的工程绝对路径按 - 分割而成。

变量 gutentags_ctags_extra_args 用于配置ctags生成tag标签的参数

ctags参数意义

参数 含义
c 类(classes)
d 宏定义(macro definitions)
e 枚举变量(enumerators)
f 函数定义(function definitions)
g 枚举类型(enumeration names)
l 局部变量(local variables),默认不提取
m 类、结构体、联合体(class, struct, and union members)
n 命名空间(namespaces)
p 函数原型(function prototypes),默认不提取
s 结构体类型(structure names)
t (typedefs)
u 联合体类型(union names)
v 变量定义(variable definitions)
x 外部变量(external and forward variable declarations),默认不提取

需要注意的是,gutentags 需要靠上面定义的 gutentags_project_root 判断文件所在的工程,如果一个文件没有保存在包含 .git.svn.root等 定义在 gutentags_project_root 中的文件,gutentags就不会为该野文件生成 tags。 #在为当前目录生成tags文件后,可以通过按键 Ctrl + ] 跳转到对应的定义位置,再使用命令 Ctrl + o 回退到原来的位置。 建议多使用 Ctrl + W + ] 用新窗口打开并查看光标下符号的定义,或者 Ctrl+W+] 使用 preview 窗口预览光标下符号的定义。

工程项目树展示

Vim插件NERDTree是一款用来在Vim界面显示树形目录的文件管理器插件,可在vim操作界面进行文件打开、目录浏览操作。其github地址为:https://github.com/scrooloose/nerdtree

使用Vim插件管理器Vundle安装Vim插件NERDTree:

1
Plugin 'scrooloose/nerdtree'

通过vundle安装好NERDTree插件后,在vim命令行模式输入命令:NERDTree就可以看到NERDTree的显示界面。使用快捷键 Ctrl + w,可将光标自动在左右侧窗口进行切换。

配置.vimrc文件

1
2
3
4
5
6
"在 vim 启动的时候默认开启 NERDTree:
autocmd VimEnter * NERDTree
或使用autocmd的缩写形式
au VimEnter * NERDTree
"将NERDTree的窗口设置在vim窗口的右侧(默认为左侧):
let NERDTreeWinPos="right"

NERDTree常用命令汇总

命令 作用
q 关闭 NERDTree
o 在已有窗口中打开文件或目录,并将光标跳到该窗口
O 递归打开选中 结点下的所有目录
x 合拢选中结点的父目录
X 递归 合拢选中结点下的所有目录
p 跳到根结点
P 跳到父结点
u 设置上级目录为根路径
U 设置上级目录为跟路径,但是维持原来目录打开的状态
r 刷新光标所在的目录
R 刷新当前根路径
I 显示或者不显示隐藏文件
f 打开和关闭文件过滤器
A 全屏显示 NERDTree,或者关闭全屏
C 将根路径设置为光标所在的目录

代码折叠

Vim支持多种折叠形式:手动折叠manual、基于缩进行折叠indent、基于语法进行折叠syntax、未更改文本折叠diff等

在 ~/.vimrc 配置文件中增加以下配置项

1
2
3
4
"基于缩进进行代码折叠
set foldmethod=indent
"启动 Vim 时关闭折叠
set nofoldenable

Vim打开文件后,重复使用操作命令 za 可打开或关闭当前折叠;zM 用于关闭所有折叠,zR 则用来打开所有折叠

全局搜索

推荐Vim模糊搜索插件ctrlp。ctrlp是一款支持对文件、缓冲区( :CtrlPBuffer )、MRU(Most Recently Used)文件( :CtrlPMRU )和标签进行模糊搜索/查找的Vim插件,也支持通过正则表达式搜索 ( -r 进行切换),同类软件还有模糊搜索插件fzf等。 地址:https://github.com/ctrlpvim/

安装插件

1
Plugin 'ctrlpvim/ctrlp.vim'

安装完ctrlp插件后,可以在Vim命令行模式下使用命令 :help ctrlp.txt 获取ctrlp的官方说明文档,这是个非常详细的文档,建议细读

ctrlp命令介绍

在Vim命令行模式下,可通过以下几种方式启动ctrlp:

  1. Vim命令行模式下使用命令

    :CtrlP:CtrlP 路径

    可以调用ctrlp并进入查找文件模式,可通过设置 let g:ctrlp_cmd = 'CtrlP' 来指定打开ctrlp的Vim命令行命令

  2. Vim命令行模式下使用命令

    :CtrlPBuffer:CtrlPMRU

    可以调用ctrlp并分别进入查找缓冲区 和 查找 MRU文件模式

  3. Vim命令行模式下使用命令

    :CtrlPMixed 可同时搜索 文件、缓冲区 和 MRU文件

  4. 在Vim 普通模式下,默认按下 Ctrl+p 即可打开ctrlp搜索窗口。可通过设置 let g:ctrlp_map = '<c-p>' 来修改Vim普通模式下默认打开ctrlp的Vim按键映射。

  5. 默认设置下,ctrlp的窗口显示在Vim窗口的底端(bottom),可以通过 g:ctrlp_match_window 选项设置窗口的位置,例如,let g:ctrlp_match_window = 'top,order:ttb,min:1,max:10,results:20' 设置ctrlp窗口显示在顶端(top),模糊搜索结果按从上到下(ttb, top to bottom)的顺序显示,高度最小为1行,最大为10行,搜索结果最多显示20行。

一旦打开ctrlp,即可输入要寻找的文件名使用ctrlp进行模糊搜索,可以使用以下命令进行操作:

  • 按下 EscCtrl-c 可退出ctrlp,返回到Vim窗口中
  • 按下 F5 用于刷新当前操作路径下的文件缓存,可以使用命令 let g:ctrlp_cache_dir = $HOME.'/.cache/ctrlp' 设置缓存文件存放路径
  • 使用 Ctrl-kCtrl-j 在模糊搜索结果列表中上下移动 (当然也可以使用键盘上的上下方向键
  • 使用 Ctrl-fCtrl-b 在查找文件模式、查找缓冲区模式、查找MRU文件几种模式间进行切换 (cycle between modes)
  • 使用 Ctrl-d 在 路径匹配 和 文件名匹配 之间切换 (switch to filename search instead of full path) ,可以通过设置 let g:ctrlp_by_filename = 1 来设置默认使用 文件名匹配 模式进行模糊搜索
  • 使用 Ctrl-r 在 字符串模式 和 正则表达式模式 之间切换 (switch to regexp mode)
  • 使用 Ctrl-t 在新的Vim标签页中打开文件 (open the selected entry in a new tab)
  • 使用 Ctrl-v 垂直分割窗口打开文件
  • 使用 Ctrl-x 水平分割窗口打开文件
  • 使用 Ctrl-p 或` 选择前或后一条历史记录
  • 使用 Ctrl-y 用于当搜索的目标文件不存在时创建文件及父目录 (create a new file and its parent directories)
  • 使用 Ctrl-z 标记或取消标记多个文件, 标记多个文件后可以使用 Ctrl-o 同时打开多个文件

括号自动补全

Github地址

安装插件

1
Plugin 'jiangmiao/auto-pairs'

配置.vimrc文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
"设置要自动配对的符号
let g:AutoPairs = {'(':')', '[':']', '{':'}',"'":"'",'"':'"'}
"添加要自动配对的符号<>
let g:AutoPairs['<']='>'
"设置要自动配对的符号,默认为g:AutoPairs,可以通过自动命令来对不同文件类型设置不同自动匹配对符号
let b:AutoPairs = g:AutoParis
"设置插件打开/关闭的快捷键,默认为ALT+p。
let g:AutoPairsShortcutToggle = '<M-p>'
"设置自动为文本添加圆括号的快捷键,默认为ALT+e。
let g:AutoPairsShortcutFastWrap = '<M-e>'
"设置调到下一层括号对的快捷键,默认为ALT+n。
let g:AutoPairsShortcutJump = '<M-n>'
"设置撤销飞行模式的快捷键,默认为ALT+b。
let g:AutoPairsShortcutBackInsert = '<M-b>'
"把BACKSPACE键映射为删除括号对和引号,默认为1。
let g:AutoPairsMapBS = 1
"把ctrl+h键映射为删除括号对和引号,默认为1。
let g:AutoPairsMapCh = 1
"把ENTER键映射为换行并缩进,默认为1。
let g:AutoPairsMapCR = 1
"当g:AutoPairsMapCR为1时,且文本位于窗口底部时,自动移到窗口中间。
let g:AutoPairsCenterLine = 1
"把SPACE键映射为在括号两侧添加空格,默认为1。
let g:AutoPairsMapSpace = 1
"启用飞行模式,默认为0。
let g:AutoPairsFlyMode = 0
"启用跳出多行括号对,默认为1,为0则只能跳出同一行的括号。
let g:AutoPairsMultilineClose = 1

安装vim-airline

1
Plugin 'bling/vim-airline'

安装neocomplete

1
Plugin 'Shougo/neocomplete'

注意启用设置粘贴set paste的时候会自动禁用这个插件

安装neocomplete 插件需要vim的lua模块支持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
let g:neocomplete#enable_at_startup = 1
"至此,neocomplete配置完成。同时,作者提供了一份neocomplete的配置,如果没有特殊需要,可以直接使用:
"Note: This option must be set in .vimrc(_vimrc). NOT IN .gvimrc(_gvimrc)!
" Disable AutoComplPop.
let g:acp_enableAtStartup = 0
" Use neocomplete.
let g:neocomplete#enable_at_startup = 1
" Use smartcase.
let g:neocomplete#enable_smart_case = 1
" Set minimum syntax keyword length.
let g:neocomplete#sources#syntax#min_keyword_length = 3

" Define dictionary.
let g:neocomplete#sources#dictionary#dictionaries = {
\ 'default' : '',
\ 'vimshell' : $HOME.'/.vimshell_hist',
\ 'scheme' : $HOME.'/.gosh_completions'
\ }

" Define keyword.
if !exists('g:neocomplete#keyword_patterns')
let g:neocomplete#keyword_patterns = {}
endif
let g:neocomplete#keyword_patterns['default'] = '\h\w*'

" Plugin key-mappings.
inoremap <expr><C-g> neocomplete#undo_completion()
inoremap <expr><C-l> neocomplete#complete_common_string()

" Recommended key-mappings.
" <CR>: close popup and save indent.
inoremap <silent> <CR> <C-r>=<SID>my_cr_function()<CR>
function! s:my_cr_function()
return (pumvisible() ? "\<C-y>" : "" ) . "\<CR>"
" For no inserting <CR> key.
"return pumvisible() ? "\<C-y>" : "\<CR>"
endfunction
" <TAB>: completion.
inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>"
" <C-h>, <BS>: close popup and delete backword char.
inoremap <expr><C-h> neocomplete#smart_close_popup()."\<C-h>"
inoremap <expr><BS> neocomplete#smart_close_popup()."\<C-h>"
" Close popup by <Space>.
"inoremap <expr><Space> pumvisible() ? "\<C-y>" : "\<Space>"

" AutoComplPop like behavior.
"let g:neocomplete#enable_auto_select = 1

" Shell like behavior(not recommended).
"set completeopt+=longest
"let g:neocomplete#enable_auto_select = 1
"let g:neocomplete#disable_auto_complete = 1
"inoremap <expr><TAB> pumvisible() ? "\<Down>" : "\<C-x>\<C-u>"

" Enable omni completion.
autocmd FileType css setlocal omnifunc=csscomplete#CompleteCSS
autocmd FileType html,markdown setlocal omnifunc=htmlcomplete#CompleteTags
autocmd FileType javascript setlocal omnifunc=javascriptcomplete#CompleteJS
autocmd FileType python setlocal omnifunc=pythoncomplete#Complete
autocmd FileType xml setlocal omnifunc=xmlcomplete#CompleteTags

" Enable heavy omni completion.
if !exists('g:neocomplete#sources#omni#input_patterns')
let g:neocomplete#sources#omni#input_patterns = {}
endif
"let g:neocomplete#sources#omni#input_patterns.php = '[^. \t]->\h\w*\|\h\w*::'
"let g:neocomplete#sources#omni#input_patterns.c = '[^.[:digit:] *\t]\%(\.\|->\)'
"let g:neocomplete#sources#omni#input_patterns.cpp = '[^.[:digit:] *\t]\%(\.\|->\)\|\h\w*::'

" For perlomni.vim setting.
" https://github.com/c9s/perlomni.vim
let g:neocomplete#sources#omni#input_patterns.perl = '\h\w*->\h\w*\|\h\w*::'

先到这里,以后发现了什么好玩的插件再来更新。