title: 把Vim配置成属于自己的模样
tags:
  - Linux
  - Vim
  - Vimrc
categories:
  - 工具
top_img: false
cover: '/upload/cdn0files/20200721130037.jpg'
abbrlink: bfe797d6
date: 2019-12-30 22:06:09
updated: 2019-12-30 22:06:09

启用 Vim 的特性

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

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

$ vim ~/.vimrc

基础设置

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

设置中文不乱码

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

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

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

显示行号

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

set nu
set number

突出显示当前行

set cursorline

启用鼠标

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

set mouse=a
set selection=exclusive
set selectmode=mouse,key

设置缩进

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

粘贴格式

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

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

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

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

Vim配置变更立即生效

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

autocmd BufWritePost $MYVIMRC source $MYVIMRC

语法高亮

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

"打开文件类型检测
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依赖

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

安装Clang

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

$ sudo apt-get install clang

Clone

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

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

获取依赖

在源码目录执行:

git submodule update --init --recursive

编译安装

在源码目录执行:

$ 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 文件,添加下列配置:

"去除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软件

$ 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 中增加配置项:

Plugin 'ludovicchabant/vim-gutentags'

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

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

gutentags配置

" 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:

Plugin 'scrooloose/nerdtree'

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

配置.vimrc文件

"在 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 配置文件中增加以下配置项

"基于缩进进行代码折叠
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/

安装插件

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地址

安装插件

Plugin 'jiangmiao/auto-pairs'

配置.vimrc文件

"设置要自动配对的符号
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

Plugin 'bling/vim-airline'

安装neocomplete

Plugin 'Shougo/neocomplete'

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

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

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*::'

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