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才是終極補全神器。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM