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

# はじめに
vim のプラグイン管理ではこれまで `NeoBundle` がデファクトだったけど、今後は [`dein.vim`](https://github.com/Shougo/dein.vim) を使えってことなので移行してます。
で `dein#add` で追加したプラグインの設定をどこでどう書くかを[色々試した](http://qiita.com/kawaz/items/5a882b864732cd483266)結果、TOML管理機能を使うのが一番よさげ、という結論に至ったので、こうしておくとよさそうという現時点での僕の設定を書いておきます。

# 設定例
`init.vim` (neovimじゃない場合は.vimrcと読み替えてOK） は最終的に↓こんな感じに凄くシンプルになった。

```vim:~/.config/nvim/init.vim
if !&compatible
  set nocompatible
endif

" reset augroup
augroup MyAutoCmd
  autocmd!
augroup END

" dein settings {{{
" dein自体の自動インストール
let s:cache_home = empty($XDG_CACHE_HOME) ? expand('~/.cache') : $XDG_CACHE_HOME
let s:dein_dir = s:cache_home . '/dein'
let s:dein_repo_dir = s:dein_dir . '/repos/github.com/Shougo/dein.vim'
if !isdirectory(s:dein_repo_dir)
  call system('git clone https://github.com/Shougo/dein.vim ' . shellescape(s:dein_repo_dir))
endif
let &runtimepath = s:dein_repo_dir .",". &runtimepath
" プラグイン読み込み＆キャッシュ作成
let s:toml_file = fnamemodify(expand('<sfile>'), ':h').'/dein.toml'
if dein#load_state(s:dein_dir)
  call dein#begin(s:dein_dir)
  call dein#load_toml(s:toml_file)
  call dein#end()
  call dein#save_state()
endif
" 不足プラグインの自動インストール
if has('vim_starting') && dein#check_install()
  call dein#install()
endif
" }}}

" プラグイン以外のその他設定が続く
" :
```

ここまでのポイント

- リモートのいろんな環境で自分用設定をcloneして使うことが多いので `XDG Base Directory Specification` 対応はちゃんとしておく。
    - `s:dein_dir` は `~/.cache/dein` 固定より `${XDG_CACHE_HOME:-~/.cache}/dein` が良い。
    - `init.vim` は `~/.config/nvim/init.vim` 固定より `${XDG_CONFIG_HOME:-~/.config}/nvim/init.vim` にあるつもりが良い。
- `dein.vim` 自体が無ければ自動インストールする（何でも自動化しとくのが楽よね）
- `dein#begin` は第2引数にTOMLパスを指定しなくても良くなったので[修正](http://qiita.com/kawaz/items/ee725f6214f91337b42b/revisions/32)しました。
- 落としてないプラグインが追加されていたら見つけたら自動インストール（自動化！自動化！）

で、プラグイン自体は `dein#load_toml` で指定した先のTOML形式で管理することになります。

```toml:~/.config/nvim/dein.toml　（ところでQiitaってtomlシンタックスが無いようなので対応して欲しいです→されるようになってた!）
[[plugins]]
repo = 'Shougo/dein.vim'

[[plugins]] # カーソル位置のコンテキストに合わせてftを切り替える
repo = 'osyo-manga/vim-precious'
depends = ['context_filetype.vim']

[[plugins]] # カーソル位置のコンテキストのftを判定するライブラリ
repo = 'Shougo/context_filetype.vim'

[[plugins]] # toml syntax
repo = 'cespare/vim-toml'
on_ft = 'toml'

[[plugins]] # カラースキーマ
repo = 'w0ng/vim-hybrid'
hook_add = '''
  set background=dark
  " colorscheme 設定は source 後に行う必要があるので VimEnter で行う。
  " 但し Colorscheme イベントの発生が抑制されないよう nented を付ける。
  au MyAutoCmd VimEnter * nested colorscheme hybrid
'''

# other plugins
# :
```

- `dein#add` は最近 `hook_add`/`hook_source`/`hook_post_source` オプションが追加されて add や source 時に行いたい処理が書けるようになったので活用する。
    - このオプションは特にTOML管理するときに威力を発揮する。このオプションはvimコマンドを文字列で渡すので `init.vim` 内でvimのコードとして書こうとするとエスケープやら改行の扱いやらが面倒であまり使い勝手が良いとは言えないが、逆にTOMLでは複数行表記が簡単なので気軽にvimスクリプトが書ける。正にtoml管理の為に追加されたオプションです。
    - `hook_*` オプション内では改行の認識や行頭コメントの利用も出来るようになっているのでTOML内では普通のvim感覚で書けて既存設定の移植も楽ちんです。
    - そしてTOML管理だとプラグインの利用宣言とその後処理が一箇所にまとめて書けるのも良い。vimで書く場合は `dein#add` は `dein#begin` ブロック内で行って、プラグイン個別の設定は `dein#end` 以降の `if dein#tap('xx') endif` ブロック内という離れた場所に書かざるをえなかったのが、TOML管理にすればそれが解消されます。
    - `on_ft` や `on_i` など `on_` で始まる系のオプションが書いてあると、そのプラグインは自動で遅延ロード(必要になった時点でsourceされる)対象になります。なお `on_*` 系オプションが無くても `lazy=1` で遅延ロードになる模様。
    - 遅延ロードされたプラグインが実際に読み込まれる際にはその前後で、`hook_souce` と `hook_post_source` オプションに指定したコマンドを実行させることが出来ます。



# `dein.vim` でtoml管理する際のポイント

## colorscheme は VimEnter に nested 指定で遅延設定する

```toml
[[plugins]] # カラースキーマ
repo = 'w0ng/vim-hybrid'
hook_add = '''
  set background=dark
  " colorscheme 設定は source 後に行う必要があるので VimEnter で行う。
  " 但し Colorscheme イベントの発生が抑制されないよう nented を付ける。
  au MyAutoCmd VimEnter * nested colorscheme hybrid
'''
```

何も考えずに `hook_add` で `colorscheme hybrid` ってやろうとすると、その時点ではまだプラグインは `source` されていないのでそんな名前のカラースキーマなんてねーよとエラーになってしまいます。しかし、非遅延プラグイン(`on_*`のオプション指定がないもの)では `hook_source` と `hook_post_source` は呼ばれないという dein の仕様がある為、`hook_post_source` は使えません。

そこで __`colorscheme` は `VimEnter` のタイミングで設定されるように `autocmd` を仕掛けるようにします。またそのときは必ず `nested` を付けるようにします。__（`nested` 指定がないと `colorscheme` 設定時に発生する筈の `Colorscheme` イベントがが入れ子イベントとなり発生が抑制されてしまうので、このイベントに初期化処理を依存している他プラグインが上手く動かなくなってしまいます）

`dein.vim` のドキュメントのFAQではプラグインで入れた `colorscheme` は `dein#end` の後に書け、と書いてありますが、1つのプラグイン設定はやはり1箇所にまとめて書きたいのでTOML側でこんな風にしてみました。

（2016-05-10追記： 昔は起動直後に読み込み完了しているという遅延ロード設定が書けなかったので、仕方なく [`hook_add` の中で `autocmd VimEnter` とかして無理やり設定を遅延させてた](http://qiita.com/kawaz/items/ee725f6214f91337b42b/revisions/27)んですが、最近 `on_event` が追加されたことでシンプルな記述で `VimEnter` 時にロード（=設定フックを発火）させられるようになったので、このエントリ中の設定も更新しておきました。）

（2016-05-29追記： そもそも `VimEnter` で単純にカラースキーマ設定をすると `Colorscheme` イベントが起こらない問題があることが分かったので、一周回って `hook_add` で `VimEnter` に `autocmd` を仕掛ける（但し `nested` を付ける形に戻ってきました）


## vim-precious の導入でtoml管理が快適に
`vim-precious` と依存プラグインである `context_filetype.vim` を導入すると、toml の `hook_*` オプション内にカーソルがあるときだけ、`set filetype=vim` させることが出来るので、プラグインの追加設定も toml 内で快適に書けて、TOML最高！となります。

（2016-03-31追記：このエントリを書いた当初は自分で `g:context_filetypes.vim#filetypes' にdein用設定を追加してたんですがいつの間にかプラグイン本体のデフォルト設定に[同じような設定が追加されてた](https://github.com/Shougo/context_filetype.vim/commit/2dd8642362ae8e932aac4b0ed124e92a81e1eb8f)ので自分でパターンを設定する必要はなくなりました。）

こんな感じになります。
![gyazo-975d6f439513424f9a82880ed9d74e7e.gif](https://qiita-image-store.s3.amazonaws.com/0/18726/0d2b53c2-7762-3623-4604-62f1a422956b.gif)

ノーマルモード時に `ｆｔ` が切り替わりすぎるのがちょっと鬱陶しいって場合は `vim-precious` の `hook_add` に以下を足しておくと、インサートモード時だけ自動切り替えを有効化するようにも出来ます（一時期はこれで抑制してたけど結局常に自動切り替えの方を好むようになったので僕は今は使ってないけど）。

```vim:
" NORMALモードのカーソル移動中に頻繁に切り替わるとうざいのでデフォは無効化しておく(helpは例外)
let g:precious_enable_switch_CursorMoved = { '*': 0, 'help': 1 }
" INSERTモードのON／OFFに合わせてトグル
autocmd MyAutoCmd InsertEnter * :PreciousSwitch
autocmd MyAutoCmd InsertLeave * :PreciousReset
```