Ubuntu16.04下vim8配置

Ubuntu16.04下vim8配置


1. 准备工作

# 卸载老旧发霉的exuberant-ctags
sudo apt-get --purge remove exuberant-ctags
# 卸载旧版vim及其相关组件
sudo apt-get remove --purge vim vim-runtime vim-gnome vim-tiny vim-gui-common
# 自动卸载无用依赖软件
sudo apt-get --purge autoremove
# 清理无用软件包
sudo apt-get autoclean
# 更新软件源
sudo apt-get update
# 安装checkinstall
sudo apt-get install checkinstall
# 安装pyton库
sudo apt-get -f install python-dev
sudo apt-get -f install python3-dev
# 安装界面相关库
sudo apt-get install libncurses5-dev
# 安装编译工具集
sudo apt-get install cmake build-essential
# 安装自动配置工具
sudo apt-get install autoconf pkg-config
# 安装cscope和global
sudo apt-get install cscope

说明:

  • exuberant-ctags 已经8年没更新,抛弃它,使用基于它之上的universal-ctags替代。
  • 由于YCM插件需要python支持,所以要卸载apt方式安装的vim,自行使用源码编译安装的最新vim。
  • make install安装软件会在/usr/local/下的各个子目录分别生成软件相关文件,这会导致如果想卸载软件很麻烦,需要从一个个目录中找出要卸载的软件相关的所有文件,然后一一删除。当然也可以在configure的时候为软件指定好单独的安装目录(例如:/opt/xxx , /usr/local/xxx 等等),这个做法的好处是卸载软件只需要删除指定的那个目录就行了,但是这样做安装完后shell找不到软件在哪里,还需要修改环境变量PATH增加新安装的软件路径才能正常使用,如果安装的软件太多,那么PATH就会特别长而且很乱,所以这种方式也不太好。checkinstall是一个源码安装工具,它收集安装信息,并且生成deb软件包,这使得所安装的软件可以用dpkg 来管理,dpkg -l xxx查询,dpkg -P xxx卸载干净。
  • python 库是必需的,很多插件需要python。
  • ncurses 是独立于终端基于文本的用户界面库,很多软件需要调用它提供的api(比如:make menuconfig)。
  • build-essential 是编译工具集,编译源码基本少不了它。
  • cmake 是一个基于软件源码自动生成Makefile的工具。
  • autoconf 是一个自动配置源码的工具,编译universal-ctags时需要。
  • cscope 配合vim实现代码查找跳转软件,这个不用说了,用vim的应该都知道。

2. 安装vim8

vim8新增了异步处理任务的特性,这使很多插件任务运行时vim还可以正常编辑,不会卡顿。由于gutentags插件需要vim8.0以上的版本才能工作,还有vim7更新GTAGS和cscope数据库时也会导致vim卡住不动,及其影响编辑体验,所以有必要安装最新的vim8。

ubuntu16.04的官方软件源目前没有vim8的deb,ubuntu18.04虽然支持apt直接安装vim8.0,但是默认安装不支持python,所以建议使用源码安装。

安装步骤:

# 从github克隆最新vim源码
git clone https://github.com/vim/vim.git
# 进入源码目录
cd vim
# 配置生成Makefile
./configure --with-features=huge \
            --enable-multibyte \
            --enable-rubyinterp=yes \
            --enable-python3interp=yes \
            --with-python3-config-dir=$(python3-config --configdir) \
            --enable-perlinterp=yes \
            --enable-luainterp=yes \
            --enable-gui=gtk2 \
            --enable-cscope \
            --prefix=/usr/local
# 编译
make -j8
# 安装(输入软件说明一路回车)
sudo checkinstall
# 完成后删除源码
cd ..
sudo rm -rf vim
# 使用dpkg查看
dpkg -l vim
# 设置vim为默认编辑器(vi和editor默认调用vim)
sudo update-alternatives --install /usr/bin/editor editor /usr/local/bin/vim 50
sudo update-alternatives --set editor /usr/local/bin/vim
sudo update-alternatives --install /usr/bin/vi vi /usr/local/bin/vim 50
sudo update-alternatives --set vi /usr/local/bin/vim

Ubuntu16.04下vim8配置_第1张图片

3. 安装universal-ctags

# 从github克隆最新universal-ctags源码
git clone https://github.com/universal-ctags/ctags.git
# 进入源码目录
cd ctags
# 运行自动配置脚本
./autogen.sh
# 配置生成Makefile
./configure
# 编译
make -j8
# 安装(输入软件说明一路回车)
# checkinstall的时候版本号不能为空(可以填0.0.0)
sudo checkinstall
# 完成后删除源码
cd ..
sudo rm -rf ctags
# 使用dpkg查看
dpkg -l ctags

Ubuntu16.04下vim8配置_第2张图片

4. 安装gnu-global

global(gnu-global内部包含gtags、global、gtags-cscope)功能和cscope差不多,可以生成gtags数据库,比cscope强的地方在于数据库增量更新非常快,比ctags强的地方在于不仅能查找定义还能查找引用。

# 下载gnu-global源码
wget http://tamacom.com/global/global-6.6.2.tar.gz
# 解压
tar xvf global-6.6.2.tar.gz
# 进入源码目录
cd global-6.6.2
# 配置生成Makefile
./configure
# 编译
make -j8
# 安装(输入软件说明一路回车)
sudo checkinstall
# 完成后删除源码
cd ..
sudo rm -rf global-6.6.2*
# 使用dpkg查看
dpkg -l global

