Vim配置

上周装了Ubuntu16.04,接下来打算在上面学习点C++开发,所以得先配个环境,打算配置一下Vim以及装一些插件,接下来就搞一下。

Vim升级

用的时候发现ubuntu默认的Vim、g++和gcc版本都偏低了,先更新一下,把Vim升级到8以上,g++更新升级到4.8.5以上以支持c++11。

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
# 安装依赖
sudo apt-get install libncurses5-dev
sudo apt-get install build-essential cmake
sudo apt-get install python-dev python3-dev
sudo apt-get install libgmp-dev libmpfr-dev libmpc-dev libisl-dev libcloog-isl-dev zlib1g-dev
sudo apt-get install autogen
sudo apt-get install libclang-dev

# 升级GCC
wget ftp://ftp.gnu.org/gnu/gcc/gcc-4.9.2/gcc-4.9.2.tar.gz
cd gcc-4.9.2
./configure --prefix=/opt/gcc-4.9.2 --enable-languages=c,c++ --disable-multilib --disable-bootstrap --with-system-zlib
make && make check
sudo make install

# 配置好,如果之前有这两个链接文件的话就删掉重新链接就行了
sudo ln -s /opt/gcc-4.9.2/bin/gcc /usr/bin/gcc
sudo ln -s /opt/gcc-4.9.2/bin/g++ /usr/bin/g++

# 升级Vim
sudo add-apt-repository ppa:jonathonf/vim
sudo apt-get update
sudo apt-get install vim-nox-py2
sudo mv /usr/local/bin/vim /usr/local/bin/vim.old
sudo ln -s /usr/bin/vim.nox-py2 /usr/local/bin/vim
# 参考 https://blog.csdn.net/yanjiee/article/details/76066936

Vim-Plug基本使用

Vim-plug 是一个自由、开源、速度非常快的、极简的 vim 插件管理器。

安装

安装很简单,执行以下命令即可:

1
2
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

插件安装

安装插件也很方便,主要有以下几步:

  • ~/.vimrc中声明需要安装的插件,这里以ligntline.vim插件为例,如下图所示

配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
let g:lightline = {
\ 'colorscheme': 'wombat',
\ 'active': {
\ 'left': [ [ 'mode', 'paste' ],
\ [ 'readonly', 'filename', 'modified', 'helloworld' ] ]
\ },
\ 'component': {
\ 'helloworld': 'I am writing shit...'
\ },
\ }

set laststatus=2
  • 重新打开vim,使用:PlugStatus命令查看插件状态,如图:
  • 接着输入:PlugInstall完成插件安装

更新插件

更新插件就运行:PlugUpdate即可,更新插件后,可以按d查看更改,或者也可以之后输入:PlugDiff

审查插件

有时候更新的插件会有问题或不能正常工作,要解决这个问题就可以回滚,输入:PlugDiff的命令按回车键查看上次的更改,然后在每个段落上按X将每个插件回滚到前一个状态。

删除插件

  • 首先将~/.vimrc文件中对应的插件配置plug命令删除或者注释,然后重启Vim编辑器,如图:
  • 然后在Vim里输入:PlugClean命令,接着按y,就可以删除已经不存在配置文件中的插件了。

升级Vim-Plug本身

输入:PlugUpgrade就可以升级Vim-Plug本身了。

安装ctags

需要重新安装ctags,使用Universal CTags,默认的Exuberant CTags太旧了。

1
2
3
4
5
6
7
8
sudo apt install autoconf
cd /tmp
git clone https://github.com/universal-ctags/ctags
cd ctags
./autogen.sh
./configure --prefix=PATH # 安装路径,自己的情况调整。
make
sudo make install

.vimrc里添加set tags=./tags;,tags

然后再用sudo apt install global安装gtags,这时已经可以通过在项目根目录运行ctags -R *来生成tags文件,就可以用了。

自动生成tags

使用vim-gutentags插件。

.vimrc里加入Plug 'ludovicchabant/vim-gutentags'

