2020年了,不要再看網(wǎng)上那些老舊的文章還在教你使用手工生成 tags 的,請使用自動代碼索引生成工具,比如 vim-gutentags,現(xiàn)在網(wǎng)上好像就沒有一篇能正確討論 Vim C/C++ 環(huán)境搭建的,都在談些十年前的東西,所以我寫了篇關(guān)于 Vim 8 和 C/C++ 相關(guān)插件的介紹:
假設(shè)你已經(jīng)有一定 Vim 使用經(jīng)驗,并且折騰過 Vim 配置,能夠相對舒適的在 Vim 中編寫其他代碼的時候,準(zhǔn)備在 Vim 開始 C/C++ 項目開發(fā),或者你已經(jīng)用 Vim 編寫了幾年 C/C++ 代碼,想要更進一步,讓自己的工作更加順暢的話,本文就是為你準(zhǔn)備的:
插件管理
為什么把插件管理放在第一個來講呢?這是比較基本的一個東西,如今 Vim 下熟練開發(fā)的人,基本上手都有 20-50 個插件,遙想十年前,Vim里常用的插件一只手都數(shù)得過來。過去我一直使用老牌的 Vundle 來管理插件,但是隨著插件越來越多,更新越來越頻繁,Vundle 這種每次更新就要好幾分鐘的東西實在是不堪重負了。
在我逐步對 Vundle 失去耐心之后,我試用了 vim-plug ,用了兩天以后就再也回不去 Vundle了,它支持全異步的插件安裝,安裝50個插件只需要一分鐘不到的時間,這在 Vundle 下面根本不可想像的事情,插件更新也很快,不像原來每次更新都可以去喝杯茶去,最重要的是它支持插件延遲加載:
“ 定義插件,默認用法,和 Vundle 的語法差不多Plug ‘junegunn/vim-easy-align’Plug ‘skywind3000/quickmenu.vim’” 延遲按需加載,使用到命令的時候再加載或者打開對應(yīng)文件類型才加載Plug ‘scrooloose/nerdtree’, { ‘on’: ‘NERDTreeToggle’ }Plug ‘tpope/vim-fireplace’, { ‘for’: ‘clojure’ }“ 確定插件倉庫中的分支或者 tagPlug ‘rdnetto/YCM-Generator’, { ‘branch’: ‘stable’ }Plug ‘nsf/gocode’, { ‘tag’: ‘v.20150303’, ‘rtp’: ‘vim’ }
定義好插件以后一個 :PlugInstall 命令就并行安裝所有插件了,比 Vundle 快捷不少,關(guān)鍵是 vim-plug 只有單個文件,正好可以放在我 github 上的 vim 配置倉庫中,每次需要更新 vim-plug 時只需要 :PlugUpgrade,即可自我更新。使用時建議給插件分組,同類別插件放一個組里,vimrc 里面只需要確定下啟用哪些組就行了。
拋棄 Vundle 切換到 vim-plug 以后,不僅插件安裝和更新快了一個數(shù)量級,大量的插件我都配置成了延遲加載,Vim 啟動速度比 Vundle 時候提高了不少。使用 Vundle 的時候一旦插件數(shù)量超過30個,管理是一件很痛苦的事情,而用了 vim-plug 以后,50-60個插件都輕輕松松。
符號索引
現(xiàn)在有好多 ctags 的代替品,比如 gtags, etags 和 cquery。然而我并不排斥 ctags,因為他支持 50+ 種語言,沒有任何一個符號索引工具有它支持的語言多。同時 Vim 和 ctags 集成的相當(dāng)好,用它依賴最少,大量基礎(chǔ)工作可以直接通過 ctags 進行,然而到現(xiàn)在為止,我就沒見過幾個人把 ctags 用對了的。
就連配置文件他們都沒寫對,正確的 ctags 配置應(yīng)該是:
set tags=。/.tags;,.tags
這里解釋一下,首先我把 tag 文件的名字從“tags” 換成了 “.tags”,前面多加了一個點,這樣即便放到項目中也不容易污染當(dāng)前項目的文件,刪除時也好刪除,gitignore 也好寫,默認忽略點開頭的文件名即可。
前半部分 “。/.tags; ”代表在文件的所在目錄下(不是 “:pwd”返回的 Vim 當(dāng)前目錄)查找名字為 “.tags”的符號文件,后面一個分號代表查找不到的話向上遞歸到父目錄,直到找到 .tags 文件或者遞歸到了根目錄還沒找到,這樣對于復(fù)雜工程很友好,源代碼都是分布在不同子目錄中,而只需要在項目頂層目錄放一個 .tags文件即可;逗號分隔的后半部分 .tags 是指同時在 Vim 的當(dāng)前目錄(“:pwd”命令返回的目錄,可以用 :cd 。.命令改變)下面查找 .tags 文件。
最后請更新你的 ctags,不要再使用老舊的 Exuberant Ctags,這貨停止更新快十年了,請使用最新的 Universal CTags 代替之,它在 Exuberant Ctags 的基礎(chǔ)上繼續(xù)更新迭代了近十年,如今任然活躍的維護著,功能更強大,語言支持更多。
(注意最新版 universal ctags 調(diào)用時需要加一個 --output-format=e-ctags,輸出格式才和老的 exuberant ctags 兼容否則會有 windows 下路徑名等小問題)。
自動索引
過去寫幾行代碼又需要運行一下 ctags 來生成索引,每次生成耗費不少時間。如今 Vim 8 下面自動異步生成 tags 的工具有很多,這里推薦最好的一個:vim-gutentags,這個插件主要做兩件事情:
- 確定文件所屬的工程目錄,即文件當(dāng)前路徑向上遞歸查找是否有 `.git`, `.svn`, `.project` 等標(biāo)志性文件(可以自定義)來確定當(dāng)前文檔所屬的工程目錄。
- 檢測同一個工程下面的文件改動,能會自動增量更新對應(yīng)工程的 `.tags` 文件。每次改了幾行不用全部重新生成,并且這個增量更新能夠保證 `.tags` 文件的符號排序,方便 Vim 中用二分查找快速搜索符號。
vim-gutentags 需要簡單配置一下:
” gutentags 搜索工程目錄的標(biāo)志,碰到這些文件/目錄名就停止向上一級目錄遞歸let g:gutentags_project_root = [‘.root’, ‘.svn’, ‘.git’, ‘.hg’, ‘.project’]“ 所生成的數(shù)據(jù)文件的名稱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 的參數(shù)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
有了上面的設(shè)置,你平時基本感覺不到 tags 文件的生成過程了,只要文件修改過,gutentags 都在后臺為你默默打點是否需要更新數(shù)據(jù)文件,你根本不用管,還會幫你:setlocal tags+=。.. 添加到局部 tags 搜索列表中。
為當(dāng)前文件添加上對應(yīng)的 tags 文件的路勁而不影響其他文件。得益于 Vim 8 的異步機制,你可以任意隨時使用 ctags 相關(guān)功能,并且數(shù)據(jù)庫都是最新的。需要注意的是,gutentags 需要靠上面定義的 project_root 里的標(biāo)志,判斷文件所在的工程,如果一個文件沒有托管在 .git/.svn 中,gutentags 找不到工程目錄的話,就不會為該野文件生成 tags,這也很合理。想要避免的話,你可以在你的野文件目錄中放一個名字為 .root 的空白文件,主動告訴 gutentags 這里就是工程目錄。
最后啰嗦兩句,少用 CTRL-] 直接在當(dāng)前窗口里跳轉(zhuǎn)到定義,多使用 CTRL-W ] 用新窗口打開并查看光標(biāo)下符號的定義,或者 CTRL-W } 使用 preview 窗口預(yù)覽光標(biāo)下符號的定義。
我自己還寫過不少關(guān)于 ctags 的 vimscript,例如在最下面命令行顯示函數(shù)的原型而不用急著跳轉(zhuǎn),或者重復(fù)按 `ALT+;` 在 preview 窗口中輪流查看多個定義,不切走當(dāng)前窗口,不會出一個很長的列表讓你選擇,有興趣可以刨我的 vim dotfiles。
編譯運行
再 Vim 8 以前,編譯和運行程序要么就讓 vim 傻等著結(jié)束,不能做其他事情,要么切到一個新的終端下面去單獨運行編譯命令和執(zhí)行命令,要么開個 tmux 左右切換。如今新版本的異步模式可以讓這個流程更加簡化,這里我們使用 AsyncRun 插件,簡單設(shè)置下:
Plug ‘skywind3000/asyncrun.vim’“ 自動打開 quickfix window ,高度為 6let g:asyncrun_open = 6” 任務(wù)結(jié)束時候響鈴提醒let g:asyncrun_bell = 1“ 設(shè)置 F10 打開/關(guān)閉 Quickfix 窗口nnoremap 《F10》 :call asyncrun#quickfix_toggle(6)《cr》
該插件可以在后臺運行 shell 命令,并且把結(jié)果輸出到 quickfix 窗口:
最簡單的編譯單個文件,和 sublime 的默認 build system 差不多,我們定義 F9 為編譯單文件:
nnoremap 《silent》 《F9》 :AsyncRun gcc -Wall -O2 “$(VIM_FILEPATH)” -o “$(VIM_FILEDIR)/$(VIM_FILENOEXT)” 《cr》
其中 $(。..) 形式的宏在執(zhí)行時會被替換成實際的文件名或者文件目錄,這樣按 F9 就可以編譯當(dāng)前文件,同時按 F5 運行:
nnoremap 《silent》 《F5》 :AsyncRun -raw -cwd=$(VIM_FILEDIR) “$(VIM_FILEDIR)/$(VIM_FILENOEXT)” 《cr》
用雙引號引起來避免文件名包含空格,“-cwd=$(VIM_FILEDIR)” 的意思時在文件文件的所在目錄運行可執(zhí)行,后面可執(zhí)行使用了全路徑,避免 linux 下面當(dāng)前路徑加 “。/” 而 windows 不需要的跨平臺問題。
參數(shù) `-raw` 表示輸出不用匹配錯誤檢測模板 (errorformat) ,直接原始內(nèi)容輸出到 quickfix 窗口。這樣你可以一邊編輯一邊 F9 編譯,出錯了可以在 quickfix 窗口中按回車直接跳轉(zhuǎn)到錯誤的位置,編譯正確就接著執(zhí)行。
接下來是項目的編譯,不管你直接使用 make 還是 cmake,都是對一群文件做點什么,都需要定位到文件所屬項目的目錄,AsyncRun 識別當(dāng)前文件的項目目錄方式和 gutentags相同,從文件所在目錄向上遞歸,直到找到名為 “.git”, “.svn”, “.hg”或者 “.root”文件或者目錄,如果遞歸到根目錄還沒找到,那么文件所在目錄就被當(dāng)作項目目錄,你重新定義項目標(biāo)志:
let g:asyncrun_rootmarks = [‘.svn’, ‘.git’, ‘.root’, ‘_darcs’, ‘build.xml’]
然后在 AsyncRun 命令行中,用 “《root》” 或者 “$(VIM_ROOT)”來表示項目所在路徑,于是我們可以定義按 F7 編譯整個項目:
nnoremap 《silent》 《F7》 :AsyncRun -cwd=《root》 make 《cr》
那么如果你有一個項目不在 svn 也不在 git 中怎么查找 《root》 呢?很簡單,放一個空的 .root 文件到你的項目目錄下就行了,前面配置過,識別名為 .root 的文件。
繼續(xù)配置用 F8 運行當(dāng)前項目:
nnoremap 《silent》 《F8》 :AsyncRun -cwd=《root》 -raw make run 《cr》
當(dāng)然,你的 makefile 中需要定義怎么 run ,接著按 F6 執(zhí)行測試:
nnoremap 《silent》 《F6》 :AsyncRun -cwd=《root》 -raw make test 《cr》
如果你使用了 cmake 的話,還可以照葫蘆畫瓢,定義 F4 為更新 Makefile 文件,如果不用 cmake 可以忽略:
nnoremap 《silent》 《F4》 :AsyncRun -cwd=《root》 cmake 。 《cr》
由于 C/C++ 標(biāo)準(zhǔn)庫的實現(xiàn)方式是發(fā)現(xiàn)在后臺運行時會緩存標(biāo)準(zhǔn)輸出直到程序退出,你想實時看到 printf 輸出的話需要 fflush(stdout) 一下,或者程序開頭關(guān)閉緩存:“setbuf(stdout, NULL);” 即可。
同時,如果你開發(fā) C++ 程序使用 std::cout 的話,后面直接加一個 std::endl 就強制刷新緩存了,不需要弄其他。而如果你在 Windows 下使用 GVim 的話,可以彈出新的 cmd.exe 窗口來運行剛才的程序:
nnoremap 《silent》 《F5》 :AsyncRun -cwd=$(VIM_FILEDIR) -mode=4 “$(VIM_FILEDIR)/$(VIM_FILENOEXT)” 《cr》nnoremap 《silent》 《F8》 :AsyncRun -cwd=《root》 -mode=4 make run 《cr》
在 Windows 下使用 -mode=4 選項可以跟 Visual Studio 執(zhí)行命令行工具一樣,彈出一個新的 cmd.exe窗口來運行程序或者項目,于是我們有了下面的快捷鍵:
F4:使用 cmake 生成 Makefile
F5:單文件:運行
F6:項目:測試
F7:項目:編譯
F8:項目:運行
F9:單文件:編譯
F10:打開/關(guān)閉底部的 quickfix 窗口
恩,編譯和運行基本和 NotePad++ / GEdit 的體驗差不多了。如果你重度使用 cmake 的話,你還可以寫點小腳本,將 F4 和 F7 的功能合并,檢測 CMakeLists.txt 文件改變的話先執(zhí)行 cmake 更新一下 Makefile,然后再執(zhí)行 make,否則直接執(zhí)行 make,這樣更自動化些。
動態(tài)檢查
代碼檢查是個好東西,讓你在編輯文字的同時就幫你把潛在錯誤標(biāo)注出來,不用等到編譯或者運行了才發(fā)現(xiàn)。我很奇怪 2018 年了,為啥網(wǎng)上還在到處介紹老舊的 syntastic,但凡見到介紹這個插件的文章基本都可以不看了。老的 syntastic 基本沒法用,不能實時檢查,一保存文件就運行檢查器并且等待半天,所以請用實時 linting 工具 ALE:
大概長這個樣子,隨著你不斷的編輯新代碼,有語法錯誤的地方會實時幫你標(biāo)注出來,側(cè)邊會標(biāo)注本行有錯,光標(biāo)移動過去的時候下面會顯示錯誤原因,而具體錯誤的符號下面會有紅色波浪線提醒。Ale 支持多種語言的各種代碼分析器,就 C/C++ 而言,就支持:gcc, clang, cppcheck 以及 clang-format 等,需要另行安裝并放入 PATH下面,ALE能在你修改了文本后自動調(diào)用這些 linter 來分析最新代碼,然后將各種 linter 的結(jié)果進行匯總并顯示再界面上。
同樣,我們也需要簡單配置一下:
let g:ale_linters_explicit = 1let g:ale_completion_delay = 500let g:ale_echo_delay = 20let g:ale_lint_delay = 500let g:ale_echo_msg_format = ‘[%linter%] %code: %%s’let g:ale_lint_on_text_changed = ‘normal’let g:ale_lint_on_insert_leave = 1let g:airline#extensions#ale#enabled = 1let 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 = ‘’
基本上就是定義了一下運行規(guī)則,信息顯示格式以及幾個 linter 的運行參數(shù),其中 6,7 兩行比較重要,它規(guī)定了如果 normal 模式下文字改變以及離開 insert 模式的時候運行 linter,這是相對保守的做法,如果沒有的話,會導(dǎo)致 YouCompleteMe 的補全對話框頻繁刷新。
記得設(shè)置一下各個 linter 的參數(shù),忽略一些你覺得沒問題的規(guī)則,不然錯誤太多沒法看。默認錯誤和警告的風(fēng)格都太難看了,你需要修改一下,比如我使用 GVim,就重新定義了警告和錯誤的樣式,去除默認難看的紅色背景,代碼正文使用干凈的波浪下劃線表示:
let g:ale_sign_error = “\\ue009\\ue009”hi! clear SpellBadhi! clear SpellCaphi! clear SpellRarehi! SpellBad gui=undercurl guisp=redhi! SpellCap gui=undercurl guisp=bluehi! SpellRare gui=undercurl guisp=magenta
不同項目之間如果評測標(biāo)準(zhǔn)不一樣還可以具體單獨制定 linter 的參數(shù),具體見 ALE 幫助文檔了。我基本使用兩個檢查器:gcc 和 cppcheck,都可以在 ALE 中進行詳細配置,前者主要檢查有無語法錯誤,后者主要會給出一些編碼建議,和對危險寫法的警告。
我之前用 syntastic 時就用了兩天就徹底刪除了,而開始用 ALE 后,一用上就停不下來,頭兩天我還一度覺得它就是個可有可無的點綴,但是第三天它幫我找出兩個潛在的 bug 的時候,我開始覺得沒白安裝,比如:
即便你使用各類 C/C++ IDE,也只能給實時你標(biāo)注一些編譯錯誤或者警告,而使用 ALE + cppcheck/gcc,連上面類似的潛在錯誤都能幫你自動找出來,并且當(dāng)你光標(biāo)移動過去時在最下面命令行提示你錯誤原因。
用上一段時間以后,讓你寫 C/C++ 有一種安心和舒適的感覺。
修改比較
這是個小功能,在側(cè)邊欄顯示一個修改狀態(tài),對比當(dāng)前文本和 git/svn 倉庫里的版本,在側(cè)邊欄顯示修改情況,以前 Vim 做不到實時顯示修改狀態(tài),如今推薦使用 vim-signify 來實時顯示修改狀態(tài),它比 gitgutter 強,除了 git 外還支持 svn/mercurial/cvs 等十多種主流版本管理系統(tǒng)。
沒注意到它時,你可能覺得它不存在,當(dāng)你有時真的看上兩眼時,你會發(fā)現(xiàn)這個功能很貼心。最新版 signify 還有一個命令`:SignifyDiff`,可以左右分屏對比提交前后記錄,比你命令行 svn/git diff 半天直觀多了。并且對我這種同時工作在 subversion 和 git 環(huán)境下的情況契合的比較好。
Signify 和前面的 ALE 都會在側(cè)邊欄顯示一些標(biāo)記,默認側(cè)邊欄會自動隱藏,有內(nèi)容才會顯示,不喜歡側(cè)邊欄時有時無的行為可設(shè)置強制顯示側(cè)邊欄:“set signcolumn=yes” 。
文本對象
相信大家用 Vim 進行編輯時都很喜歡文本對象這個概念,diw 刪除光標(biāo)所在單詞,ciw 改寫單詞,vip 選中段落等,ci“/ci( 改寫引號/括號中的內(nèi)容。而編寫 C/C++ 代碼時我推薦大家補充幾個十分有用的文本對象,可以使用 textobj-user 全家桶:
Plug ‘kana/vim-textobj-user’Plug ‘kana/vim-textobj-indent’Plug ‘kana/vim-textobj-syntax’Plug ‘kana/vim-textobj-function’, { ‘for’:[‘c’, ‘cpp’, ‘vim’, ‘java’] }Plug ‘sgur/vim-textobj-parameter’
它新定義的文本對象主要有:
i, 和 a, :參數(shù)對象,寫代碼一半在修改,現(xiàn)在可以用 di, 或 ci, 一次性刪除/改寫當(dāng)前參數(shù)
ii 和 ai :縮進對象,同一個縮進層次的代碼,可以用 vii 選中,dii / cii 刪除或改寫
if 和 af :函數(shù)對象,可以用 vif / dif / cif 來選中/刪除/改寫函數(shù)的內(nèi)容
最開始我不太想用額外的文本對象,一直在堅持 Vim 固有的幾個默認對象,生怕手練習(xí)慣了肌肉形成記憶到遠端沒有環(huán)境的 vim 下形成依賴改不過來,后來我慢慢發(fā)現(xiàn)挺有用的,比如改寫參數(shù),以前是比較麻煩的事情,這下流暢了很多,當(dāng)我發(fā)現(xiàn)自己編碼效率得到比較大的提升時,才發(fā)現(xiàn)習(xí)慣依賴不重要,行云流水才是真重要。以前看到過無數(shù)次都選擇性忽略的東西,有時候試試可能會有新的發(fā)現(xiàn)。
編輯輔助
大家都知道 color 文件定義了眾多不同語法元素的色彩,還有一個關(guān)鍵因素就是語法文件本身能否識別并標(biāo)記得出眾多不同的內(nèi)容來?語法文件對某些東西沒標(biāo)注,你 color 文件確定了顏色也沒用。因此 Vim 下面寫 C/C++ 代碼,語法高亮準(zhǔn)確豐富的話能讓你編碼的心情好很多,這里推薦 vim-cpp-enhanced-highlight 插件,提供比 Vim 自帶語法文件更好的 C/C++ 語法標(biāo)注,支持 標(biāo)準(zhǔn) 11/14/17。
前面編譯運行時需要頻繁的操作 quickfix 窗口,ale查錯時也需要快速再錯誤間跳轉(zhuǎn)(location list),就連文件比較也會用到快速跳轉(zhuǎn)到上/下一個差異處,unimpaired 插件幫你定義了一系列方括號開頭的快捷鍵,被稱為官方 Vim 中丟失的快捷鍵。
我們好些地方用到了 quickfix / location 窗口,你在 quickfix 中回車選中一條錯誤的話,默認會把你當(dāng)前窗口給切走,變成新文件,雖然按 CTRL+O 可以返回,但是如果不太喜歡這樣切走當(dāng)前文件的做法,可以設(shè)置 switchbuf,發(fā)現(xiàn)文件已在 Vim 中打開就跳過去,沒打開過就新建窗口/標(biāo)簽打開,具體見幫助。
Vim最爽的地方是把所有 ALT 鍵映射全部留給用戶了,盡量使用 Vim 的 ALT鍵映射,可以讓冗長的快捷鍵縮短很多,請參考:《Vim和終端軟件中支持ALT映射》。
代碼補全
傳統(tǒng)的 Vim 代碼補全基本以 omni 系列補全和符號補全為主,omni 補全系統(tǒng)是 Vim 自帶的針對不同文件類型編寫不同的補全函數(shù)的基礎(chǔ)語義補全系統(tǒng),搭配 neocomplete 可以很方便的對所有補全結(jié)果(omni補全/符號補全/字典補全)進行一個合成并且自動彈出補全框,雖然趕不上 IDE 的補全,但是已經(jīng)比大部分編輯器補全好用很多了。然而傳統(tǒng) Vim 補全還是有兩個邁不過去的坎:語義補全太弱,其次是補全分析無法再后臺運行,對大項目而言,某些復(fù)雜符號的補全會拖慢你的打字速度。
新一代的 Vim 補全系統(tǒng),YouCompleteMe 和 Deoplete,都支持異步補全和基于 clang 的語義補全,前者集成度高,后者擴展方便。對于 C/C++ 的話,我推薦 YCM,因為 deoplete 的 clang 補全插件不夠穩(wěn)定,太吃內(nèi)存,并且反應(yīng)比較慢,它的代碼量和代碼質(zhì)量和 YCM完全不是一個量級的。所以 C/C++ 的補全的話,請直接使用 YCM,沒有之一,而使用 YCM的話,需要進行一些簡單的調(diào)教:
let g:ycm_add_preview_to_completeopt = 0let g:ycm_show_diagnostics_ui = 0let g:ycm_server_log_level = ‘info’let g:ycm_min_num_identifier_candidate_chars = 2let g:ycm_collect_identifiers_from_comments_and_strings = 1let g:ycm_complete_in_strings=1let g:ycm_key_invoke_completion = ‘《c-z》’set completeopt=menu,menuonenoremap 《c-z》 《NOP》let g:ycm_semantic_triggers = { \ ‘c,cpp,python,java,go,erlang,perl’: [‘re!\w{2}’], \ ‘cs,lua,javascript’: [‘re!\w{2}’], \ }
這樣可以輸入兩個字符就自動彈出語義補全,不用等到輸入句號 。 或者 -》 才觸發(fā),同時關(guān)閉了預(yù)覽窗口和代碼診斷這些 YCM 花邊功能,保持清靜,對于原型預(yù)覽和診斷我們后面有更好的解決方法,YCM這兩項功能干擾太大。
上面這幾行配置具體每行的含義,可以見:《YouCompleteMe 中容易忽略的配置》。另外我在 Windows 下編譯了一個版本,你用 Windows 的話無需下載VS編譯,點擊 [這里]。我日常開發(fā)使用 YCM 輔助編寫 C/C++, Python 和 Go 代碼,基本能提供 IDE 級別的補全。
函數(shù)列表
不再建議使用 tagbar, 它會在你保存文件的時候以同步等待的方式運行 ctags (即便你沒有打開 tagbar),導(dǎo)致vim操作變卡,特別是 windows下開了反病毒軟件掃描的話,有時候保存文件卡5-6秒。2018年了,我們有更好的選擇,比如使用
@Yggdroot
開發(fā)的 LeaderF 來顯示函數(shù)列表:
全異步顯示文件函數(shù)列表,不用的時候不會占用你任何屏幕空間,將 ALT+P 綁定到 `:LeaderfFunction!` 這個命令上,按 ALT+P 就彈出當(dāng)前文件的函數(shù)列表,然后可以進行模糊匹配搜索,除了上下鍵移動選擇外,各種vim的跳轉(zhuǎn)和搜索命令都可以始用,回車跳轉(zhuǎn)然后關(guān)閉函數(shù)列表,除此之外按 i 進入模糊匹配,按TAB切換回列表選擇。
Leaderf 的函數(shù)功能屬于你想要它的時候它才會出來,不想要它的時候不會給你搗亂。
文件切換
文件/buffer模糊匹配快速切換的方式,比你打開一個對話框選擇文件便捷不少,過去我們常用的 CtrlP 可以光榮下崗了,如今有更多速度更快,匹配更精準(zhǔn)以及完美支持后臺運行方式的文件模糊匹配工具。我自己用的是上面提到的 LeaderF,除了提供函數(shù)列表外,還支持文件,MRU,Buffer名稱搜索,完美代替 CtrlP,使用時需要簡單調(diào)教下:
let g:Lf_ShortcutF = ‘《c-p》’let g:Lf_ShortcutB = ‘《m-n》’noremap 《c-n》 :LeaderfMru《cr》noremap 《m-p》 :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.30let g:Lf_CacheDirectory = expand(‘~/.vim/cache’)let g:Lf_ShowRelativePath = 0let g:Lf_HideHelp = 1let g:Lf_StlColorscheme = ‘powerline’let g:Lf_PreviewResult = {‘Function’:0, ‘BufTag’:0}
這里定義了 CTRL+P 在當(dāng)前項目目錄打開文件搜索,CTRL+N 打開 MRU搜索,搜索你最近打開的文件,這兩項是我用的最頻繁的功能。接著 ALT+P 打開函數(shù)搜索,ALT+N 打開 Buffer 搜索:
LeaderF 是目前匹配效率最高的,高過 CtrlP/Fzf 不少,敲更少的字母就能把文件找出來,同時搜索很迅速,使用 Python 后臺線程進行搜索匹配,還有一個 C模塊可以加速匹配性能,需要手工編譯下。LeaderF在模糊匹配模式下按 TAB 可以切換到匹配結(jié)果窗口用光標(biāo)或者 Vim 搜索命令進一步篩選,這是 CtrlP/Fzf 不具備的,更多方便的功能見它的官方文檔。
文件/MRU 模糊匹配對于熟悉的項目效率是最高的,但對于一個新的項目,通常我們都不知道它有些什么文件,那就談不上根據(jù)文件名匹配什么了,我們需要文件瀏覽功能。如果你喜歡把 Vim 偽裝成 NotePad++ 之類的,那你該繼續(xù)使用 NERDTree 進行文件瀏覽,但你想按照 Vim 的方式來,推薦閱讀這篇文章:
Oil and vinegar - split windows and project drawer
然后像我一樣開始使用 vim-dirvish,進行一些配置,比如當(dāng)前文檔按“-”號就能不切窗口的情況下在當(dāng)前窗口直接返回當(dāng)前文檔所在的目錄,再按一次減號就返回上一級目錄,按回車進入下一級目錄或者再當(dāng)前窗口打開光標(biāo)下的文件。進一步映射 “《tab》7” , “《tab》8” 和 “《tab》9” 分別用于在新的 split, vsplit 和新標(biāo)簽打開當(dāng)前文件所在目錄,這樣從一個文件如手,很容易找到和該文件相關(guān)的其他項目文件。
最后一個是 C/C++ 的頭文件/源文件快速切換功能,有現(xiàn)成的插件做這事情,比如 a.vim,我自己沒用,因為這事情太簡單,再我發(fā)現(xiàn) a.vim 前我就覺得需要這個功能,然后自己兩行 vim 腳本就搞定了。
參數(shù)提示
這個功能應(yīng)人而異,有人覺得不需要,有人覺得管用。寫 C/C++ 時函數(shù)忘了可以用上面的 YCM 補全,但很多時候是參數(shù)忘記了怎么辦?YCM的參數(shù)提示很蛋疼,要打開個 Preview 窗口,實在是太影響我的視線了,我自己寫過一些參數(shù)提醒功能,可以在最下面的命令行顯示當(dāng)前函數(shù)的參數(shù),不過這是基于 tags 的,搭配前面的 gutentags,對其他語言很管用,但對 C/C++ 我們還可以使用更好的 echodoc 插件:
它可以無縫的和前面的 YCM 搭配,用 libclang 給你生成參數(shù)提示,當(dāng)你用 YCM 的 tab 補全了一個函數(shù)名后,只要輸入左括號,下面命令行就會里面顯示出該函數(shù)的參數(shù)信息,隨著光標(biāo)移動,下面還會高亮出來你正在處于哪個參數(shù)位置。
唯一需要設(shè)置的是使用 “set noshowmode”關(guān)閉模式提示,就是底部 ---INSERT--- 那個,我們一般都用 airline / lightline 之類的顯示當(dāng)前模式了,所以默認模式提示可以關(guān)閉,INSERT 模式下的命令行,完全留給 echodoc 顯示參數(shù)使用。
-
Linux
+關(guān)注
關(guān)注
87文章
11212瀏覽量
208724 -
C語言
+關(guān)注
關(guān)注
180文章
7595瀏覽量
135894 -
C++
+關(guān)注
關(guān)注
21文章
2102瀏覽量
73453
發(fā)布評論請先 登錄
相關(guān)推薦
評論