Ubuntu16.04下vim8配置_第3张图片

5. 安装fonts-powerline

fonts-powerline 基于终端的字体,vim状态栏插件ariline需要它(不然箭头图标等显示不正确)。

安装

# 从github克隆最新powerline/fonts源码
git clone https://github.com/powerline/fonts.git --depth=1
# 进入源码目录
cd fonts
# 执行安装脚本
./install.sh
# 完成后删除源码
cd ..
rm -rf fonts

设置终端字体

  • ubuntu终端标题栏选择 Edit >> ProfilePreference >> General >> Custom font
  • 选择原来的字体替换成带Powerline的同名字体 :
    Ubuntu16.04下vim8配置_第4张图片

6. 安装vim-plug插件管理器

vim-plug是一个类似于Vundle的vim插件管理器,比Vundle更强大的地方在于支持全异步并发安装更新加载插件,还有支持插件按指定条件加载和延迟加载。

# 备份原来的vim配置
tar czvf vimbak.tar.gz ~/.vim ~/.vimrc
# 删除vim配置文件
rm -rf ~/.vim*
# 下载安装vim-plug插件
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

关于vim-plug怎么使用这里由于篇幅原因不细说,请参考一下链接:
https://vim.ink/vim-plug.html
https://www.jianshu.com/p/f4fb7877829f

7. 添加vimrc配置

需要的插件

  • vim中文帮助手册:yianwillis/vimcdoc
  • C++语法高亮增强:octol/vim-cpp-enhanced-highlight
  • 最近打开的文件维护插件:vim-scripts/mru.vim
  • 状态栏插件:
    vim-airline/vim-airline
    vim-airline/vim-airline-themes
  • Taglist插件:vim-scripts/taglist.vim
  • 树形目录插件:scrooloose/nerdtree
  • 通用函数插件:vim-scripts/genutils
  • 查找文件插件(依赖于genutils):vim-scripts/lookupfile
  • 自动更新tags插件:ludovicchabant/vim-gutentags
  • 自动加载切换gtags数据库:skywind3000/gutentags_plus
  • 预览 quickfix 窗口 ctrl-w z 关闭:skywind3000/vim-preview
  • 代码补齐插件:
    MarcWeber/vim-addon-mw-utils
    tomtom/tlib_vim
    garbas/vim-snipmate
  • 代码补齐模板:honza/vim-snippets
  • 自动补全插件YCM:Valloric/YouCompleteMe
  • 异步静态代码检查:w0rp/ale
  • 主题配色:
    morhetz/gruvbox
    mhinz/vim-janah
    nanotech/jellybeans.vim
    tomasr/molokai
    jpo/vim-railscasts-theme
    tpope/vim-vividchalk
    joshdick/onedark.vim

我的vimrc

" =============================================================================
" vim-plug插件管理
" =============================================================================
call plug#begin('~/.vim/plug')

" vim中文帮助手册
Plug 'yianwillis/vimcdoc'
" C++语法高亮增强
Plug 'octol/vim-cpp-enhanced-highlight'
" 最近打开的文件维护插件
Plug 'vim-scripts/mru.vim'
" 状态栏插件
Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'

" Taglist插件
Plug 'vim-scripts/taglist.vim', { 'on': 'TlistToggle' }
" 树形目录插件
Plug 'scrooloose/nerdtree', { 'on':  'NERDTreeToggle' }

" 通用函数插件
Plug 'vim-scripts/genutils'
" 查找文件插件(依赖于genutils)
Plug 'vim-scripts/lookupfile'

" 自动更新tags插件
Plug 'ludovicchabant/vim-gutentags'

" 代码补齐插件
Plug 'MarcWeber/vim-addon-mw-utils'
Plug 'tomtom/tlib_vim'
Plug 'garbas/vim-snipmate'
" 代码补齐模板
Plug 'honza/vim-snippets'

" 自动补全插件YCM
Plug 'Valloric/YouCompleteMe', { 'do': './install.py --clang-completer'}

" 异步静态代码检查
Plug 'w0rp/ale', { 'for': ['s', 'S', 'c', 'h', 'C', 'cpp', 'cc', 'cxx', 'py', 'go', 'java', 'js', 'php', 'sh', 'conf', 'vimrc', 'bashrc', 'config', 'ini', 'mk', 'makefile', 'Makefile'] }

" 主题配色
Plug 'morhetz/gruvbox'
Plug 'mhinz/vim-janah'
Plug 'nanotech/jellybeans.vim'
Plug 'tomasr/molokai'
Plug 'jpo/vim-railscasts-theme'
Plug 'tpope/vim-vividchalk'
Plug 'joshdick/onedark.vim'

call plug#end() 

" =============================================================================
" 编码相关
" =============================================================================
set termencoding=utf-8  " 设置终端显示编码
set encoding=utf-8      " 设置vim内部编码
" 菜单显示编码
set langmenu=zh_CN.UTF-8
" 设置可识别文件编码列表
set fileencodings=utf-8,gb2312,gbk,gb18030,cp936,utf-16,big5,latin1   

