[dein.vim] hook の便利な使い方

  • 126
    Like
  • 0
    Comment

dein.vim は NeoBundle に変わるプラグインマネージャです。詳しくはこちらの記事に書きました。

NeoBundle から dein.vim に乗り換えたら爆速だった話 - Qiita

プラグインのリストを TOML ファイルに書くとき、そこにプラグインの設定も一緒に入れてしまうといろいろ捗ります。

dein.vimによるプラグイン管理のマイベストプラクティス - Qiita

この記事ではこれに使われる hook 機能についてまとめてみました。

hook の種類

hook の名前 実行されるタイミング lazy OFF lazy ON
hook_add プラグインが dein.vim によって追加されたとき OK OK
hook_source プラグインが読み込まれる直前 NG OK
hook_post_source プラグインが読み込まれた直後 NG OK
hook_post_update プラグインが更新された直後 OK OK

以下、それぞれについて例を挙げて見ていきます。

hook_add

dein.vim によってプラグインが認識されたときに発火される hook です。non lazy な(Vim の起動と同時に読み込まれる)プラグインの場合、設定情報を置くにはこれを使うしかありません。

便利な用途としては、プラグインを起動するための mapping を書いたり、プラグインのための変数を設定したりします。

[[plugins]]
repo     = 'tpope/vim-capslock'
hook_add = 'imap <C-L> <Plug>CapsLockToggle'

[[plugins]]
repo     = 'elzr/vim-json'
hook_add = 'let g:vim_json_syntax_conceal = 0'

hook_source

プラグインを読み込む直前に実行されます。たとえばこんな感じ。

[[plugins]]
repo        = 'Shougo/echodoc.vim'
hook_source = 'let g:echodoc_enable_at_startup = 1'

この程度の分量なら hook_add と大して違いはない(あるいは vimrc に直接書くのと変わらない)ですが、本当に必要になるときまで設定を遅らせることができるので、Vim 起動時に環境を汚さないようになります。

hook_post_source

プラグインを読み込んだ直後に実行されます。hook_source と似てますが、プラグイン自体の機能が必要なときはこちらに設定しなければなりません。

[[plugins]]
repo    = 'osyo-manga/vim-watchdogs'
depends = [
  'vim-hier',
  'quickfixstatus',
  'shabadou.vim',
  'vim-quickrun',
]
# 追記参照 2016/05/09
on_event = ['FocusLost', 'CursorHold']
hook_add = '''
  let g:quickrun_config = get(g:, 'quickrun_config', {})
  let g:quickrun_config['watchdogs_checker/_'] = {'outputter/quickfix/open_cmd': ''}
  let g:quickrun_config['watchdogs_checker/jshint'] = {'cmdopt': '--config `/.jshintrc'}
'''
hook_post_source = '''
  call watchdogs#setup(g:quickrun_config)
'''

vim-watchdogs はファイル保存時などに非同期でコンパイルチェックをしてくれるプラグインです。依存関係の複雑なプラグインですので、on_event を使って Vim 起動後、非同期に読み込んでいます。

/* 追記ここから 2016/05/09 */

on_idle は deprecated になりました。該当部分のコードを見るとわかりますように、現在は単なる on_event へのエイリアスになっています。

/* 追記ここまで */

このプラグインは設定の最後に watchdogs#setup() を呼ぶ必要があるのですが、これは当然、プラグインを読み込んだ後でないと実行できません。こういうときに hook_post_source は便利です。

hook_post_update

vimproc.vimTern for Vim 等、インストール後にコンパイルや関連ツールのインストールが必要なプラグインがあります。dein.vim では、このようなとき build オプションが使えます。

[[plugins]]
repo  = 'Shougo/vimproc.vim'
build = 'make'

以前までこのオプションには OS 毎に別のコマンドを指定することが出来ましたがその機能がなくなってしまいました(このコメントで教えていただきました。thx!)。現在はこのような用途で hook_post_update を使うことが推奨されています

[[plugins]]
repo = 'Shougo/vimproc.vim'
hook_post_update = '''
  if dein#util#_is_windows()
    let cmd = 'tools\\update-dll-mingw'
  elseif dein#util#_is_cygwin()
    let cmd = 'make -f make_cygwin.mak'
  elseif executable('gmake')
    let cmd = 'gmake'
  else
    let cmd = 'make'
  endif
  let g:dein#plugin.build = cmd
'''

別にこの hook_post_update に限った話ではないのですが、全ての hook では g:dein#plugin を直接指定して設定を動的に書き換えることができます。1

設定が膨らんできたら……

便利な hook なのですが、ここに設定をたくさん載せていくと今度は TOML がカオスになってしまいます。これを避けるため、設定が複雑になってきたら関数に切り出すようにしました。2

~/.vim/vimrc
set runtimepath+=~/.vim
~/.vim/autoload/delphinus/init/vimproc.vim
function! delphinus#init#vimproc#hook_post_update() abort
  if dein#util#_is_windows()
    let cmd = 'tools\\update-dll-mingw'
  elseif dein#util#_is_cygwin()
    let cmd = 'make -f make_cygwin.mak'
  elseif executable('gmake')
    let cmd = 'gmake'
  else
    let cmd = 'make'
  endif
  let g:dein#plugin.build = cmd
endfunction
dein.toml
[[plugins]]
repo = 'Shougo/vimproc.vim'
hook_post_update = 'call delphinus#init#vimproc#hook_post_update()'

autoload 関数にすると、本当に必要になったときだけ、ファイルが読み込まれるようになるので CPU にもストレージにも優しいです。このようにすれば、見通しよくプラグインの管理ができると思います。


  1. これできたらいいなー、と思って、ここで要望したら爆速で実行していただけました!! 

  2. autoload 関数はあらゆるプラグインで使われています。関数の名前が被るとまずいので、プラグインに使われそうもない名前空間(ここでは僕のハンドル delphinus)に置かないといけません。