vimにPythonコーディング環境を整える
研究室で、新しいMacを譲り受けた。 色々とセットアップしたついでに、Vimもちょっと凝りたくなったので弄ってみたら、便利すぎて素のvimでコーディングできなくなった。。。
色々と四苦八苦して導入したので、綺麗にはまとめられないのだけれど、知見を残しておく。
環境
最終的な.vimrc
" ------------------------------------------------------------------------------ "dein settings " ------------------------------------------------------------------------------ if !&compatible set nocompatible endif "Vim起動完了時にインストール augroup PluginInstall autocmd! autocmd VimEnter * if dein#check_install() | call dein#install() | endif augroup END "各プラグインをインストールするディレクトリ let s:plugin_dir = expand('~/.vim/bundle') "dein.vimをインストールするディレクトリをランタイムパスへ追加 let s:dein_dir = s:plugin_dir . '/repos/github.com/Shougo/dein.vim' execute 'set runtimepath+=' . s:dein_dir "プラグイン読み込み&キャッシュ作成 if dein#load_state(s:plugin_dir) call dein#begin(s:plugin_dir) "インストールするプラグイン call dein#add(s:dein_dir) call dein#add('Shougo/deoplete.nvim', {'on_i': 1}) let g:deoplete#enable_at_startup = 1 if !has('nvim') call dein#add('roxma/nvim-yarp') call dein#add('roxma/vim-hug-neovim-rpc') endif call dein#add('Shougo/neosnippet.vim', {'on_i' : 1, 'on_ft' : 'snippet', 'depends' : 'neosnippet-snippets'}) "code snippet; 簡単に言うと定型構文をすばやく挿入できる機能 call dein#add('Shougo/neosnippet-snippets') call dein#add('vim-syntastic/syntastic') call dein#add('Vimjas/vim-python-pep8-indent', {'on_ft' : 'python'}) call dein#end() call dein#save_state() endif filetype plugin indent on syntax enable "不足プラグインの自動インストール if dein#check_install() call dein#install() endif "disabledされてるpluginを、削除 ":call dein#recache_runtimepath() "すること。 call map(dein#check_clean(), "delete(v:val, 'rf')") call dein#recache_runtimepath() highlight Normal ctermbg=none "vimの背景色をターミナルの背景色と揃える set backspace=indent,eol,start "バックスペースキーでいろいろ消せるようにする " ------------------------------------------------------------------------------ "見た目系 " ------------------------------------------------------------------------------ set number "行番号 set ruler "ルーラを表示 set hlsearch "検索時にハイライト set title "titleを表示 colorscheme iceberg "colorschemeを設定 set list "不可視文字の可視化 set listchars=tab:»-,trail:-,extends:»,precedes:«,nbsp:%,eol:↲ set wrap set textwidth=0 "折り返しなし set colorcolumn=80 "80文字の場所にハイライト set showmatch "一致するカッコを一瞬ハイライト set matchtime=2 set cursorline "cursorの行列をハイライト set cursorcolumn " ------------------------------------------------------------------------------ "syntasticの設定 " ------------------------------------------------------------------------------ if dein#is_sourced('syntastic') set statusline+=%#warningmsg# set statusline+=%{SyntasticStatuslineFlag()} set statusline+=%* let g:syntastic_always_populate_loc_list = 1 let g:syntastic_auto_loc_list = 1 let g:syntastic_check_on_open = 1 let g:syntastic_check_on_wq = 0 let g:syntastic_mode_map = { 'mode': 'active', \ 'active_filetypes': ['vim', 'python', 'html'], \ 'passive_filetypes': [] } let g:syntastic_python_checkers = ["flake8"] let g:syntastic_error_symbol='✗' let g:syntastic_style_error_symbol = '✗' let g:syntastic_warning_symbol = '⚠' let g:syntastic_style_warning_symbol = '⚠' endif " ------------------------------------------------------------------------------ "neosnipetの設定 " ------------------------------------------------------------------------------ " Plugin key-mappings. " Note: It must be "imap" and "smap". It uses <Plug> mappings. imap <C-k> <Plug>(neosnippet_expand_or_jump) smap <C-k> <Plug>(neosnippet_expand_or_jump) xmap <C-k> <Plug>(neosnippet_expand_target) " SuperTab like snippets behavior. " Note: It must be "imap" and "smap". It uses <Plug> mappings. imap <expr><TAB> \ pumvisible() ? "\<C-n>" : \ neosnippet#expandable_or_jumpable() ? \ "\<Plug>(neosnippet_expand_or_jump)" : "\<TAB>" "TABで選択 imap <expr><CR> \ neosnippet#expandable() ? \ "\<Plug>(neosnippet_expand_or_jump)" : \ pumvisible() ? "<C-y>" : "<CR>" "ENTERで決定 " For conceal markers. if has('conceal') set conceallevel=2 concealcursor=niv endif "set snippet file dir let g:neosnippet#snippets_directory='~/.vim/bundle/neosnippet-snippets/snippets/,~/.vim/snippets'
手順(というか七転八倒記録)
プラグインマネージャdein.vim
を使ってみようと思い立った
「プラグインマネージャをわざわざ導入する必要はない」といった意見も散見するけれど、入れてみた感想としては「プラグインのインストール&アンインストールがめっちゃ楽になる」ので入れておいて損はないと思う。
プラグインマネージャには色々あるのだけれど、せっかくなら日本で最近シェアの広そうなdein.vim
に挑戦してみることにした。
Vimを最新バージョンにしようとしたが、--with-lua
できなかった。けどなんとかなった。
最新のdein.vim
を使うには、Vim 8.0以上が必要になる。
公式にも、If you use Vim 7.4, please use dein.vim ver.1.5 instead.
と書いてあるし、実際Vim7.4に導入しようとしたらエラーを吐かれた。
したがって、まずVim
自体のバージョンを確認し、必要とあればアップデートを行う必要がある。
私の環境はmacなので、Homebrew
でアップデートを行った。
lua
やPython3
オプションが+
になっている必要があるので--with-lua
するべし、といった情報が上がっていて、素直に--with-lua --with-python3
したのだが、エラーが発生した。
こちらなどを参考にbrew doctor
してみたりしたが、どうも解決しなかった。
結局、lua
は諦めてバージョンだけアップしようと
brew uninstall vim brew install vim
したら、オプション指定をしなかったのに、lua
もpython3
も+
付いている最新版のvimが入ってくれた。
解せぬ。
(install->uninstallじゃなくて、brew reinstall
だったかもしれない...)
dein.vimを手動でインストールした
公式のReadmeを参考に、dein.vim
をインストールした。
様々な参考サイトで、.vimrc
に「dein.vim
がまだ入っていなければ最初にgit clone
する」という処理まで書いていたが、それをするとインストールログが表示されなくてwarning等を見逃すからなのか、はたまた別の問題があったのか、うまくいかなかった。
そんなわけで、最初のインストールはReadmeに倣って下記の3コマンドを叩いた。
インストールディレクトリについては、~/.cache/dein
にしたり~/.vim.bundles
にしたり、、といった様々な流派が存在するようだけれど、私は一番参考になったサイト(Vimプラグインの管理にdein.vimを使う - yuhei.kagaya)に則って~/.vim/bundle
にした。
mkdir ~/.vim/bundle curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh sh ./installer.sh ~/.vim/bundle
dein.vimの設定を書く
.vimrc
にdein.vimの設定を書く。必要最低限の設定は、インストール時に表示されるので、それをコピペすれば良い親切設計になっている。
私も基本的にはそれをそのまま使わせてもらった。違いは、プラグインの削除に関する最後の3行だけだと思う。
" ------------------------------------------------------------------------------ "dein settings " ------------------------------------------------------------------------------ if !&compatible set nocompatible endif "Vim起動完了時にインストール augroup PluginInstall autocmd! autocmd VimEnter * if dein#check_install() | call dein#install() | endif augroup END "各プラグインをインストールするディレクトリ let s:plugin_dir = expand('~/.vim/bundle') "dein.vimをインストールするディレクトリをランタイムパスへ追加 let s:dein_dir = s:plugin_dir . '/repos/github.com/Shougo/dein.vim' execute 'set runtimepath+=' . s:dein_dir "プラグイン読み込み&キャッシュ作成 if dein#load_state(s:plugin_dir) call dein#begin(s:plugin_dir) "インストールするプラグイン call dein#add(s:dein_dir) call dein#end() call dein#save_state() endif filetype plugin indent on syntax enable "不足プラグインの自動インストール if dein#check_install() call dein#install() endif "disabledされてるpluginを、削除 call map(dein#check_clean(), "delete(v:val, 'rf')") call dein#recache_runtimepath()
Pythonソースコードの自動補完と静的解析ができるjedi-vim
を入れたかった。動かせなかった。
こちら(jedi-vim を導入してVimでPythonコードの補完をさせる - A little bit of everything)の記事を参考に、jedi-vim
を入れた。
:help jedi-vim
でjedi-vim
が入っていることは確かめられたのだが、補完のための.
を押すと-- オムニ補完 (^O^N^P) パターンは見つかりませんでした
と出てきて、正常に動作しなかった。
このような状況は幾件か報告されていて、例えばここなどを参考にvimのpythonのバージョンとosのpythonのバージョンやパスを確かめてみたりしたのだけれど、結局原因は見つけられなかった。
そんなわけで、今回はjedi-vim
を見送ることにして、自動補完と静的解析を別々に行う他のツールを試すことにした。
自動補完のためのdeoplete.nvim
を導入
自動補完にも、neocomplete
やneocomplcache
など、色々なものがあるらしい。
最初はよく名を見るneocomplete
をインストールしようとしたのだけれど、どうもうまく動作しなかったので他の手段を模索した。
調べていくと、neocomplete
はdein
を作ったShougoさんが手がけたツールらしいのだけれど、どうもメンテナンスは現在行われていないらしく、新たに作られたのがdeoplete
という自動補完ツールらしいと分かった。
そんなわけで、今回はdeoplete.nvim
を使ってみることにした。
導入方法は公式のReadmeを参考にした。dein
での導入方法と、併せて使いたいツールが載っている。
上記のインストールするプラグイン
のところに下記を記載して、vimを再度開くだけで導入完了。
call dein#add('Shougo/deoplete.nvim', {'on_i': 1}) let g:deoplete#enable_at_startup = 1 if !has('nvim') call dein#add('roxma/nvim-yarp') call dein#add('roxma/vim-hug-neovim-rpc') endif
neosnippet.vim
も入れたら、コード補完が更に簡単になった
スニペットとは繰り返し登場するコードの断片、またはそれをすぐに呼び出せるように管理するエディタの機能のことです。自分がよく使用する記述をスニペットにしておけばいちいち検索したり、昔書いたソースを探ってみたりすることなく、使いたい時に正確な記述をサッと呼び出して使うことができます。(一度書いたコードは二度と探さない!スニペットを究めて快適コーディング!【HTML, CSS, JavaScript】 | WebNAUT)
折角deoplete
を入れたので、同じShougoさん作のneosnippet.vim
も入れてみた。
まず、プラグインインストールのdeoplete
関連の下のところに下記を書いてインストールする。
call dein#add('Shougo/neosnippet.vim', {'on_i' : 1, 'on_ft' : 'snippet', 'depends' : 'neosnippet-snippets'}) "code snippet; 簡単に言うと定型構文をすばやく挿入できる機能 call dein#add('Shougo/neosnippet-snippets')
続いて、TABで補完対象を選択し、ENTERで決定できるように、dein
関係の設定の下に下記を書く。
" ------------------------------------------------------------------------------ "neosnipetの設定 " ------------------------------------------------------------------------------ " Plugin key-mappings. " Note: It must be "imap" and "smap". It uses <Plug> mappings. imap <C-k> <Plug>(neosnippet_expand_or_jump) smap <C-k> <Plug>(neosnippet_expand_or_jump) xmap <C-k> <Plug>(neosnippet_expand_target) " SuperTab like snippets behavior. " Note: It must be "imap" and "smap". It uses <Plug> mappings. imap <expr><TAB> \ pumvisible() ? "\<C-n>" : \ neosnippet#expandable_or_jumpable() ? \ "\<Plug>(neosnippet_expand_or_jump)" : "\<TAB>" "TABで選択 imap <expr><CR> \ neosnippet#expandable() ? \ "\<Plug>(neosnippet_expand_or_jump)" : \ pumvisible() ? "<C-y>" : "<CR>" "ENTERで決定 " For conceal markers. if has('conceal') set conceallevel=2 concealcursor=niv endif "set snippet file dir let g:neosnippet#snippets_directory='~/.vim/bundle/neosnippet-snippets/snippets/,~/.vim/snippets'
この設定をして初めて、私のトリアタマでもneosnippetの恩恵が受けられるようになった。笑
静的文法解析のためのSyntastic
とflake8
自分のコードがPEP8に準拠できてるのかをチェックするために、flake8
とSyntastic
をインストールした。
flake8
はpip install
しておく。
pip3 install flake8
あとは、プラグインインストールのところに以下を書いて、vim再起動でインストール。
call dein#add('vim-syntastic/syntastic')
続いて、Syntasticの細かい設定をdein関係の設定の後に追記。
解析結果をどう表示するのか?関係が記述されているのかな。
基本的な設定は、SyntasticのReadmeに載っているのでそのまま書けばいい。Pythonの構文解析のときだけflake8
を使うように変更してある。
" ------------------------------------------------------------------------------ "syntasticの設定 " ------------------------------------------------------------------------------ if dein#is_sourced('syntastic') set statusline+=%#warningmsg# set statusline+=%{SyntasticStatuslineFlag()} set statusline+=%* let g:syntastic_always_populate_loc_list = 1 let g:syntastic_auto_loc_list = 1 let g:syntastic_check_on_open = 1 let g:syntastic_check_on_wq = 0 let g:syntastic_mode_map = { 'mode': 'active', \ 'active_filetypes': ['vim', 'python', 'html'], \ 'passive_filetypes': [] } let g:syntastic_python_checkers = ["flake8"] let g:syntastic_error_symbol='✗' let g:syntastic_style_error_symbol = '✗' let g:syntastic_warning_symbol = '⚠' let g:syntastic_style_warning_symbol = '⚠' endif
PEP8準拠のインデントを自動挿入してくれるvim-python-pep8-indent
は文の途中で折り返すときに便利
入れてみて意外と便利だったのはvim-python-pep8-indent
。PEP8的に、1行80文字でコーディングしようとすると、どうしても折り返しが必要になる。そんなとき、自分で考えなくても適切なインデントを追加してくれるこのプラグインにはとても助けられている。
プラグインインストールのところに以下を書くだけ。
call dein#add('Vimjas/vim-python-pep8-indent', {'on_ft' : 'python'})
インデントを可視化してくれるvim-indent-guides
を入れたかった。動かなかった。
可視化してくれるときもあるけど、概ね可視化してくれない、というよくわからない状況になった。
ちなみに、インストール部分には下記を書き、
call dein#add('nathanaelkane/vim-indent-guides', {'lazy' : 1}) let g:indent_guides_enable_on_vim_startup = 1
詳細設定には以下を設定した。
" ------------------------------------------------------------------------------ "vim-indent-guidesの設定 " ------------------------------------------------------------------------------ let g:indent_guides_auto_colors=0 autocmd VimEnter,Colorscheme * :hi IndentGuidesOdd ctermbg=black autocmd VimEnter,Colorscheme * :hi IndentGuidesEven ctermbg=darkgrey let g:indent_guides_exclude_filetypes = ['help', 'nerdtree', 'tagbar'] let g:indent_guides_start_level = 2 let g:indent_guides_guide_size = 1
結局、動かない原因はわからなかった。
カーソル位置のハイライトがあるし、インデントがおかしいときはSyntastic
が教えてくれるから、今回は諦めてしまった。
感想
使い始めてみると驚くほど便利で、すぐに素のvim
が使えなくなってしまった。。。
自分にあまり権限が与えら得ていない環境とかだと、今回インストールしたような新しめのプラグインを導入することができなくてギャップに苦しむことになる(そのときの妥協案環境の話もまた今度メモしたい)のだけれど、それを鑑みてもやっぱり上記のプラグインから得られる恩恵は大きくて、vim
への愛着はとても増したと思う。
それから、今回七転八倒していく中で、沢山の人達の無償の貢献がvim
界隈を支えているのだということに気づいた。自分もいつか何かのかたちで貢献できればなと思った。