" =============================================================================
" 基本配置
" =============================================================================
" 开启文件类型检查,根据不同的文件类型加载不同的插件采用不同的缩进
filetype plugin indent on
syntax on               " 打开语法高亮
set t_Co=256            " 启用256色
set nocompatible        " 不与vi兼容(采用vim自己的操作命令) 
set background=dark     " 设置背景色
set cursorline          " 高亮光标所在行
" 高亮行颜色
highlight CursorLine cterm=Bold ctermbg=Black ctermfg=NONE guibg=Black guifg=NONE
"设置主题配色
"colorscheme gruvbox
"colorscheme janah
"colorscheme jellybeans
colorscheme molokai
"colorscheme railscasts
"colorscheme vividchalk
"colorscheme onedark
"colorscheme desert
"colorscheme torte
"colorscheme ron
set number              " 显示行号
set laststatus=2        " 是否显示状态栏(0,1,2)
set ruler               " 在状态栏显示当前光标坐标
set showmode            " 底行显示当前处于哪种模式
set showcmd             " 命令模式下,在底行显示键入的指令
set mouse=vh           " 鼠标模式(n,v,i,c,h,a,r,A)
set scrolloff=7         " 垂直滚动时光标距离顶部/底部的行数
set sidescrolloff=7     " 水平滚动时光标距离边缘的字符数
"set showmatch           " 插入括号时短暂跳转到对应的另一个括号
set nobackup            " 不创建备份文件
set noerrorbells        " 出错时不要发出声音
"set visualbell          " 出错时发出视觉提示(通常时屏幕闪烁)
set history=1024        " 记录历史操作的数量
set autoread            " 打开文件监视,如果在编辑中的文件被外部修改则提示
set autowrite           " 跳转时自动保存
" 文件换行符检测列表
set fileformats=unix,dos,mac
set foldenable          " 默认折叠
set foldmethod=marker   " 折叠方式
set guioptions-=T       " gvim不包含工具栏
set guioptions-=m       " gvim不使用菜单栏
set guioptions-=r       " gvim不显示右边滚动条
set guioptions-=l       " gvim不显示左边滚动条
set helpheight=10       " 帮助窗口的最小高度
set helplang=cn,en      " 帮助手册语言
set hidden              " 允许在有未保存的修改时切换缓冲区
set nowrap              " 不自动折行
set helplang=cn         " 中文帮助优先
"自动向上递归查找tags文件
set tags=./tags;

" =============================================================================
" 编辑相关
" =============================================================================
set tabstop=4           " 制表符宽度(Tab空格数)
set softtabstop=4       " 软制表符宽度(按Tab键和Backspace键时光标跳转的空格数)
set shiftwidth=4        " 缩进宽度(空格数)
set expandtab           " 制表符替换为空格
set autoindent          " 自动缩进
set cindent             " 特别针对C语言的自动缩进
set cinoptions=:0       " 自动缩进方案
set smartindent         " 插入新行时自动缩进
" 启用退格键删除功能
set backspace=indent,eol,start
set whichwrap=h,l       "使用指定的左右移动光标键可以移到前一行和后一行
" 自动补全模式
set complete=.,w,b,u,t,i,d
" 自动补全选项
set completeopt=longest,menu
set pumheight=10        " 自动补全菜单显示的最多项目数
" 文件和目录名补全忽略的文件
set wildignore=*.bak,*.o,*.e,*~
set wildmenu            " 命令模式下,按Tab键补全命令
" 命令补全模式
set wildmode=longest:list,full
set hlsearch            " 查找时高亮显示匹配结果
set incsearch           " 查找输入时,每输入一个字符,自动跳转到第一个匹配结果
set ignorecase          " 查找时忽略大小写
set smartcase           " 针对只有首字母时大写的查找词不忽略大小写

" =============================================================================
" 自动命令
" =============================================================================
" 打开文件光标自动跳转到上次关闭时的位置
autocmd BufReadPost *
    \ if line("'\"") > 0 && line("'\"") <= line("$") |
    \     exe "normal g'\"" |
    \ endif

" =============================================================================
" 快捷键
" =============================================================================
" Leader键设置
let mapleader=','

" 使用分号进入命令模式
nnoremap  :
vnoremap  :

" 窗口切换快捷键
nnoremap <C-h> <C-w>h
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-l> <C-w>l
inoremap <C-h> <Esc><C-w>h
inoremap <C-j> <Esc><C-w>j
inoremap <C-k> <Esc><C-w>k
inoremap <C-l> <Esc><C-w>l

" 窗口大小调整
nnoremap + :resize +1
nnoremap _ :resize -1
nnoremap \ :vertical resize +1
nnoremap ; :vertical resize -1
 
" shell命令调用函数
function! RunShell(Msg, Shell)
	echo a:Msg . '...'
    call system(a:Shell)
	echo 'Done!!!'
endfunction

" vimgrep查找字符串
nmap  :vimgrep /=expand("<cword>")/ **/*.c **/*.h:cw
" 生成filenametags快捷键F7
nmap <F7> :call RunShell("Generate filenametags", "genftags")<cr>
" 生成GTAGS数据库文件快捷键F8
nmap  :call RunShell("Generate GTAGS DB", "gengtags")
" 生成tags文件快捷键F9 
nmap <F9> :call RunShell("Generate ctags", "genctags")<cr>
" 生成cscope数据库文件快捷键F10 
nmap  :call RunShell("Generate cscope DB", "gencsdb")
" 更新cscope或者GTAGS数据库快捷键F12
nmap <F12> :call UpdateDb()<cr>

" =============================================================================
" 插件配置
" =============================================================================
" 不加载standard-plugin,避免高亮匹配括号
let loaded_matchparen = 1

