Vim のプラグインって作ってる最中は Vim 自体の動作も不安定になりがちだし、普段の環境と同じ環境で作ってるとなにかと弊害が起きがち。ちょっとした変更ならまだしも、大規模な変更は 1 度の作業で終わらないこともあるし、作業中断して別のことをやることになったりするとさらに面倒。
または、VCS でプラグインを管理したくて、プラグインごとにリポジトリを独立したいけど環境分けるのが面倒だとか。
というわけで私が普段やってる Vim プラグインの開発スタイルを晒してみようと思う。
設定
私の vimrc には最後の方に以下の記述がある。
" Load settings for each location. augroup vimrc-local autocmd! autocmd BufNewFile,BufReadPost * call s:vimrc_local(expand('<afile>:p:h')) augroup END function! s:vimrc_local(loc) let files = findfile('vimrc_local.vim', escape(a:loc, ' ') . ';', -1) for i in reverse(filter(files, 'filereadable(v:val)')) source `=i` endfor endfunction if g:loaded_vimrc == 0 call s:vimrc_local(getcwd()) endif
前半は Vim Hack #112 で紹介したものとまったく同じだが、その後に追加がある。
g:loaded_vimrc は単にリロードした際には実行しないようにするもので、vimrc の最後で 1 に設定される。
で、if の中身だけど、getcwd()、つまり Vim を起動したディレクトリと、その親ディレクトリにある vimrc_local.vim を読み込んでいる。
ディレクトリ構成
まず Vim プラグイン開発用のディレクトリを用意して、その下にサブディレクトリとして各プラグインのディレクトリを作っている。こんな感じ。
~/work/vim-plugins/ |-- quickrun | |-- autoload | |-- doc | `-- plugin |-- ref | |-- autoload | | |-- ku | | `-- ref | |-- doc | `-- plugin |-- visualstar | |-- doc | `-- plugin `-- vparsec |-- autoload |-- doc `-- sample
プラグインはこれで全部じゃないけど、雰囲気としてはこうなってる。
キモの部分
で、ここで言う ~/work/vim-plugins には以下のような vimrc_local.vim が置いてある。
if exists('s:loaded') finish endif let s:loaded = 1 let s:basename = expand('<sfile>:h:t') let s:dir = getcwd() if fnamemodify(s:dir, ':h:t') ==# s:basename let &rtp = s:dir . ',' . &rtp . ',' . s:dir . '/after' augroup vimrc-local-dev-plugin execute 'autocmd SourcePre */' . s:basename . '/*/plugin/*.vim' \ 'unlet! g:loaded_{expand("<afile>:p:r:s?.*/plugin/??:gs?[/\\\\]?_?")}' augroup END endif
色々やってたからごちゃごちゃしてしまった感があるが、2 番目の if は最初の行以外無視していい。
何をしているかというと、現在のディレクトリを 'runtimepath' に追加している。
ここで重要なのは、これが vimrc の段階、つまりプラグインがロードされる前に実行されるということ。これによって開発中のプラグインが先にロードされる。
つまりは各開発中のプラグインのディレクトリへ移動して Vim を立ち上げれば自動的に開発中のプラグインがロードされるということ。普段使ってるのは別に通常の 'runtimepath' に入ってるけど、多重ロード防止コードがあるので読み込まれることはない。
こうやって動くかどうかも怪しいバギーな状態のプラグインと普段使うプラグインを分離している。
以上
誰かの参考になれば幸いです。