然后加入以下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
" gutentags 搜索工程目录的标志,碰到这些文件/目录名就停止向上一级目录递归
let g:gutentags_project_root = ['.root', '.svn', '.git', '.hg', '.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

" 配置 ctags 的参数
let g:gutentags_ctags_extra_args = ['--fields=+niazS', '--extra=+q']
let g:gutentags_ctags_extra_args += ['--c++-kinds=+px']
let g:gutentags_ctags_extra_args += ['--c-kinds=+px']

" 检测 ~/.cache/tags 不存在就新建
if !isdirectory(s:vim_tags)
silent! call mkdir(s:vim_tags, 'p')
endif

现在只要项目根目录里有'.root', '.svn', '.git', '.hg', '.project'这些文件,当使用vim编辑文件的时候就会自动生成.tag文件了,该文件可以在~/.cache/tags里看到。

现在就可以使用ctrl+]进行跳转了,但是建议使用ctrl+w+]用新窗口打开或者ctrl+w+}使用预览窗口,:pclose关闭预览窗口。

安装AsyncRun

Vim8以后,利用异步模式,可以让编译更方便,用AsyncRun插件,配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
Plug 'skywind3000/asyncrun.vim'
let g:asyncrun_rootmarks = ['.svn', '.git', '.root', '_darcs', 'build.xml']
" 自动打开 quickfix window ,高度为 6
let g:asyncrun_open = 6

" 任务结束时候响铃提醒
let g:asyncrun_bell = 1

" 设置 F10 打开/关闭 Quickfix 窗口
nnoremap <F10> :call asyncrun#quickfix_toggle(6)<cr>

" 设置F7编译整个项目,注意makefile的目录,可以自行修改
nnoremap <silent> <F7> :AsyncRun -cwd=<root>/src make <cr>

安装代码检查ALE

配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Plug 'dense-analysis/ale'
let g:ale_linters_explicit = 1
let g:ale_linters = {
\ 'csh': ['shell'],
\ 'zsh': ['shell'],
\ 'go': ['gofmt', 'golint'],
\ 'python': ['flake8', 'mypy', 'pylint'],
\ 'c': ['gcc', 'cppcheck'],
\ 'cpp': ['gcc', 'cppcheck'],
\ 'text': [],
\}
let g:ale_completion_delay = 500
let g:ale_echo_delay = 20
let g:ale_lint_delay = 500
let g:ale_echo_msg_format = '[%linter%] %code: %%s'
let g:ale_lint_on_text_changed = 'normal'
let g:ale_lint_on_insert_leave = 1
let g:airline#extensions#ale#enabled = 1

let g:ale_c_gcc_options = '-Wall -O2 -std=c99'
let g:ale_cpp_gcc_options = '-Wall -O2 -std=c++14'
let g:ale_c_cppcheck_options = ''
let g:ale_cpp_cppcheck_options = ''

这个插件比较大,装的比较久,成功后如图:

安装YouCompleteMe

这个也有点麻烦,走了不少坑,首先要对git做下设置,否则git clone的时候会不能获取到一些国外的repo,原因嘛……

1
2
3
git config --global http.proxy 'socks5://127.0.0.1:1080'

git config --global https.proxy 'socks5://127.0.0.1:1080'

运行上述两条命令,结合之前已经搞好的科学上网,就可以正常clone啦,而且速度好快哦~

配置如下:

1
2
3
4
5
6
7
8
9
10
let g:ycm_global_ycm_extra_conf='~/.vim/plugged/YouCompleteMe/third_party/ycmd/.ycm_extra_conf.py'
let g:ycm_add_preview_to_completeopt = 0
let g:ycm_show_diagnostics_ui = 0
let g:ycm_server_log_level = 'info'
let g:ycm_min_num_identifier_candidate_chars = 2
let g:ycm_collect_identifiers_from_comments_and_strings = 1
let g:ycm_complete_in_strings=1
let g:ycm_key_invoke_completion = '<c-z>' " 使用 Ctrl+Z 主动触发语义补全
noremap <c-z> <NOP>
set completeopt=menu,menuone

应该没问题了,但如果出现YouCompleteMe unavailable no module named builtins错误,则cd到YouCompleteMe目录下运行git submodule update --init --recursive,这个问题应该是因为网速问题没下完整。

如果出现The ycmd server SHUT DOWN (restart with ':YcmRestartServer'). Unexpected exit code 1.类似问题,则cd到YouCompleteMe目录下运行/usr/bin/python install.py

NerdTree

目录树,配置如下,按F3就可以打开目录树:

1
2
3
Plug 'scrooloose/nerdtree'