" lookupfile.vim
" -----------------------------------------------------------------------------
" 映射LookupFile快捷键
nmap lt :LUTags
" 映射LUBufs快捷键
nmap <Leader>lb :LUBufs<cr>
" 映射LUWalk快捷键
nmap lw :LUWalk  
" 最少输入2个字符才开始查找
let g:LookupFile_MinPatLength=2
" 不保存上次查找的字符串
let g:LookupFile_PreserveLastPattern=0
" 保存查找历史
let g:LookupFile_PreservePatternHistory=1
" 回车打开第一个匹配项目
let g:LookupFile_AlwaysAcceptFirst=1
" 不允许创建不存在的文件
let g:LookupFile_AllowNewFiles=0
" 关闭对搜索结果的字母排序
let g:LookupFile_SortMethod=""
" 向上递归查找tags文件
let g:filename_tags=findfile("filenametags", ".;")
" 设置tags文件
if filereadable(g:filename_tags)
    let g:LookupFile_TagExpr='"'.g:filename_tags.'"'
endif
" 查找忽略大小写
function! LookupFile_IgnoreCaseFunc(pattern)
    let _tags = &tags
    try
        let &tags = eval(g:LookupFile_TagExpr)
        let newpattern = '\c' . a:pattern
        let tags = taglist(newpattern)
    catch
        echohl ErrorMsg | echo "Exception: " . v:exception | echohl NONE
        return ""
    finally
        let &tags = _tags
    endtry

    " Show the matches for what is typed so far.
    let files = map(tags, 'v:val["filename"]')
    return files
endfunction
let g:LookupFile_LookupFunc = 'LookupFile_IgnoreCaseFunc'

" mru.vim
" -----------------------------------------------------------------------------
" 打开mru快捷键F4
nmap  <F4> :MRU<cr>

" man.vim
" -----------------------------------------------------------------------------
" 启动man插件
source $VIMRUNTIME/ftplugin/man.vim
" man 光标定位的函数
nmap <Leader>mm :Man <C-R>=expand("")<cr><cr>
" man 2 光标定位的函数
nmap m2 :Man 2 =expand("<cword>")
" man 3 光标定位的函数
nmap <Leader>m3 :Man 3 <C-R>=expand("")<cr><cr>

" taglist.vim
" -----------------------------------------------------------------------------
" 设置打开关闭快捷键F2
nmap   :TlistToggle
" 自动更新tags列表
let g:Tlist_Auto_Update=1
" 始终解析文件中的tag,不管taglist窗口有没有打开
let g:Tlist_Process_File_Always=1
" 当taglist窗口是最后一个窗口时退出vim
let g:Tlist_Exit_OnlyWindow=1
" 只显示一个文件的tags
let g:Tlist_Show_One_File=1
" 窗口宽度
let g:Tlist_WinWidth=30
" 只显示当前文件的tags
let g:Tlist_Enable_Fold_Column=0
" 高亮显示当前tag
let g:Tlist_Auto_Highlight_Tag=1
" 设置窗口显示在右侧
"let g:Tlist_Use_Right_Window=1
" 打开时光标定位于taglist窗口
let g:Tlist_GainFocus_On_ToggleOpen=1

" NERDTree.vim
" -----------------------------------------------------------------------------
" 设置打开关闭快捷键F3 
nmap  <F3> :NERDTreeToggle<cr>
" 窗口美化
let NERDChristmasTree=1
" 自动调整光标到窗口中心
let NERDTreeAutoCenter=1
" 指定鼠标模式(1.双击打开;2.单目录双文件;3.单击打开)
let NERDTreeMouseMode=2
" 默认显示文件
let NERDTreeShowFiles=1
" 默认显示隐藏文件
let NERDTreeShowHidden=1
" 窗口位置('left' or 'right'let g:NERDTreeWinPos="right"
" 窗口宽度
let g:NERDTreeWinSize=30
" 显示行号
let g:NERDTreeShowLineNumbers=1
" 打开文件后关闭NERDTree窗口
let g:NERDTreeQuitOnOpen=1
" 高亮显示当前行目录或文件
let NERDTreeHightCursorline=1

" cscope配置
" -----------------------------------------------------------------------------
" cscope数据库更新完毕回调函数
function! UpcsCallback(...)
	execute "cs reset"
endfunction

" 更新cscope数据库函数
function! UpdateCsdb(path)
    if (a:path != '')
	    execute "cd " . a:path
    endif
    call job_start("cscope -bkq", {'exit_cb': 'UpcsCallback'})
    if (a:path != '')
	    execute "cd -"
    endif
endfunction

" 更新GTAGS数据库函数
function! UpdateGtags(f)
    let l:dir = fnamemodify(a:f, ':p:h')
    execute "cd " . l:dir
    call job_start("global -u")
	execute "cd -"
endfunction

" 更新cscope或者GTAGS数据库
function! UpdateDb()
    if g:csflag == 1
        call UpdateCsdb(g:cspath)
    elseif g:csflag == 2
        call UpdateGtags(expand(''))
    else
    endif
endfunction

" 获取GTAGS目录
let s:gtfile = system('global -pq')
" 向上递归寻找cscope.files
let g:csfile = findfile("cscope.out", ".;")

