天天看點

Vim 自動補全插件 YouCompleteMe 安裝與配置 本文系轉載文章,原文連結 http://howiefh.github.io/2015/05/22/vim-install-youcompleteme-plugin/

本文系轉載文章,原文連結 http://howiefh.github.io/2015/05/22/vim-install-youcompleteme-plugin/

Contents

  1. 1. 概述
  2. 2. 安裝
    1. 2.1. 完全安裝
    2. 2.2. Ubuntu Linux X64 超快安裝
  3. 3. 配置
  4. 4. YCM & Eclim

概述

對于代碼自動補全,之前一直使用的是Shougo/neocomplcache和Shougo/neosnippet。早就聽說過YouCompleteMe的大名,一直想嘗試一下YCM,但是還是拖到了現在。YCM和其它Vim插件的安裝有些不同,可能需要折騰一下。之是以安裝稍微會麻煩些,是因為YCM 後端調用 libclang(以擷取AST,當然還有其他語言的語義分析庫)、前端由 C++ 開發(以提升補全效率)、外層由 python 封裝(以成為 vim 插件),它可能是安裝最複雜的 vim 插件了。YCM是Client-sever架構的,Vim這部分的YCM隻是很小的一個用戶端,與具有大量邏輯和功能的ycmd HTTP+JSON互動。server在你開啟或關閉Vim是自動開啟或關閉。

其它自動補全的插件基本上是基于文本的,也就是說它們基本上是使用正則去猜。差別于其它Vim的自動補全插件,YCM基于語義引擎(比如C家族的libclang)提供了語義補全,是通過分析源檔案,經過文法分析之後進行補全。對于C家族的語言這種基于語義的自動補全依賴于clang/llvm,其他語言 ,會調用vim設定的omnifunc來比對,可以檢視github

  • Java/Ruby eclim
  • Python Jedi
  • Go Gocode
  • C# OmniSharp
  • JavaScript Tern for Vim

YCM不是基于字首補全的,而是子序列,是以輸入 abc 可以補全 xaybgc,它對于大小寫的補全也非常智能。對于C家族的語言和Python支援跳轉到定義處。此外還可以對檔案路徑進行補全,和ultisnips也很好結合。

安裝

完全安裝