noremap <F3> :NERDTreeToggle<cr>

vim-cpp-enhanced-highlight

C++语法高亮插件,直接加入即可,不需多余配置。

Plug 'octol/vim-cpp-enhanced-highlight'

nerdcommerter

注释的插件,快捷键<leader>cc<leader>c<space>

LeaderF

函数列表插件,配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Plug 'Yggdroot/LeaderF', { 'do': './install.sh' }
let g:Lf_ShortcutF = '<c-p>'
let g:Lf_ShortcutB = '<m-n>'
noremap <c-n> :LeaderfMru<cr>
" 设置F2显示本文件的函数列表,这里Vim映射Alt键不成功,所以自己改成F2
noremap <F2> :LeaderfFunction!<cr>
noremap <m-n> :LeaderfBuffer<cr>
noremap <m-m> :LeaderfTag<cr>
let g:Lf_StlSeparator = { 'left': '', 'right': '', 'font': '' }

let g:Lf_RootMarkers = ['.project', '.root', '.svn', '.git']
let g:Lf_WorkingDirectoryMode = 'Ac'
let g:Lf_WindowHeight = 0.30
let g:Lf_CacheDirectory = expand('~/.vim/cache')
let g:Lf_ShowRelativePath = 0
let g:Lf_HideHelp = 1
let g:Lf_StlColorscheme = 'powerline'
let g:Lf_PreviewResult = {'Function':0, 'BufTag':0}

echodoc.vim

显示参数列表,配置:

1
2
3
Plug 'Shougo/echodoc.vim'

set noshowmode

当用YCM的tab补全函数名后,输入左括号即可显示参数信息,和YCM配合结果如图:

Vim所有配置

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
set number
set hlsearch
set incsearch
set softtabstop =4 " Tab key indents by 4 spaces.
set hidden " Switch between buffers without having to save first.
set noshowmode
" set cmdheight =2
" 插件列表

call plug#begin('~/.vim/plugged')
Plug 'itchyny/lightline.vim'
" Plug 'tenfyzhong/CompleteParameter.vim'
Plug 'ludovicchabant/vim-gutentags'
Plug 'skywind3000/asyncrun.vim'
Plug 'octol/vim-cpp-enhanced-highlight'
Plug 'dense-analysis/ale'
Plug 'scrooloose/nerdtree'
Plug 'scrooloose/nerdcommenter' " 注释的插件 <leader>cc和<leader>c<space>
Plug 'Yggdroot/LeaderF', { 'do': './install.sh' }
Plug 'Valloric/YouCompleteMe', { 'do': './install.py --clang-completer --go-completer' }
Plug 'Shougo/echodoc.vim'
call plug#end()

" ###################################################################
" lightline

let g:lightline = {
\ 'colorscheme': 'wombat',
\ 'active': {
\ 'left': [ [ 'mode', 'paste' ],
\ [ 'readonly', 'filename', 'modified', 'helloworld' ] ]
\ },
\ 'component': {
\ 'helloworld': 'I am writing shit...'
\ },
\ }