" 如果存在cscope.out则获取目录
if filereadable(g:csfile)
    " 设置cscope模式标志
    let g:csflag = 1
    " 获取cscope.out目录
    let s:pathlen = strridx(g:csfile, "cscope.out")
    let g:cspath = strpart(g:csfile, 0, s:pathlen)
" 如果存在GTAGS则获取目录
elseif s:gtfile != ""
    " 设置cscope模式标志
    let g:csflag = 2
    " 获取GTAGS目录
    let g:gtpath = strpart(s:gtfile, 0, strlen(s:gtfile) - 1)
else
    " 设置cscope模式标志
    let g:csflag = 0
endif

" cscope模式
if g:csflag == 1 && executable('cscope')
    " 设置cscope映射的程序
    set csprg=/usr/bin/cscope
    " 自动命令查找结果不使用quickfix窗口
    " autocmd BufReadPost * set cscopequickfix="s-,c-,d-,i-,t-,e-,g-,f-,a-"
    " 保存文件后自动更新GTAGS
    autocmd BufWritePost * call UpdateCsdb(g:cspath)
    " 加载cscope.out
    set nocsverb
    execute 'cs add ' . g:csfile
" gtags模式
elseif g:csflag == 2 && executable('gtags-cscope')
    " 设置cscope映射的程序
    set csprg=/usr/local/bin/gtags-cscope
    " 加载GTAGS
    execute 'silent cs add ' . g:gtpath . '/GTAGS'
    " 保存文件后自动更新GTAGS
    autocmd BufWritePost * call UpdateGtags(expand(''))
else
    " 不加载
endif

" 显示添加数据库结果
set csverb
" 使用cstag命令代替tag命令 
set cst
" 优先搜索cscope.out,失败再搜索tags
set csto=0
" 显示文件路径全名 
set cspc=0

" cscope当前窗口直接跳转快捷键
nnoremap fs :cs find s =expand("<cword>")
nnoremap fg :cs find g =expand("<cword>")
nnoremap fd :cs find d =expand("<cword>")
nnoremap fc :cs find c =expand("<cword>")
nnoremap ft :cs find t =expand("<cword>")
nnoremap fe :cs find e =expand("<cword>")
nnoremap ff :cs find f =expand("<cfile>")
nnoremap fi :cs find i =expand("<cfile>")
nnoremap fa :cs find a =expand("<cword>")

" cscope跳转同时新建水平分割窗口快捷键
nnoremap <Leader>ss :scs find s <C-R>=expand("")<cr><cr>
nnoremap <Leader>sg :scs find g <C-R>=expand("")<cr><cr>
nnoremap <Leader>sd :scs find d <C-R>=expand("")<cr><cr>
nnoremap <Leader>sc :scs find c <C-R>=expand("")<cr><cr>
nnoremap <Leader>st :scs find t <C-R>=expand("")<cr><cr>
nnoremap <Leader>se :scs find e <C-R>=expand("")<cr><cr>
nnoremap <Leader>sf :scs find f <C-R>=expand("")<cr><cr>
nnoremap <Leader>si :scs find i <C-R>=expand("")<cr><cr>
nnoremap <Leader>sa :scs find a <C-R>=expand("")<cr><cr>

" cscope跳转同时新建垂直分割窗口快捷键
nnoremap vs :vert scs find s =expand("<cword>")
nnoremap vg :vert scs find g =expand("<cword>")
nnoremap vd :vert scs find d =expand("<cword>")
nnoremap vc :vert scs find c =expand("<cword>")
nnoremap vt :vert scs find t =expand("<cword>")
nnoremap ve :vert scs find e =expand("<cword>")
nnoremap vf :vert scs find f =expand("<cfile>")
nnoremap vi :vert scs find i =expand("<cfile>")
nnoremap va :vert scs find a =expand("<cword>")

" gutentags.vim
" -----------------------------------------------------------------------------
" 搜索工程目录的标志,碰到这些文件/目录名就停止向上一级目录递归 "
let g:gutentags_project_root = ['.root', '.svn', '.git', '.project']
" 所生成的数据文件的名称 "
let g:gutentags_ctags_tagfile = '.tags'
" tags模式设置
let g:gutentags_modules = []
if executable('ctags')
	let g:gutentags_modules += ['ctags']
endif
" 将自动生成的 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', '--extras=+q']
let g:gutentags_ctags_extra_args += ['--c++-kinds=+lpxzLANU']
let g:gutentags_ctags_extra_args += ['--c-kinds=+lpxzL']
" 如果使用universal ctags需要增加下面一行
let g:gutentags_ctags_extra_args += ['--output-format=e-ctags']

" YouCompleteMe.vim
" -----------------------------------------------------------------------------
" 补全配置脚本 
let g:ycm_global_ycm_extra_conf='~/.vim/plug/YouCompleteMe/third_party/ycmd/.ycm_extra_conf.py'

" 弹出列表时选择第1项的快捷键(默认为)
let g:ycm_key_list_select_completion = ['', '']
" 弹出列表时选择前1项的快捷键(默认为<S-TAB><UP>)
let g:ycm_key_list_previous_completion = ['', '']
" 主动补全, 默认为
let g:ycm_key_invoke_completion = ''
" 停止显示补全列表(防止列表影响视野),可以按<C-x>重新弹出
let g:ycm_key_list_stop_completion = ['']

