Life With Vim[2] 用Deoplete和cquery搭建代碼補(bǔ)全

使用Deoplete作為Vim的代碼補(bǔ)全

YouCompleteMe

從開始學(xué)習(xí)用Vim寫代碼起,我一直都是用的YouCompleteMe來進(jìn)行補(bǔ)全。因?yàn)榫W(wǎng)上一搜,至少中文資源里面關(guān)于Python和C的Vim補(bǔ)全插件就全是說YCM。

我對(duì)YCM的感覺,談不上壞,但也不是很好。

首先YCM用起來,至少在Mac上其實(shí)是很方便的:Vim-plug下載,進(jìn)目錄./install.py --clang-completer安裝玩,基本上就可以開始用了。頂天在修改一下ycm_extra_conf.py讓它自己去找include目錄和compile_commands.json就可以了。

但不滿的地方在于,這個(gè)插件有點(diǎn)大。這可能和它的架構(gòu)有關(guān)系:它作為一個(gè)Vim插件試圖去整合那些后端做靜態(tài)分析的庫(kù)。這導(dǎo)致它不管是橫向還是縱向發(fā)展都很緩慢:拓展語(yǔ)言和拓展功能的工作量都很大。

再有就是在Arch上總有點(diǎn)奇奇怪怪的問題。完全不是過去開箱即用的感覺。因?yàn)椴寮?,看文檔看的頭痛。雖然最后花了半小時(shí)是用上了,但一直問自己為什么不去用VScode。

Deoplete

Deoplete其實(shí)從功能上說,和YCM是一樣的。但它的實(shí)現(xiàn)方式就很討喜:就是一個(gè)前端的補(bǔ)全引擎而已,后端的東西能分離的都盡量分離出去。就能夠認(rèn)清自己只是一個(gè)前端插件來說,我就很喜歡。

因?yàn)檫@樣的分離,Deoplete從理論上來說,就沒有什么語(yǔ)言不支持的。因?yàn)樗梢宰远xcomplete source。在Completion Sources上列出專門支持的語(yǔ)句就不止20種。而且最重要的是它支持LanguageClient這個(gè)插件。

LanguageClient

幾周前,在Vim Subreddit上看到關(guān)于LSP(Language Server Protocol)的貼子后,就覺得這個(gè)點(diǎn)子好。因?yàn)楦鱾€(gè)語(yǔ)言的代碼分析庫(kù)紛繁復(fù)雜,只要LSP這個(gè)協(xié)議推廣開來,各語(yǔ)言各自實(shí)現(xiàn)一個(gè)支持LSP的language server統(tǒng)一調(diào)用接口,那么市面上所有的編輯器都可以享用到不妥協(xié)的語(yǔ)言服務(wù)了(重構(gòu)對(duì)于純編輯器就簡(jiǎn)單許多)。

于是我這兩天搜了一搜,果不其然Vim就已經(jīng)有了LanguageClient這個(gè)插件了。

LanguageClient其實(shí)就是一個(gè)中間件,存在的原因就是因?yàn)镹eovim/vim自帶的和第三方的補(bǔ)全引擎不支持LSP。LanuageClient在中間當(dāng)胖翻譯就是了。

Language Servers

因?yàn)楝F(xiàn)在主要寫C++,現(xiàn)在C/C++主要的LS就兩個(gè)一個(gè)是clangd一個(gè)是cquery。

clangd

  • 好處是它是clang自帶的。如果僅需要補(bǔ)全用它就夠了。
  • 壞處是功能實(shí)現(xiàn)的比較少,而且它沒辦法找到在./build目錄下的compile_commands.json,你必須軟鏈接到項(xiàng)目根目錄才行。

cquery就幾乎是個(gè)全功能的Language Server了。它支持:

  1. 代碼格式化; [clangd也可以]
  2. 跨文件重命名symbol;
  3. 定義跳轉(zhuǎn);
  4. 引用跳轉(zhuǎn);
  5. 枚舉引用列表;
  6. 文檔內(nèi)Symbol搜索;
  7. 工程內(nèi)Symbol搜索(包括各種頭文件);
  8. 快速定位Diagnostic位置;

我剛剛配置完進(jìn)去實(shí)際工程里面溜一圈,確實(shí)爽的多。越來越像IDE了。只有一個(gè)功能貌似用不了:implementation是沒法從頭文件跳去cpp文件的。但是呢,卻可以從reference列表跳轉(zhuǎn)(列表第一項(xiàng)),所以也不是什么問題了。

配置

其實(shí)Deoplete + LanguageClient + cquery,不知道是不是心里作用,雖然配置起來行數(shù)多了。但是比YCM好懂得多。

首先,安裝好neovim python clientcquery。如果是Arch,cquery就在AUR上,全自動(dòng)編譯。實(shí)在懶得編譯也可以上國(guó)內(nèi)的archlinuxcn源,里面之前是有cquery二進(jìn)制的。