set laststatus=2
" ###################################################################
" ctags
set tags=./.tags;,.tags
" gutentags 搜索工程目录的标志,碰到这些文件/目录名就停止向上一级目录递归
let g:gutentags_project_root = ['.root', '.svn', '.git', '.hg', '.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

" 配置 ctags 的参数
let g:gutentags_ctags_extra_args = ['--fields=+niazS', '--extra=+q']
let g:gutentags_ctags_extra_args += ['--c++-kinds=+px']
let g:gutentags_ctags_extra_args += ['--c-kinds=+px']

" 检测 ~/.cache/tags 不存在就新建
if !isdirectory(s:vim_tags)
silent! call mkdir(s:vim_tags, 'p')
endif
" ###########################################################

" asyncrun

let g:asyncrun_rootmarks = ['.svn', '.git', '.root', '_darcs', 'build.xml']
" 自动打开 quickfix window ,高度为 6
let g:asyncrun_open = 6

" 任务结束时候响铃提醒
let g:asyncrun_bell = 1

" 设置 F10 打开/关闭 Quickfix 窗口
nnoremap <F10> :call asyncrun#quickfix_toggle(6)<cr>

" 设置F7编译整个项目,注意makefile的目录,可以自行修改
nnoremap <silent> <F7> :AsyncRun -cwd=<root>/src make <cr>
" ###########################################################

" ALE
let g:ale_linters_explicit = 1
let g:ale_linters = {
\ 'csh': ['shell'],
\ 'zsh': ['shell'],
\ 'go': ['gofmt', 'golint'],
\ 'python': ['flake8', 'mypy', 'pylint'],
\ 'c': ['gcc', 'cppcheck'],
\ 'cpp': ['gcc', 'cppcheck'],
\ 'text': [],
\}
let g:ale_completion_delay = 500
let g:ale_echo_delay = 20
let g:ale_lint_delay = 500
let g:ale_echo_msg_format = '[%linter%] %code: %%s'
let g:ale_lint_on_text_changed = 'normal'
let g:ale_lint_on_insert_leave = 1
let g:airline#extensions#ale#enabled = 1

let g:ale_c_gcc_options = '-Wall -O2 -std=c99'
let g:ale_cpp_gcc_options = '-Wall -O2 -std=c++14'
let g:ale_c_cppcheck_options = ''
let g:ale_cpp_cppcheck_options = ''

" ###########################################################
" YouCompleteMe
let g:ycm_global_ycm_extra_conf='~/.vim/plugged/YouCompleteMe/third_party/ycmd/.ycm_extra_conf.py'
let g:ycm_add_preview_to_completeopt = 0
let g:ycm_show_diagnostics_ui = 0
let g:ycm_server_log_level = 'info'
let g:ycm_min_num_identifier_candidate_chars = 2
let g:ycm_collect_identifiers_from_comments_and_strings = 1
let g:ycm_complete_in_strings=1
let g:ycm_key_invoke_completion = '<c-z>' " 使用 Ctrl+Z 主动触发语义补全
noremap <c-z> <NOP>
set completeopt=menu,menuone

" 修改补全列表配色
highlight PMenu ctermfg=0 ctermbg=242 guifg=black guibg=darkgrey
highlight PMenuSel ctermfg=242 ctermbg=8 guifg=darkgrey guibg=black

" 对指定源文件,输入两个字母后即触发语义补全
let g:ycm_semantic_triggers = {
\ 'c,cpp,python,java,go,erlang,perl': ['re!\w{2}'],
\ 'cs,lua,javascript': ['re!\w{2}'],
\ }

let g:ycm_filetype_whitelist = {
\ "c":1,
\ "cpp":1,
\ "go":1,
\ "python":1,
\ "sh":1,
\ "zsh":1,
\ }

let g:ycm_filetype_blacklist = {
\ 'markdown' : 1,
\ 'text' : 1,
\ 'pandoc' : 1,
\ 'infolog' : 1,
\}
" ###########################################################

" LeaderF
let g:Lf_ShortcutF = '<c-p>'
let g:Lf_ShortcutB = '<m-n>'
noremap <c-n> :LeaderfMru<cr>
" 设置F2显示本文件的函数列表,这里Vim映射Alt键不成功,所以自己改成F2
noremap <F2> :LeaderfFunction!<cr>
noremap <m-n> :LeaderfBuffer<cr>
noremap <m-m> :LeaderfTag<cr>
let g:Lf_StlSeparator = { 'left': '', 'right': '', 'font': '' }

let g:Lf_RootMarkers = ['.project', '.root', '.svn', '.git']
let g:Lf_WorkingDirectoryMode = 'Ac'
let g:Lf_WindowHeight = 0.30
let g:Lf_CacheDirectory = expand('~/.vim/cache')
let g:Lf_ShowRelativePath = 0
let g:Lf_HideHelp = 1
let g:Lf_StlColorscheme = 'powerline'
let g:Lf_PreviewResult = {'Function':0, 'BufTag':0}

" ###########################################################
" nerdtree

noremap <F3> :NERDTreeToggle<cr>
" ###########################################################
" echodoc
let g:echodoc_enable_at_startup = 1

" ###########################################################
" CompleteParameter
" inoremap <silent><expr> ( complete_parameter#pre_complete("()")
" smap <c-j> <Plug>(complete_parameter#goto_next_parameter)
" imap <c-j> <Plug>(complete_parameter#goto_next_parameter)
" smap <c-k> <Plug>(complete_parameter#goto_previous_parameter)
" imap <c-k> <Plug>(complete_parameter#goto_previous_parameter)