" 停止提示是否载入本地ycm_extra_conf文件
let g:ycm_confirm_extra_conf = 0
" 自动开启语义补全
let g:ycm_seed_identifiers_with_syntax = 1
" 开启YCM 基于标签引擎
let g:ycm_collect_identifiers_from_tags_files = 1
" 从第2个键入字符就开始罗列匹配项
let g:ycm_min_num_of_chars_for_completion = 2
" 补全后自动关闭预览窗口
let g:ycm_autoclose_preview_window_after_completion = 1
" 禁止缓存匹配项,每次都重新生成匹配项
let g:ycm_cache_omnifunc=0
"离开插入模式后自动关闭预览窗口
autocmd InsertLeave * if pumvisible() == 0|pclose|endif
" 开启输入注释时补全
let g:ycm_complete_in_comments = 1
" 开启输入字符串时补全
let g:ycm_complete_in_strings = 1
" 开启注释和字符串中收集补全
let g:ycm_collect_identifiers_from_comments_and_strings = 1
" 关闭函数预览
let g:ycm_add_preview_to_completeopt = 0
" 关闭代码诊断
let g:ycm_show_diagnostics_ui = 0
" 设置标识符补全最小字符数
let g:ycm_min_num_identifier_candidate_chars = 2
"整合UltiSnips的提示
let g:ycm_use_ultisnips_completer = 1
" 语义补全的语言
let g:ycm_semantic_triggers =  {
			\ 'c,cpp,python,java,go,erlang,perl': ['re!\w{2}'],
			\ 'cs,lua,javascript': ['re!\w{2}'],
			\ }
		
" ALE.vim
" -----------------------------------------------------------------------------
"普通模式下警告跳转快捷键
nmap <silent> <Leader>p <Plug>(ale_previous_wrap)
nmap <silent> <Leader>n <Plug>(ale_next_wrap)
"x触发/关闭语法检查
nmap x :ALEToggle
"<Leader>y查看错误或警告的详细信息
nmap <Leader>y :ALEDetail<CR>
"始终开启标志列
"let g:ale_sign_column_always = 1
" 错误警告消息格式
let g:ale_echo_msg_error_str = 'E'
let g:ale_echo_msg_warning_str = 'W'
let g:ale_echo_msg_format = '[%linter%] %s [%severity%]'
" 文件打开时不进行检查
let g:ale_lint_on_enter = 0
" 文件修改时不进行检查
let g:ale_lint_on_text_changed = 'never'
" 文件保存时进行检查(默认)
"let g:ale_lint_on_save = 1
" 指定对应语言的检查工具
let g:ale_linters = {
            \   'c++': ['clang'],
            \   'c': ['clang'],
            \   'python': ['pylint'],
            \   'go': ['gofmt', 'golint'],
            \}
" 关闭补全功能
let g:ale_completion_enabled = 0
" 使能airline状态栏扩展
let g:airline#extensions#ale#enabled = 1
" 禁用高亮显示
"let g:ale_set_highlights = 0
" 自定义error和warning标志
"let g:ale_sign_error = '✗'
"let g:ale_sign_warning = '⚡'

" airline.vim
" -----------------------------------------------------------------------------
" 设置主题
let g:airline_theme='bubblegum'
" 这个是安装字体后必须设置此项"
let g:airline_powerline_fonts = 1
" 开启标签栏
let g:airline#extensions#tabline#enabled = 1
" 标签只显示文件名忽略路径
let g:airline#extensions#tabline#fnamemod = ':t'
" 显示缓冲区编号
let g:airline#extensions#tabline#buffer_nr_show = 1
" tabline中当前buffer两端的分隔字符
"let g:airline#extensions#tabline#left_sep = ' '
" tabline中未激活buffer两端的分隔字符
"let g:airline#extensions#tabline#left_alt_sep = '|'
" 缓冲区切换快捷键
nnoremap <Leader>. :bn<cr>
nnoremap <Leader>, :bp<cr>
nnoremap <Tab> :bn<cr>
" 关闭状态显示空白符号计数"
let g:airline#extensions#whitespace#enabled = 0
" 状态栏显示设置
if !exists('g:airline_symbols')
    let g:airline_symbols = {}
endif
" powerline symbols
let g:airline_left_sep = ''
let g:airline_left_alt_sep = ''
let g:airline_right_sep = ''
let g:airline_right_alt_sep = ''
let g:airline_symbols.branch = ''
let g:airline_symbols.readonly = ''
let g:airline_symbols.linenr = '☰'
let g:airline_symbols.maxlinenr = ''

说明:

  • 拷贝上文vimrc写入新建的~/.vimrc,然后打开vim,输入命令 :PlugInstall 即可自动安装插件。
  • 由于YCM插件有接近400M大小,下载很慢所以建议先注释掉Plug ‘Valloric/YouCompleteMe’,等安装完其余插件后再取消注释单独安装YCM。
  • YCM下载需要等待一段时间,下载完成可进入~/.vim/plug/YouCompleteMe下执行:git submodule update --init --recursive检查完整性
  • 使用 :PlugInstall 安装YCM,会自动下载自动执行./install.py --clang-completer编译,编译过程中会自动下载libclang7.0,不需要系统手动安装libclang,不过下载可能失败,如果自动编译不成功,需要进入:~/.vim/plug/YouCompleteMe目录下手动执行:./install.py --clang-completer进行编译。
  • 最后8行符号需要powerline字体才能显示,可以参考.vim/plug/vim-airline/doc/airline.txt第300行左右的配置。
  • 安装完成后效果:
    Ubuntu16.04下vim8配置_第5张图片

