dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

[vim]python補完プラグイン「jedi-vim」を快適にする方法(jedi-vim+neocomplete)

vimpythonの開発を行う上で
jedi-vimというプラグインが非常に便利だという話はネットで頻繁に目にしますが、
自分の環境ではそれほど使い勝手が良くないなあーと思って色々調整してみました。

結果的に、その他の補完プラグインとして使っていたneocomplcacheneocompleteに移行し、
もろもろ設定を.vimrcに書いたら今までよりずっと使いやすくなりました。

以下、気に入らなかったポイントとその改善策を。

その1:補完の時に上に小さな画面が出てきて画面がずれる、動作がぎくしゃくする

自分の環境では、補完候補を選択すると画面の上部に勝手にポップアップが表示されます。

f:id:dackdive:20140813015311p:plain

これが、候補を切り替えるたびに別の内容が表示されるもんだから
いちいちウィンドウの高さが変わって画面がガタガタとずれ、見ていていいもんじゃありません。

また、そのせいか、「高速に動作する」はずのjedi-vimが遅かったり、補完ウィンドウが残ったままになったりと動作的にも不安定です。

解決策

こちらにありました。

vimでpython3を書く時のおすすめの補完設定 - k4zy no blog

.vimrcに以下を記述するだけでOKです。

" docstringは表示しない
autocmd FileType python setlocal completeopt-=preview

ポップアップはdocstringを表示しているらしいですね。

その2:補完の時に一番上の選択肢が自動的に選ばれる

これもツライです。補完候補が勝手に表示されるのはいいとして、
その中の最初の候補が選択された状態になります。

f:id:dackdive:20140813015523p:plain

そのため、特に補完使わずにタイプを続けたい時に不要な単語が勝手に挿入されちゃいます。

解決策

色々調べていると、neocompleteという補完プラグインと一緒に使っている場合は
設定により回避する必要がありそうだとわかりました。

  1. jedi-vimとneocomplete.vimを併用する際に行っておきたい設定 - kozo2's blog
  2. vimでpython3を書く時のおすすめの補完設定 - k4zy no blog

で、確認したところ自分が使っているプラグインneocomplcacheというもので、
どうやらその後継としてneocompleteが出ているとのこと。

ただ、根本的な原因は同じなのでは?と思い、
せっかくなのでneocomplcacheからneocompleteに乗り換え、
上の記事にある方法を試してみました。

はじめに、neocompleteの設定についてはGitHubに載ってるのをほぼそのままコピーしてこんな感じに。

"------------------------------------
" neocomplete.vim
"------------------------------------
"Note: This option must set it in .vimrc(_vimrc).  NOT IN .gvimrc(_gvimrc)!
" Disable AutoComplPop.
let g:acp_enableAtStartup = 0
" Use neocomplete.
let g:neocomplete#enable_at_startup = 1
" Use smartcase.
let g:neocomplete#enable_smart_case = 1
" Set minimum syntax keyword length.
let g:neocomplete#sources#syntax#min_keyword_length = 3
let g:neocomplete#lock_buffer_name_pattern = '\*ku\*'
" Plugin key-mappings.
inoremap <expr><C-g>     neocomplete#undo_completion()
inoremap <expr><C-l>     neocomplete#complete_common_string()

" Recommended key-mappings.
" <CR>: close popup and save indent.
inoremap <silent> <CR> <C-r>=<SID>my_cr_function()<CR>
function! s:my_cr_function()
  " return neocomplete#close_popup() . "\<CR>"
  " For no inserting <CR> key.
  return pumvisible() ? neocomplete#close_popup() : "\<CR>"
endfunction
" <TAB>: completion.
inoremap <expr><TAB>  pumvisible() ? "\<C-n>" : "\<TAB>"
" <C-h>, <BS>: close popup and delete backword char.
inoremap <expr><C-h> neocomplete#smart_close_popup()."\<C-h>"
inoremap <expr><BS> neocomplete#smart_close_popup()."\<C-h>"
inoremap <expr><C-y>  neocomplete#close_popup()
inoremap <expr><C-e>  neocomplete#cancel_popup()

" Close popup by <Space>.
inoremap <expr><Space> pumvisible() ? neocomplete#close_popup() : "\<Space>"

" autocmd FileType python setlocal omnifunc=pythoncomplete#Complete

--- 2014/09/06追記 ---
一番下の行はjedi-vimの補完を使うので不要ですね。コメントアウトしました。
--- 追記ここまで ---

そして肝心のjedi-vimとneocompleteの連携のための設定ですが、
.vimrcに以下を記述しました。

autocmd FileType python setlocal omnifunc=jedi#completions
let g:jedi#completions_enabled = 0
let g:jedi#auto_vim_configuration = 0

if !exists('g:neocomplete#force_omni_input_patterns')
        let g:neocomplete#force_omni_input_patterns = {}
endif

" let g:neocomplete#force_omni_input_patterns.python = '\%([^. \t]\.\|^\s*@\|^\s*from\s.\+import \|^\s*from \|^\s*import \)\w*'
let g:neocomplete#force_omni_input_patterns.python = '\h\w*\|[^. \t]\.\w*'

おおむね上にあげた1の記事にある通りでいいんですが、
2の記事にあるようにif !existsの条件文がないと

E121: 未定義の変数です: g:neocomplete#force_omni_input_patterns"

というエラーが出たのでそこだけ追記しました。

--- 2014/09/06追記 ---

let g:neocomplete#force_omni_input_patterns.python = '\%([^. \t]\.\|^\s*@\|^\s*from\s.\+import \|^\s*from \|^\s*import \)\w*'

だとimportとか書いてる時にEnterキーが効かなくなる(補完リストが消えない)ので、
次のように変更しました。

let g:neocomplete#force_omni_input_patterns.python = '\h\w*\|[^. \t]\.\w*'

--- 追記ここまで ---

そして設定後...

上にあげた問題点が2つとも解消されて、非常に使いやすくなりました!
速い!すごい!

f:id:dackdive:20140813021333p:plain

この、メソッドの引数とかまで表示してくれるのはありがたいですね。

リファレンス

vimでpython3を書く時のおすすめの補完設定 - k4zy no blog

jedi-vimとneocomplete.vimを併用する際に行っておきたい設定 - kozo2's blog

neocompleteを入れてみた作業ログ - Make 鮫 noise

neocomplcache -> neocompleteへの移行について(変数設定など)
neocomplete migration guide · Shougo/neocomplete.vim Wiki · GitHub