如果用Vundle更新YCM,yum_support_lib庫API改變了,YCM會提醒你重新編譯它。

  1. 確定Vim版本至少是7.3.584,并且支援python2腳本。

    在Vim中輸入

    :version

    可以檢視版本。如果版本已經高于7.4了,那麼OK。版本是7.3。那麼繼續往下看,看到

    包含版本:1-Z

    ,如果Z小于584就需要重裝了。Ubuntu的話可以通過PPA安裝高版本的。否則就要從源碼編譯安裝了。

    檢視是否支援python2:進入vim,指令:echo has(‘python’),輸出為1,則表示支援。如果為0,則需要重新編譯安裝vim,在編譯時添加python支援。

  2. 通過Vundle安裝YCM,在你的vimrc中添加

    Plugin 'Valloric/YouCompleteMe'

    ,然後執行

    :PluginInstall

  3. 如果不需要對C家族的語言進行語義補全支援,則跳過這一步。

    下載下傳最新版的libclang。Clang是一個開源編譯器,能夠編譯C/C++/Objective-C/Objective-C++。Clang提供的libclang庫是用于驅動YCM對這些語言的語義補全支援。YCM需要版本至少為3.6的libclang,但是理論上3.2+版本也行。也可以使用系統libclang,如果确定是3.3版本或者更高。推薦下載下傳官網的二進制檔案。確定選對适合自己系統的包。

  4. 編譯YCM需要的ycm_support_libs庫。YCM的C++引擎通過這些庫來擷取更快的補全速度。

    需要cmake,如果未安裝,安裝之:

    sudo apt-get install build-essential cmake

    (也可以下載下傳安裝http://www.cmake.org/cmake/resources/software.html)。確定python頭檔案已安裝:

    sudo apt-get install python-dev

    。假設你已經通過Vundle裝好YCM了,那麼它應該位于

    ~/.vim/bundle/YouCompleteMe

    。我們建立一個目錄用來放置編譯檔案,并切換到此目錄下

    cd ~;mkdir ycm_build;cd ycm_build;

    下一步生成makefile,這一步很重要,有點複雜。
    • 如果不需要C族語言的語義支援,在ycm_build目錄下執行:

      cmake -G "Unix Makefiles" . ~/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp

    • 如果需要C族語言的語義支援,還得分幾種情況:
      • 假如你從llvm的官網下載下傳了LLVM+Clang,然後解壓到:~/ycm_temp/llvm_root_dir (該目錄下有 bin, lib, include 等檔案夾),然後執行:

        cmake -G "Unix Makefiles" -DPATH_TO_LLVM_ROOT=~/ycm_temp/llvm_root_dir . ~/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp

      • 如果想用系統的libclang:

        cmake -G "Unix Makefiles" -DUSE_SYSTEM_LIBCUnix Makefiles" -DEXTERNAL_LIBCLANG_PATH=/path/to/libclang.so . ~/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp

        。/path/to/libclang.so這部分填入你自己的路徑。

        makefiles生成後執行:

        make ycm_support_libs

我是從llvm網站下載下傳的二進制檔案,安裝的,安裝過程中也沒遇到什麼問題。

Ubuntu Linux X64 超快安裝

最好還是完整安裝,這種快速安裝未必适合所有人。安裝之前,同樣也要确定滿足以上所述的vim版本、python支援等條件。和上面一樣使用Vundle安裝YCM,安裝CMake和python頭檔案。

編譯YCM,如果需要對C-family的語義支援:

1
2
      
cd ~/.vim/bundle/YouCompleteMe
./install.sh --clang-completer
      

如果不需要對C-family的語義支援:

1
2
      
cd ~/.vim/bundle/YouCompleteMe
./install.sh
      

如果需要支援C#,添加 

--omnisharp-complete

。如果需要支援Go添加

--gocode-completer

配置

YCM使用TAB鍵接受補全,一直按TAB則會循環所有的比對補全項。shift+TAB則會反向循環。注意:如果使用控制台Vim(非GVim或MacVim等),控制台不會将shift+Tab傳遞給Vim,是以會無反應,需要重新映射按鍵。此外,如果同時使用ultisnaps,可能會有沖突,需要進行一些設定。可以使用Ctrl+Space來觸發補全,不過會和輸入法沖突,也需要設定。

YCM會尋找目前打開的檔案的同級目錄下或上級目錄中的

ycm_extra_conf.py

這個檔案,找到後會加載為Python子產品,且隻加載一次。YCM調用該子產品中的FlagsForFile方法。該子產品必須提供帶有編譯目前檔案的必要資訊的這個方法。需要修改

.ycm_extra_conf.py

檔案中的flags部分,使用-isystem添加系統的頭檔案進行解析,使用-I添加第三方的頭檔案進行解析,在flags部分後添加如下内容:

1
2
      
'-isystem',
'/usr/include',
      

使用指令

:YcmDiags

可以打開location-list檢視警告和錯誤資訊。

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
      
set completeopt=longest,menu	"讓Vim的補全菜單行為與一般IDE一緻(參考VimTip1228)
autocmd InsertLeave * if pumvisible() == 0|pclose|endif	"離開插入模式後自動關閉預覽視窗
inoremap <expr> <CR>       pumvisible() ? "\<C-y>" : "\<CR>"	"回車即選中目前項
"上下左右鍵的行為 會顯示其他資訊
inoremap <expr> <Down>     pumvisible() ? "\<C-n>" : "\<Down>"
inoremap <expr> <Up>       pumvisible() ? "\<C-p>" : "\<Up>"
inoremap <expr> <PageDown> pumvisible() ? "\<PageDown>\<C-p>\<C-n>" : "\<PageDown>"
inoremap <expr> <PageUp>   pumvisible() ? "\<PageUp>\<C-p>\<C-n>" : "\<PageUp>"
" 跳轉到定義處
nnoremap <leader>jd :YcmCompleter GoToDefinitionElseDeclaration<CR>
nnoremap <F6> :YcmForceCompileAndDiagnostics<CR>	"force recomile with syntastic
" nnoremap <leader>lo :lopen<CR>	"open locationlist
" nnoremap <leader>lc :lclose<CR>	"close locationlist
inoremap <leader><leader> <C-x><C-o>

let g:ycm_global_ycm_extra_conf = '~/.vim/data/ycm/.ycm_extra_conf.py'
" 不顯示開啟vim時檢查ycm_extra_conf檔案的資訊  
let g:ycm_confirm_extra_conf=0
" 開啟基于tag的補全,可以在這之後添加需要的标簽路徑  
let g:ycm_collect_identifiers_from_tags_files=1
"注釋和字元串中的文字也會被收入補全
let g:ycm_collect_identifiers_from_comments_and_strings = 0
" 輸入第2個字元開始補全
let g:ycm_min_num_of_chars_for_completion=2
" 禁止緩存比對項,每次都重新生成比對項
let g:ycm_cache_omnifunc=0
" 開啟語義補全
let g:ycm_seed_identifiers_with_syntax=1	
"在注釋輸入中也能補全
let g:ycm_complete_in_comments = 1
"在字元串輸入中也能補全
let g:ycm_complete_in_strings = 1
" 設定在下面幾種格式的檔案上屏蔽ycm
let g:ycm_filetype_blacklist = {
      \ 'tagbar' : 1,
      \ 'nerdtree' : 1,
      \}
"youcompleteme  預設tab  s-tab 和 ultisnips 沖突
let g:ycm_key_list_select_completion = ['<Down>']
let g:ycm_key_list_previous_completion = ['<Up>']
" 修改對C函數的補全快捷鍵,預設是CTRL + space,修改為ALT + ;
let g:ycm_key_invoke_completion = '<M-;>'

" SirVer/ultisnips 代碼片斷
" Trigger configuration. Do not use <tab> if you use https://github.com/Valloric/YouCompleteMe.
let g:UltiSnipsExpandTrigger="<tab>"
let g:UltiSnipsJumpForwardTrigger="<tab>"
let g:UltiSnipsJumpBackwardTrigger="<s-tab>"
let g:UltiSnipsListSnippets="<c-e>"
"定義存放代碼片段的檔案夾,使用自定義和預設的,将會的到全局,有沖突的會提示
let g:UltiSnipsSnippetDirectories=["bundle/vim-snippets/UltiSnips"]

" 參考https://github.com/Valloric/YouCompleteMe/issues/36#issuecomment-62941322
" 解決ultisnips和ycm tab沖突,如果不使用下面的辦法解決可以參考
" https://github.com/Valloric/YouCompleteMe/issues/36#issuecomment-63205056的配置
" begin
" let g:ycm_key_list_select_completion=['<C-n>', '<Down>']
" let g:ycm_key_list_previous_completion=['<C-p>', '<Up>']
" let g:UltiSnipsExpandTrigger="<Tab>"
" let g:UltiSnipsJumpForwardTrigger="<Tab>"                                           
" let g:UltiSnipsJumpBackwardTrigger="<S-Tab>"
" end
" UltiSnips completion function that tries to expand a snippet. If there's no
" snippet for expanding, it checks for completion window and if it's
" shown, selects first element. If there's no completion window it tries to
" jump to next placeholder. If there's no placeholder it just returns TAB key 
function! g:UltiSnips_Complete()
    call UltiSnips#ExpandSnippet()
    if g:ulti_expand_res == 0
        if pumvisible()
            return "\<C-n>"
        else
            call UltiSnips#JumpForwards()
            if g:ulti_jump_forwards_res == 0
               return "\<TAB>"
            endif
        endif
    endif
    return ""
endfunction

au BufEnter * exec "inoremap <silent> " . g:UltiSnipsExpandTrigger . " <C-R>=g:UltiSnips_Complete()<cr>"

" Expand snippet or return
let g:ulti_expand_res = 1
function! Ulti_ExpandOrEnter()
    call UltiSnips#ExpandSnippet()
    if g:ulti_expand_res
        return ''
    else
        return "\<return>"
endfunction

" Set <space> as primary trigger
inoremap <return> <C-R>=Ulti_ExpandOrEnter()<CR>
      

YCM & Eclim

YCM配合Eclim可以實作對Java代碼的自動提示,首先需要下載下傳Eclim,下載下傳好後執行

java -jar eclim_2.4.1.jar

,解除安裝的話,後面再加個參數

uninstaller

就行。按提示一步步安裝就好了,安裝好後首先要啟動eclimd,它存放在eclipse的根目錄下。

對不同的自動補全插件eclim都提供了配置方法,對于YCM我們隻需要在vimrc中添加一行

let g:EclimCompletionMethod = 'omnifunc'

就可以了。

打開vim執行

:ProjectCreate /path/to/project -n java

建立一個新的工程。這個工程的結構和eclipse類似。

:ProjectList

指令可以檢視工程清單。

這個插件很有意思,可以在eclipse中嵌入vim,又可以在vim中享受eclipse一樣的自動補全。對于Java來說,提供了一些以

Java

Project

New

Mvn

為字首的命名。可以輸入

:Java

按Tab鍵嘗試一下。不過,我覺得還是使用eclipse配合viPlugin插件更友善些。