8. 使用

以下只介绍上文vimrc配置的功能如何使用,vim本身自带的功能和操作不讨论,有需要的同学请自行google。

快捷键

  • F2: 启动左侧Taglist窗口
  • F3: 打开右侧NerdTree窗口
  • F4: 打开mru窗口显示最近打开过的文件,选择文件回车打开
  • F5: 窗口上方打开LookupFile搜索窗口,输入文件名或者目录名查找文件,Ctrl-N、Ctrl-P选择,回车打开
  • F6: 打开vimgrep,输入任意字符进行搜索(相当于shell的grep命令)
  • F7: 在当前目录下生成filename.tags文件,LookupFile使用该文件进行查找,生成过程中vim不允许操作
  • F8: 在当前目录下生成GTAGS数据库相关文件,gtags-cscope使用该数据库进行代码查找和跳转
  • F9: 在当前目录下生成tags文件,供ctags使用
  • F10: 在当前目录下生成cscope数据库相关文件,cscope基于cscope.out进行代码搜索和跳转
  • F12: 更新cscope或者GTAGS数据库
  • 空格 : 进入底行命令模式
  • Ctrl - h: 从当前窗口切换到左侧窗口
  • Ctrl - l: 从当前窗口切换到右侧窗口
  • Ctrl - k: 从当前窗口切换到上侧窗口
  • Ctrl - j: 从当前窗口切换到下侧窗口
  • Ctrl - x: 主动补全
  • Ctrl - y: 关闭补全列表
  • Ctrl - n: 补全列表向下选择
  • Ctrl - p: 补全列表向上选择
  • Shift - =: “+” 增加当前窗口高度
  • Shift - -: “_” 减小当前窗口高度
  • ; : 减小当前窗口宽度
  • \ : 增加当前窗口宽度
  • , lt: 打开LookupFile按tags搜索文件
  • , lb: 打开LookupFile按vim缓冲区搜索文件
  • , lw: 打开LookupFile按目录搜索文件
  • , mm: man查找当前光标所在函数
  • , m2: man 2查找当前光标所在函数(系统调用)
  • , m3: man 3查找当前光标所在函数(库函数)
  • , fs: 查找并跳转到当前光标所在标识符出现的地方
  • , fg: 查找并跳转到当前光标所在标识符的定义处
  • , fd: 查找并跳转到被当前光标所在函数调用的函数
  • , fc: 查找并跳转到调用当前光标所在函数的地方
  • , ft: 查找并跳转到当前光标所在的字符串
  • , fe: egrep模式查找并跳转到当前光标所在的字符串
  • , ff: 查找并跳转到当前光标所在的文件名
  • , fi: 查找并跳转到当前文件所包含的文件
  • , fa: 查找并跳转到当前光标所在的标识符被赋值的地方
  • , ss: 查找并水平分割窗口跳转到当前光标所在标识符出现的地方
  • , sg: 查找并水平分割窗口跳转到当前光标所在标识符的定义处
  • , sd: 查找并水平分割窗口跳转到被当前光标所在函数调用的函数
  • , sc: 查找并水平分割窗口跳转到调用当前光标所在函数的地方
  • , st: 查找并水平分割窗口跳转到当前光标所在的字符串
  • , se: egrep模式查找并水平分割窗口跳转到当前光标所在的字符串
  • , sf: 查找并水平分割窗口跳转到当前光标所在的文件名
  • , si: 查找并水平分割窗口跳转到当前文件所包含的文件
  • , sa: 查找并水平分割窗口跳转到当前光标所在的标识符被赋值的地方
  • , vs: 查找并垂直分割窗口跳转到当前光标所在标识符出现的地方
  • , vg: 查找并垂直分割窗口跳转到当前光标所在标识符的定义处
  • , vd: 查找并垂直分割窗口跳转到被当前光标所在函数调用的函数
  • , vc: 查找并垂直分割窗口跳转到调用当前光标所在函数的地方
  • , vt: 查找并垂直分割窗口跳转到当前光标所在的字符串
  • , ve: egrep模式查找并垂直分割窗口跳转到当前光标所在的字符串
  • , vf: 查找并垂直分割窗口跳转到当前光标所在的文件名
  • , vi: 查找并垂直分割窗口跳转到当前文件所包含的文件
  • , va: 查找并垂直分割窗口跳转到当前光标所在的标识符被赋值的地方
  • , x: 打开/关闭语法检查
  • , y: 显示语法错误或警告详细信息
  • , p: 跳转到上一处错误或警告
  • , n: 跳转到下一处错误或警告
  • Tab : 切换到下一个缓冲区(标签栏下一个)
  • , .: 切换到下一个缓冲区(标签栏下一个)
  • , ,: 切换到下一个缓冲区(标签栏上一个)

genftags脚本

由于Lookupfile插件默认基于ctags产生的索引进行查找文件,ctags本身除了文件信息还有大量的代码标识符等其他信息,这会使得Lookupfile查找速度很慢,所以一般都是专门为Lookupfile建立一个只有文件索引的tags文件。为了方便使用,把建立Lookupfile专用tags文件写成一个shell脚本放到~/.local/bin目录下,命名为genftags,这样只需要在项目根目录下执行:./genftags 命令就可以生成filename.tags供Lookupfile使用了。

