Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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_done_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 has('win32')
    let cmd = 'tools\\update-dll-mingw'
  elseif has('win32unix') " for 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_done_update

最後はこれです。hook_post_update は各プラグインのインストール直後に実行されるものですが、hook_done_update はプラグイン全てがインストールされた後(正確には、Runtimepath updated: ... のメッセージが表示された後)に実行されます。call dein#update() の後に、自動的に設定を読み込み直す用途などに使えそうです。

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

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

~/.vim/vimrc
set runtimepath+=~/.vim
~/.vim/autoload/delphinus/init/vimproc.vim
function! delphinus#init#vimproc#hook_post_update() abort
  if has('win32')
    let cmd = 'tools\\update-dll-mingw'
  elseif has('win32unix') " for 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)に置かないといけません。 

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away