vim下使用YouCompleteMe实现代码提示、补全以及跳转设置
配置YouCompleteMe
1. 安装vundle
vundle是一个管理vim插件的工具,使用vundle安装YouCompleteMe比较方便。
按照作者在https://github.com/gmarik/Vundle.vim#about提供的方法安装好vundle。(主要是下载解压,病略微修改 .vimrc)
2. 使用vundle安装YouCompleteMe
主要根据作者自己的建议整理 https://github.com/Valloric/YouCompleteMe
在.vimrc中 vundle部分,添加一行:
Plugin ‘Valloric/YouCompleteMe‘
然后,打开vim,输入命令
:PluginInstall
就会开始自动安装vundle指定的各种插件。
由于要安装clang等,安装过程是非常久的,大概需要一个小时,这个时间完全可以去做些别的。
等安装好后,在.vim/vundle/YouCompleteMe目录下多了一堆目录和文件。
3. 使用YouCompleteMe
YouCompleteMe进行补全时需要查找一个 ycm_global_ycm_extra_conf文件。可以每次在工作目录中放置这个文件,也可以设置全局。全局设置要在.vimrc中添加一行
let g:ycm_global_ycm_extra_conf=‘~/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/.ycm_extra_conf.py‘
4. 效果图
YCM作者主页的效果图
实用的 .vimrc 文件
主要参考http://www.cnblogs.com/ma6174/archive/2011/12/10/2283393.html。 加入了前面介绍的ctags, YouCompleteMe的配置。1 " Suzzz 2014.11.03
2 " 主要参考 http://www.cnblogs.com/ma6174/archive/2011/12/10/2283393.html
3 " 额外添加了 ctags, YouCompleteMe等
4 " 主要特点
5
6 "1.按F5可以直接编译并执行C、C++、java代码以及执行shell脚本,按“F8”可进行C、C++代码的调试
7 "2.自动插入文件头 ,新建C、C++源文件时自动插入表头:包括文件名、作者、联系方式、建立时间等,读者可根据需求自行更改
8 "3.映射“Ctrl + A”为全选并复制快捷键,方便复制代码
9 "4.按“F2”可以直接消除代码中的空行
10 "5.“F3”可列出当前目录文件,打开树状文件目录
11 "6. 支持鼠标选择、方向键移动
12 "7. 代码高亮,自动缩进,显示行号,显示状态行
13 "8. 按“Ctrl + P”可自动补全
14 "9. []、{}、()、""、‘ ‘等都自动补全 --- 如果需要{}做函数形式的补全(右括号自动换行,加一个空行,光标定位到空行,可以看下面的修改提示)
15 "10. 使用YouCompleteMe提供C++的自动补全提示,效果类似 Visual Studio那种,可以解析系统头文件
16
17
18 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
19 " """""""""""""" Suzzz """""""""""""""""""""
20 "Vundle相关。Vundle是vim插件管理器,使用它来管理插件很方便,而且功能强大
21 "https://github.com/gmarik/Vundle.vim#about
22
23 set nocompatible " be iMproved, required
24 filetype off " required
25
26 " set the runtime path to include Vundle and initialize
27 set rtp+=~/.vim/bundle/Vundle.vim
28 call vundle#begin()
29
30 " alternatively, pass a path where Vundle should install plugins
31 "call vundle#begin(‘~/some/path/here‘)
32
33 " let Vundle manage Vundle, required
34 Plugin ‘gmarik/Vundle.vim‘
35
36 " plugin on GitHub repo 添加github上的vimn插件,形式非常简单
37 Plugin ‘tpope/vim-fugitive‘
38
39
40 "语法检查
41 Plugin ‘scrooloose/syntastic‘
42 "让 syntastic忽略 python 文件
43 let g:syntastic_ignore_files=[".*\.py$"]
44
45 "补全 python
46 Plugin ‘davidhalter/jedi‘
47
48 Plugin ‘rstacruz/sparkup‘, {‘rtp‘: ‘vim/‘}
49
50 " YouCompleteMe插件,很好的智能提示,基本达到 IDE 级别
51 Plugin ‘Valloric/YouCompleteMe‘
52
53
54 " All of your Plugins must be added before the following line 所有Vundle管理的插件必须安装在这里之前
55 call vundle#end() " required
56 filetype plugin indent on " required
57 " To ignore plugin indent changes, instead use:
58 "filetype plugin on
59 " YouCompleteMe 通过这个cm_global_ycm_extra_conf来获得补全规则,可以如下指定,也可以每次放置在工作目录
60 let g:ycm_global_ycm_extra_conf=‘~/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/.ycm_extra_conf.py‘
61 "让YouCompleteMe同时利用原来的ctags
62 let g:ycm_collect_identifiers_from_tag_files = 1
63
64
65
66
67 " """"""""""""" By ma6174 """""""""""""""""""""
68
69 " 显示相关
70
71 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
72
73 "set shortmess=atI " 启动的时候不显示那个援助乌干达儿童的提示
74
75 "winpos 5 5 " 设定窗口位置
76
77 "set lines=40 columns=155 " 设定窗口大小
78
79 "set nu " 显示行号
80
81 set go= " 不要图形按钮
82
83 "color asmanian2 " 设置背景主题
84
85 set guifont=Courier_New:h10:cANSI " 设置字体
86
87 "syntax on " 语法高亮
88
89 autocmd InsertLeave * se nocul " 用浅色高亮当前行
90
91 autocmd InsertEnter * se cul " 用浅色高亮当前行
92
93 "set ruler " 显示标尺
94
95 set showcmd " 输入的命令显示出来,看的清楚些
96
97 "set cmdheight=1 " 命令行(在状态行下)的高度,设置为1
98
99 "set whichwrap+=<,>,h,l " 允许backspace和光标键跨越行边界(不建议)
100
101 "set scrolloff=3 " 光标移动到buffer的顶部和底部时保持3行距离
102
103 set novisualbell " 不要闪烁(不明白)
104
105 set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [POS=%l,%v][%p%%]\ %{strftime(\"%d/%m/%y\ -\ %H:%M\")} "状态行显示的内容
106
107 set laststatus=1 " 启动显示状态行(1),总是显示状态行(2)
108
109 set foldenable " 允许折叠
110
111 set foldmethod=manual " 手动折叠
112
113 "set background=dark "背景使用黑色
114
115 set nocompatible "去掉讨厌的有关vi一致性模式,避免以前版本的一些bug和局限
116
117 " 显示中文帮助
118
119 if version >= 603
120
121 set helplang=cn
122
123 set encoding=utf-8
124
125 endif
126
127 " 设置配色方案
128
129 "colorscheme murphy
130
131 "字体
132
133 "if (has("gui_running"))
134
135 " set guifont=Bitstream\ Vera\ Sans\ Mono\ 10
136
137 "endif
138
139
140
141 set fencs=utf-8,ucs-bom,shift-jis,gb18030,gbk,gb2312,cp936
142
143 set termencoding=utf-8
144
145 set encoding=utf-8
146
147 set fileencodings=ucs-bom,utf-8,cp936
148
149 set fileencoding=utf-8
150
151
152
153 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
154
155 """""新文件标题""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
156
157 "新建.c,.h,.sh,.java文件,自动插入文件头
158
159 autocmd BufNewFile *.cpp,*.[ch],*.sh,*.java exec ":call SetTitle()"
160
161 ""定义函数SetTitle,自动插入文件头
162
163 func SetTitle()
164
165 "如果文件类型为.sh文件
166
167 if &filetype == ‘sh‘
168
169 call setline(1,"\#########################################################################")
170
171 call append(line("."), "\# File Name: ".expand("%"))
172
173 call append(line(".")+1, "\# Author: YourName")
174
175 call append(line(".")+2, "\# mail: YourEmail")
176
177 "张鹏 原来的时间形式比较复杂,不喜欢,改变一下
178
179 "call append(line(".")+3, "\# Created Time: ".strftime("%c"))
180 call append(line(".")+3, "\# Created Time: ".strftime("%Y-%m-%d",localtime()))
181
182 call append(line(".")+4, "\#########################################################################")
183
184 call append(line(".")+5, "\#!/bin/bash")
185
186 call append(line(".")+6, "")
187
188 else
189
190 call setline(1, "/*************************************************************************")
191
192 call append(line("."), " > File Name: ".expand("%"))
193
194 call append(line(".")+1, " > Author: YourName")
195
196 call append(line(".")+2, " > Mail: YourEmail ")
197
198 " 同样的 改变时间格式
199 "call append(line(".")+3, " > Created Time: ".strftime("%c"))
200 call append(line(".")+3, " > Created Time: ".strftime("%Y-%m-%d",localtime()))
201
202 call append(line(".")+4, " ************************************************************************/")
203
204 call append(line(".")+5, "")
205
206 endif
207
208 if &filetype == ‘cpp‘
209
210 call append(line(".")+6, "#include<iostream>")
211
212 call append(line(".")+7, "using namespace std;")
213
214 call append(line(".")+8, "")
215
216 endif
217
218 if &filetype == ‘c‘
219
220 call append(line(".")+6, "#include<stdio.h>")
221
222 call append(line(".")+7, "")
223
224 endif
225
226 "新建文件后,自动定位到文件末尾
227
228 autocmd BufNewFile * normal G
229
230 endfunc
231
232 " Suzzz: 模仿上面,新建python文件时,添加文件头
233
234 autocmd BufNewFile *py exec ":call SetPythonTitle()"
235
236 func SetPythonTitle()
237 call setline(1,"#!/usr/bin/env python")
238 call append( line("."),"#-*- coding: utf-8 -*-" )
239 call append(line(".")+1," ")
240 call append(line(".")+2, "\# File Name: ".expand("%"))
241 call append(line(".")+3, "\# Author: Peng Zhang")
242 call append(line(".")+4, "\# mail: YourEmail")
243 call append(line(".")+5, "\# Created Time: ".strftime("%Y-%m-%d",localtime()))
244 endfunc
245
246 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
247
248 "键盘命令
249
250 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
251
252
253
254 nmap <leader>w :w!<cr>
255
256 nmap <leader>f :find<cr>
257
258
259
260 " 映射全选+复制 ctrl+a
261
262 map <C-A> ggVGY
263
264 map! <C-A> <Esc>ggVGY
265
266 map <F12> gg=G
267
268 " 选中状态下 Ctrl+c 复制
269
270 vmap <C-c> "+y
271
272 "去空行
273
274 nnoremap <F2> :g/^\s*$/d<CR>
275
276 "比较文件
277
278 nnoremap <C-F2> :vert diffsplit
279
280 "新建标签
281
282 map <M-F2> :tabnew<CR>
283
284 "列出当前目录文件
285
286 map <F3> :tabnew .<CR>
287
288 "打开树状文件目录
289
290 map <C-F3> \be
291
292 "C,C++ 按F5编译运行
293
294 map <F5> :call CompileRunGcc()<CR>
295
296 func! CompileRunGcc()
297
298 exec "w"
299
300 if &filetype == ‘c‘
301
302 exec "!g++ % -o %<"
303
304 exec "! ./%<"
305
306 elseif &filetype == ‘cpp‘
307
308 exec "!g++ % -o %<"
309
310 exec "! ./%<"
311
312 elseif &filetype == ‘java‘
313
314 exec "!javac %"
315
316 exec "!java %<"
317
318 elseif &filetype == ‘sh‘
319
320 :!./%
321
322 endif
323
324 endfunc
325
326 "C,C++的调试
327
328 map <F8> :call Rungdb()<CR>
329
330 func! Rungdb()
331
332 exec "w"
333
334 exec "!g++ % -g -o %<"
335
336 exec "!gdb ./%<"
337
338 endfunc
339
340 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
341
342 ""实用设置
343
344 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
345
346 " 设置当文件被改动时自动载入
347
348 set autoread
349
350 " quickfix模式
351
352 autocmd FileType c,cpp map <buffer> <leader><space> :w<cr>:make<cr>
353
354 "代码补全
355
356 set completeopt=preview,menu
357
358 "允许插件
359
360 filetype plugin on
361
362 "共享剪贴板
363
364 set clipboard+=unnamed
365
366 "从不备份
367
368 set nobackup
369
370 "make 运行
371
372 :set makeprg=g++\ -Wall\ \ %
373
374 "自动保存
375
376 set autowrite
377
378 set ruler " 打开状态栏标尺
379
380 set cursorline " 突出显示当前行
381
382 set magic " 设置魔术
383
384 set guioptions-=T " 隐藏工具栏
385
386 set guioptions-=m " 隐藏菜单栏
387
388 "set statusline=\ %<%F[%1*%M%*%n%R%H]%=\ %y\ %0(%{&fileformat}\ %{&encoding}\ %c:%l/%L%)\
389
390 " 设置在状态行显示的信息
391
392 set foldcolumn=0
393
394 set foldmethod=indent
395
396 set foldlevel=3
397
398 set foldenable " 开始折叠
399
400 " 不要使用vi的键盘模式,而是vim自己的
401
402 set nocompatible
403
404 " 语法高亮
405
406 set syntax=on
407
408 " 去掉输入错误的提示声音
409
410 set noeb
411
412 " 在处理未保存或只读文件的时候,弹出确认
413
414 set confirm
415
416 " 自动缩进
417
418 set autoindent
419
420 set cindent
421
422 " Tab键的宽度
423
424 set tabstop=4
425
426 " 统一缩进为4
427
428 set softtabstop=4
429
430 set shiftwidth=4
431
432 " 不要用空格代替制表符
433
434 set noexpandtab
435
436 " 在行和段开始处使用制表符
437
438 set smarttab
439
440 " 显示行号
441
442 set number
443
444 " 历史记录数
445
446 set history=1000
447
448 "禁止生成临时文件
449
450 set nobackup
451
452 set noswapfile
453
454 "搜索忽略大小写
455
456 set ignorecase
457
458 "搜索逐字符高亮
459
460 set hlsearch
461
462 set incsearch
463
464 "行内替换
465
466 set gdefault
467
468 "编码设置
469
470 set enc=utf-8
471
472 set fencs=utf-8,ucs-bom,shift-jis,gb18030,gbk,gb2312,cp936
473
474 "语言设置
475
476 set langmenu=zh_CN.UTF-8
477
478 set helplang=cn
479
480 " 我的状态行显示的内容(包括文件类型和解码)
481
482 "set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [POS=%l,%v][%p%%]\ %{strftime(\"%d/%m/%y\ -\ %H:%M\")}
483
484 "set statusline=[%F]%y%r%m%*%=[Line:%l/%L,Column:%c][%p%%]
485
486 " 总是显示状态行
487
488 set laststatus=2
489
490 " 命令行(在状态行下)的高度,默认为1,这里是2
491
492 set cmdheight=2
493
494 " 侦测文件类型
495
496 filetype on
497
498 " 载入文件类型插件
499
500 filetype plugin on
501
502 " 为特定文件类型载入相关缩进文件
503
504 filetype indent on
505
506 " 保存全局变量
507
508 set viminfo+=!
509
510 " 带有如下符号的单词不要被换行分割
511
512 set iskeyword+=_,$,@,%,#,-
513
514 " 字符间插入的像素行数目
515
516 set linespace=0
517
518 " 增强模式中的命令行自动完成操作
519
520 set wildmenu
521
522 " 使回格键(backspace)正常处理indent, eol, start等
523
524 set backspace=2
525
526 " 允许backspace和光标键跨越行边界
527
528 set whichwrap+=<,>,h,l
529
530 " 可以在buffer的任何地方使用鼠标(类似office中在工作区双击鼠标定位)
531
532 set mouse=a
533
534 set selection=exclusive
535
536 set selectmode=mouse,key
537
538 " 通过使用: commands命令,告诉我们文件的哪一行被改变过
539
540 set report=0
541
542 " 在被分割的窗口间显示空白,便于阅读
543
544 set fillchars=vert:\ ,stl:\ ,stlnc:545
546 " 高亮显示匹配的括号
547
548 set showmatch
549
550 " 匹配括号高亮的时间(单位是十分之一秒)
551
552 set matchtime=1
553
554 " 光标移动到buffer的顶部和底部时保持3行距离
555
556 set scrolloff=3
557
558 " 为C程序提供自动缩进
559
560 set smartindent
561
562 " 高亮显示普通txt文件(需要txt.vim脚本)
563
564 au BufRead,BufNewFile * setfiletype txt
565
566 "自动补全
567
568 :inoremap ( ()<ESC>i
569
570 :inoremap ) <c-r>=ClosePair(‘)‘)<CR>
571
572 "by Suzzz: 原作者这种设置,输入{会自动补全,并且中间插入一个空行,将光标定位到空行。这对于函数是OK的,但是使用花括号初始化数组、vector时就不方便了。所以改为现在这种。只是补全,然后光标在左右括号中间。
573 ":inoremap { {<CR>}<ESC>O
574 :inoremap { {}<ESC>i
575
576 :inoremap } <c-r>=ClosePair(‘}‘)<CR>
577
578 :inoremap [ []<ESC>i
579
580 :inoremap ] <c-r>=ClosePair(‘]‘)<CR>
581
582 :inoremap " ""<ESC>i
583
584 :inoremap ‘ ‘‘<ESC>i
585
586 function! ClosePair(char)
587
588 if getline(‘.‘)[col(‘.‘) - 1] == a:char
589
590 return "\<Right>"
591
592 else
593
594 return a:char
595
596 endif
597
598 endfunction
599
600 filetype plugin indent on
601
602 "打开文件类型检测, 加了这句才可以用智能补全
603
604 set completeopt=longest,menu
605
606 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
607
608 " CTags的设定
609
610 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
611
612 let Tlist_Sort_Type = "name" " 按照名称排序
613
614 let Tlist_Use_Right_Window = 1 " 在右侧显示窗口
615
616 let Tlist_Compart_Format = 1 " 压缩方式
617
618 let Tlist_Exist_OnlyWindow = 1 " 如果只有一个buffer,kill窗口也kill掉buffer
619
620 let Tlist_File_Fold_Auto_Close = 0 " 不要关闭其他文件的tags
621
622 let Tlist_Enable_Fold_Column = 0 " 不要显示折叠树
623
624 autocmd FileType java set tags+=D:\tools\java\tags
625
626 "autocmd FileType h,cpp,cc,c set tags+=D:\tools\cpp\tags
627
628 "let Tlist_Show_One_File=1 "不同时显示多个文件的tag,只显示当前文件的
629
630 "设置tags
631
632 set tags=tags
633
634 "set autochdir
635
636
637
638 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
639
640 "其他东东
641
642 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
643
644 "默认打开Taglist
645
646 let Tlist_Auto_Open=1
647
648 """"""""""""""""""""""""""""""
649
650 " Tag list (ctags)
651
652 """"""""""""""""""""""""""""""""
653
654 let Tlist_Ctags_Cmd = ‘/usr/bin/ctags‘
655
656 let Tlist_Show_One_File = 1 "不同时显示多个文件的tag,只显示当前文件的
657
658 let Tlist_Exit_OnlyWindow = 1 "如果taglist窗口是最后一个窗口,则退出vim
659
660 let Tlist_Use_Right_Window = 1 "在右侧窗口中显示taglist窗口
661
662 " minibufexpl插件的一般设置
663
664 let g:miniBufExplMapWindowNavVim = 1
665
666 let g:miniBufExplMapWindowNavArrows = 1
667
668 let g:miniBufExplMapCTabSwitchBufs = 1
669 let g:miniBufExplModSelTarget = 1
配置
不同于很多vim插件,YCM首先需要编译,另外还需要有配置。在vim启动后,YCM会找寻当前路径以及上层路径的.ycm_extra_conf.py
.在~/.vim/bundle/YouCompleteMe/cpp/ycm/.ycm_extra_conf.py
中提供了默认的模板。也可以参考我的(就在模板上改改而已)。不过这个解决了标准库提示找不到的问题。
一般来说,我会在~
目录下放一个默认的模板,而后再根据不同的项目在当前目录下再拷贝个.ycm_extra_conf.py。
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
|
# This file is NOT licensed under the GPLv3, which is the license for the rest # of YouCompleteMe. # # Here's the license text for this file: # # This is free and unencumbered software released into the public domain. # # Anyone is free to copy, modify, publish, use, compile, sell, or # distribute this software, either in source code form or as a compiled # binary, for any purpose, commercial or non-commercial, and by any # means. # # In jurisdictions that recognize copyright laws, the author or authors # of this software dedicate any and all copyright interest in the # software to the public domain. We make this dedication for the benefit # of the public at large and to the detriment of our heirs and # successors. We intend this dedication to be an overt act of # relinquishment in perpetuity of all present and future rights to this # software under copyright law. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. # # For more information, please refer to <http://unlicense.org/> import os import ycm_core # These are the compilation flags that will be used in case there's no # compilation database set (by default, one is not set). # CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR. flags = [ '-Wall' , '-Wextra' , #'-Werror', #'-Wc++98-compat', '-Wno-long-long' , '-Wno-variadic-macros' , '-fexceptions' , '-stdlib=libc++' , # THIS IS IMPORTANT! Without a "-std=<something>" flag, clang won't know which # language to use when compiling headers. So it will guess. Badly. So C++ # headers will be compiled as C headers. You don't want that so ALWAYS specify # a "-std=<something>". # For a C project, you would set this to something like 'c99' instead of # 'c++11'. '-std=c++11' , # ...and the same thing goes for the magic -x option which specifies the # language that the files to be compiled are written in. This is mostly # relevant for c++ headers. # For a C project, you would set this to 'c' instead of 'c++'. '-x' , 'c++' , '-I' , '.' , '-isystem' , '/usr/include' , '-isystem' , '/usr/local/include' , '-isystem' , '/Library/Developer/CommandLineTools/usr/include' , '-isystem' , '/Library/Developer/CommandLineTools/usr/bin/../lib/c++/v1' , ] # Set this to the absolute path to the folder (NOT the file!) containing the # compile_commands.json file to use that instead of 'flags'. See here for # more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html # # Most projects will NOT need to set this to anything; you can just change the # 'flags' list of compilation flags. Notice that YCM itself uses that approach. compilation_database_folder = '' if os.path.exists( compilation_database_folder ): database = ycm_core.CompilationDatabase( compilation_database_folder ) else : database = None SOURCE_EXTENSIONS = [ '.cpp' , '.cxx' , '.cc' , '.c' , '.m' , '.mm' ] def DirectoryOfThisScript(): return os.path. dirname ( os.path.abspath( __file__ ) ) def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): if not working_directory: return list( flags ) new_flags = [] make_next_absolute = False path_flags = [ '-isystem' , '-I' , '-iquote' , '--sysroot=' ] for flag in flags: new_flag = flag if make_next_absolute: make_next_absolute = False if not flag.startswith( '/' ): new_flag = os.path. join ( working_directory, flag ) for path_flag in path_flags: if flag == path_flag: make_next_absolute = True break if flag.startswith( path_flag ): path = flag[ len( path_flag ): ] new_flag = path_flag + os.path. join ( working_directory, path ) break if new_flag: new_flags.append( new_flag ) return new_flags def IsHeaderFile( filename ): extension = os.path.splitext( filename )[ 1 ] return extension in [ '.h' , '.hxx' , '.hpp' , '.hh' ] def GetCompilationInfoForFile( filename ): # The compilation_commands.json file generated by CMake does not have entries # for header files. So we do our best by asking the db for flags for a # corresponding source file, if any. If one exists, the flags for that file # should be good enough. if IsHeaderFile( filename ): basename = os.path.splitext( filename )[ 0 ] for extension in SOURCE_EXTENSIONS: replacement_file = basename + extension if os.path.exists( replacement_file ): compilation_info = database.GetCompilationInfoForFile( replacement_file ) if compilation_info.compiler_flags_: return compilation_info return None return database.GetCompilationInfoForFile( filename ) def FlagsForFile( filename, **kwargs ): if database: # Bear in mind that compilation_info.compiler_flags_ does NOT return a # python list, but a "list-like" StringVec object compilation_info = GetCompilationInfoForFile( filename ) if not compilation_info: return None final_flags = MakeRelativePathsInFlagsAbsolute( compilation_info.compiler_flags_, compilation_info.compiler_working_dir_ ) # NOTE: This is just for YouCompleteMe; it's highly likely that your project # does NOT need to remove the stdlib flag. DO NOT USE THIS IN YOUR # ycm_extra_conf IF YOU'RE NOT 100% SURE YOU NEED IT. #try: # final_flags.remove( '-stdlib=libc++' ) #except ValueError: # pass else : relative_to = DirectoryOfThisScript() final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) return { 'flags' : final_flags, 'do_cache' : True } |
YouCompleteMe提供的其他功能
YCM除了提供了基本的补全功能,自动提示错误的功能外,还提供了类似tags的功能:
- 跳转到定义
GoToDefinition
- 跳转到声明
GoToDeclaration
- 以及两者的合体
GoToDefinitionElseDeclaration
可以在.vimrc中配置相应的快捷键。
1
2
3
|
nnoremap <leader>gl :YcmCompleter GoToDeclaration<CR> nnoremap <leader>gf :YcmCompleter GoToDefinition<CR> nnoremap <leader>gg :YcmCompleter GoToDefinitionElseDeclaration<CR> |
另外,YCM也提供了丰富的配置选项,同样在.vimrc中配置。具体请参考
1
2
|
let g:ycm_error_symbol = '>>' let g:ycm_warning_symbol = '>*' |
同时,YCM可以打开location-list来显示警告和错误的信息:YcmDiags。
个人关于ycm的配置如下:
1
2
3
4
5
6
7
|
" for ycm let g:ycm_error_symbol = '>>' let g:ycm_warning_symbol = '>*' nnoremap <leader>gl :YcmCompleter GoToDeclaration<CR> nnoremap <leader>gf :YcmCompleter GoToDefinition<CR> nnoremap <leader>gg :YcmCompleter GoToDefinitionElseDeclaration<CR> nmap <F4> :YcmDiags<CR> |
YCM提供的跳跃功能采用了vim的jumplist,
往前跳和往后跳的快捷键为Ctrl+O
以及Ctrl+I。
总结
YouCompleteMe
是我用过的最爽的一个自动补全的插件了。之前使用acp时,遇到大文件基本上就卡死了,以至于都不怎么敢使用。由于YCM使用的时C/S结构,部分使用vim脚本编写,部分认为原生代码,使得跑起来速度飞快。
抛弃Vim自带的坑爹的补全吧,抛弃ctags
吧,抛弃cscope
吧,YCM才是终极的补全神器。