#!/bin/sh
# generate tag file for lookupfile plugin                                                                                                                                                        
echo -e "!_TAG_FILE_SORTED\t2\t/2=foldcase/" > filenametags
find . -path ".svn" -prune -o \
    -path ".git" -prune -o \
    ! -iregex '.*\.\(png\|gif\|jpg\|o\|so\|a\|zip\|rar\|7z\|bin\|obj\|dll\|lib\|exe\)' \
    -type f -printf "%f\t%p\t1\n" | \ 
    sort -f >> filenametags

在~/.local/bin目录下新建名为genftag的文件,然后把上面的脚本内容拷贝进去,保存,然后运行:source ~/.profile 或者退出当前用户重新登录系统,就可以在任意目录下使用genftags命令了。

ctags的使用

在项目根目录执行:ctags -R即可生成tags文件,使用vim打开项目目录下的任何文件都会自动向上递归寻找tags文件然后加载。可以在vim里输入 :set tags 查看当前加载的tags文件路径。

  • ctags在vim的操作:
    ctags -R :在当前目录递归遍历所有子目录生成的tags文件
    Ctrl - ] :跳转到标识符定义处
    Ctrl - T:跳转返回
    vim -t tag:在tags目录下直接用vim打开tag变量或函数定义的地方
    :ts :列出所有tag列表
    :tn :跳转到下一个tag处
    :tp :跳转到上一个tag处

由于默认ctags -R命令会把所有文件都包好进来,有很多是不需要的非代码文件,这不但会导致tags文件过大,而且还会影响生成tags的速度,同时影响查找跳转的效率,因为多了很多无关信息。所以建议使用如下命令生成tags文件:

ctags -R --c-kinds=+lpxzL --c++-kinds=+lpxzLANU --fields=+niazS --extras=+q --output-format=e-ctags

因为我们使用了universal-ctags,所以要加上 --output-format=e-ctags ,该选项表示生成兼容exuberant-ctags格式的tags文件。

gutentags插件

  • 上一节手动生成tags的方式有一个巨大的不足,就是当你修改了某个文件内容,tags文件是不会自动更新的,必须返回tags目录下手动更新tags,并且tags不支持增量更新,所以相当于重新生成一遍,速度很慢。
  • 为了解决这个问题,就引进了gutentags插件,它支持修改保存文件的时候异步自动更新tags,该插件必需在vim8以上版本才能正常运行。
  • gutentags会从当前打开文件的目录向上递归查找项目根目录,找到了就会在~/.cache/tags下生成对应项目的tags文件,并且当使用vim打开项目下的文件时自动加载对应的tags,并且当修改保存文件时自动更新tags,而且是异步完成更新,也就是更新过程中还可以正常使用vim,不会卡住不动。
  • gutentags查找项目根目录的依据是寻找特殊文件,找到就认为该目录是项目根目录,这些特殊文件可以自定义,参考上文vimrc配置里面的gutentags插件配置部分,以下是我的vimrc使用的特殊文件列表:
    .root、.svn、.git、.project
  • 所以如果想让gutentags自动创建自动加载自动更新tags,就需要在工程目录下存在以上特殊文件,没有的话直接touch一个.root空文件就可以了

cscope和gtags-cscope

这两个家伙功能基本一致,使用方法也一样,参考上面快捷键。关于cscope和gtags的介绍请自行google,本文不做详细介绍。cscope使用方法可以在vim命令下输入 :cscope help 获得,配置项详情可以通过 :help cscope 查看,上文的vimrc已经配置好了中文vim帮助手册,查看任何配置项详细介绍只需要在vim命令行输入 :help xxx 即可。
上文vimrc实现了自动检测cscope和gtags数据库,并且自动加载,由于这两者使用的快捷键一样(,f、,s、,v 三组快捷键),所以只能二选一,参考我的vimrc配置中关于cscope部分的详细内容,规则如下:

  • 使用vim打开文件自动向上递归查找cscope.out数据库文件
  • 如果找到,则设置cscopegprg = /usr/bin/cscope,自动加载cscope.out,不再加载GTAGS
  • 如果没找到cscope.out,则设置cscopegprg = /usr/local/bin/gtags-cscope,并且从当前文件目录自动向上递归查找GTAGS数据库文件
  • 如果找到,自动加载GTAGS
    通过上述规则,vim可以自动判断并加装cscope和gtags,而且是优先是用cscope。

最后

以上只大概介绍了本文的vim配置的部分功能,实际使用中的一些细节无法详细描述,比如还有状态栏主题更换,ALE静态代码检查等等,需要自己亲自体验之后修改vimrc对应部分的配置来实现个性化。本文提供的vimrc基本上每部分都有注释说明,各个配置详细说明还可以通过vim中文帮助 :help xxx 来查看。大家可根据自己需要自行修改。
如果要熟悉vim自带的一些操作,最好的学习方式是使用vim自带的vimtutor,直接在命令行里输入:

vimtutor -g zh

即可启动中文版vim练习教程。

另外,在快捷键配置中F7~F10对应了4个shell脚本genftags、genctags、gengtags、gencsdb,需要自行编辑并添加(参考上面genftags小节),不然这几个快捷键是无法使用的。下面是我个人使用的vim配置,包好了.vim、.vimrc和相关的快捷shell脚本:

vimconfig.tar.xz
密码:w2a0

vim还有无数本文没介绍的各种功能插件,有需要的同学请自行添加配置。

你可能感兴趣的:(Ubuntu16.04下vim8配置)