然后下載那兩個(gè)插件,再加一個(gè)fzf。因?yàn)?code>languageClient的列表什么的都是用fzf做交互的。再者說,現(xiàn)在用linux誰(shuí)還不用fzf?下面是vim-plug部分:

Plug 'autozimu/LanguageClient-neovim', {
    \ 'branch': 'next',
    \ 'do': 'bash install.sh',
    \ }
Plug 'Shougo/deoplete.nvim', { 'do': ':UpdateRemotePlugins' }

下面配置Deoplete:

" 自啟動(dòng)
let g:deoplete#enable_at_startup = 1
" smart case不解釋
let g:deoplete#enable_smart_case = 1

" 用戶輸入至少兩個(gè)字符時(shí)再開始提示補(bǔ)全
call deoplete#custom#source('LanguageClient',
            \ 'min_pattern_length',
            \ 2)

" 字符串中不補(bǔ)全
call deoplete#custom#source('_',
            \ 'disabled_syntaxes', ['String']
            \ )

" 補(bǔ)全結(jié)束或離開插入模式時(shí),關(guān)閉預(yù)覽窗口
autocmd InsertLeave,CompleteDone * if pumvisible() == 0 | pclose | endif

" 為每個(gè)語(yǔ)言定義completion source
" 是的vim script和zsh script都有,這就是deoplete
call deoplete#custom#option('sources', {
            \ 'cpp': ['LanguageClient'],
            \ 'c': ['LanguageClient'],
            \ 'vim': ['vim'],
            \ 'zsh': ['zsh']
            \})

" 忽略一些沒意思的completion source。
let g:deoplete#ignore_sources = {}
let g:deoplete#ignore_sources._ = ['buffer', 'around']

再來配置LanguageClient

" abandoned的Buffer隱藏起來,這是vim的設(shè)置。
" 如果沒有這個(gè)設(shè)置,修改過的文件需要保存了才能換buffer
" 這會(huì)影響全局重命名,因?yàn)閂im提示保存因此打斷下一個(gè)文件的重命名。
set hidden
" 告訴LS那個(gè)文件夾才是project root,同時(shí)也告訴它c(diǎn)ompile_commands在哪里
let g:LanguageClient_rootMarkers = {
            \ 'cpp': ['compile_commands.json', 'build'],
            \ 'c': ['compile_commands.json', 'build']
            \ }
" 為語(yǔ)言指定Language server和server的參數(shù)
let g:LanguageClient_serverCommands = {
            \ 'cpp': ['cquery', '--log-file=/tmp/cq.log'],
            \ 'c': ['cquery', '--log-file=/tmp/cq.log'],
            \ }

" Server加一個(gè)參數(shù)就放在下列文件中
let g:LanguageClient_loadSettings = 1
let g:LanguageClient_settingsPath = '愛放哪里放哪里'
" 把Server的補(bǔ)全API提交給Vim
" 一般有deoplete就可以用了,加上一條以防萬(wàn)一。
set completefunc=LanguageClient#complete
" 把Server的格式化API提交給Vim
set formatexpr=LanguageClient_textDocument_rangeFormatting()

因?yàn)槟J(rèn)Deoplete的補(bǔ)全是ctrl-n下翻和ctrl-p上翻,如果喜歡tab還可以加上兩行:

inoremap <expr><tab> pumvisible() ? "\<c-n>" : "\<tab>"
inoremap <expr><S-tab> pumvisible() ? "\<c-p>" : "\<tab>"

最后在settings.json 里面寫下你的server的別的參數(shù):

{
    "initializationOptions": {
        "cacheDirectory": "/tmp/cquery"
    }
}

記得把路徑寫到上面的配置里面去。
記得裝fzf。

使用

寫的太多了,困了。自己看文檔吧。

Happy Vimming!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 編譯環(huán)境及源碼版本 cmake-3.12.0llvm-4.0.1vim-81 一. llvm-clang 編譯安裝...
    mingzhi618閱讀 5,487評(píng)論 0 1
  • macvim配置 最終效果如下: 系統(tǒng)環(huán)境 macos10.12.4 homebrew1.2.1 python3....
    Like_eb56閱讀 70,814評(píng)論 5 65
  • 真實(shí)有效的Vim配置記錄(macOS) 以前在Ubuntu里配置了兩次Vim,macOS中配置了一次,都沒有配置成...
    染微言閱讀 11,701評(píng)論 0 8
  • 工欲善其事,必先利其器,第一次從頭開始打造自己的vim,特記錄下流程~安裝插件有:bundle, YouCompl...
    tianxinheihei閱讀 2,077評(píng)論 0 4
  • 安裝依賴庫(kù)(支持Python 3、Lua、Ruby) sudo apt-get install libncurse...
    Cyfeng閱讀 2,289評(píng)論 0 2

友情鏈接更多精彩內(nèi)容