かなりすごいブログ

ももんが流NeoBundle管理術

Vim Advent Calendar 2012、268日目の記事になります。

日本全国3億人のVimmerのみなさんこんにちは。最近.vimrcを1から書きなおしていると噂の私です。そこで、今回はももんが流NeoBundle管理術をお伝えして行きましょう。

記事の対象

  • NeoBundleに関する基本的な知識があるかた
  • NeoBundleLazyを利用されている方

コンセプト

コンセプトは、プラグイン管理とプラグイン設定を分離させる、です。

具体的には、NeoBundle及びNeoBundleLazyコマンドのオプションは、依存関係やビルドコマンドなどの「プラグインのインストール方法・管理方法」といったものに絞り、autoloadの設定やプラグイン読み込み時の設定は固有のセクションで管理していきます。

これにより、プラグインリストの見通しがよくなりますし、まぁ色々便利になります。

設定例!!!!

" Plugin list
NeoBundleLazy 'Shougo/unite.vim', { 'depends' : [ 'Shougo/vimproc.vim' ] }
" 中略
NeoBundleLazy 'Shougo/vimshell.vim', { 'depends' : [ 'Shougo/vimproc.vim' ] }


" Unite.vimの設定サンプル
if s:bundle_tap('unite.vim')
  call s:bundle_config({
        \   'autoload' : {
        \     'commands' : [
        \       {
        \         'name' : 'Unite',
        \         'complete' : 'customlist,unite#complete_source'
        \       },
        \       'UniteWithCursorWord',
        \       'UniteWithInput'
        \     ]
        \   }
        \ })

  function! s:tapped_bundle.hooks.on_source(bundle)
    let g:unite_kind_jump_list_after_jump_scroll=0
    let g:unite_enable_start_insert = 0
    let g:unite_source_rec_min_cache_files = 1000
    let g:unite_source_rec_max_cache_files = 5000
    let g:unite_source_file_mru_long_limit = 6000
    let g:unite_source_file_mru_limit = 300
    let g:unite_source_directory_mru_long_limit = 6000
    let g:unite_prompt = '❯ '
  endfunction

  nnoremap <silent> <space>u  :<c -u>Unite -start-insert menu:unite<cr>
  " 中略
  nnoremap <silent> <space>g  :<c -u>Unite grep -no-quit<cr>

  call s:bundle_untap()
endif

はい、こんなかんじで、まずプラグインのリストを記述し、その下にプラグインごとの設定をs:bundle_tap関数によりセクション化しています。

ここで、オリジナルの関数が3つ登場しています。s:bundle_taps:bundle_configs:bundle_untapの3つですね。これらの関数によって、ある程度宣言的にNeoBundleの設定を記述できるようになります。それぞれ解説して行きましょう。

まずs:bundle_tap、これは、引数としてプラグイン名を渡すことで、そのプラグインがNeoBundleでインストール・管理されており、かつ有効な状態であるかどうかを返し、同時に対象のプラグインを現在の設定対象プラグインとして設定します。設定対象プラグインは、自動的にs:tapped_bundle変数に格納されます。

また、ここで言う「有効な状態である」とは、NeoBundleNeoBundleLazyコマンドなどで呼び出され、NeoBundleによってrtpに追加されている状態を言います。つまり、一時的にプラグインを無効化したい場合はNeoBundleNeoBundleLazyの行をコメントアウトするだけでよく、わざわざプラグイン個別の設定セクションを編集する必要はありません。

次にs:bundle_config関数です。こちらに辞書を渡すと、現在の設定対象プラグインに対して、neobundle#config関数で設定を行ってくれます。また、現在の設定対象プラグインs:tapped_bundleに格納されていますので、s:tapped_bundle.hooks.on_source関数を定義することで、プラグインの読み込みをフックとした設定も定義することができます。

最後にs:bundle_untap関数ですが、こちらは単純にs:tapped_bundleの参照先プラグインをリセットする関数です。

ここで、これらの関数のコードを見てみましょう。

function! s:bundle_tap(bundle)
  let s:tapped_bundle = neobundle#get(a:bundle)
  return neobundle#is_installed(a:bundle)
endfunction

function! s:bundle_config(config)
  if exists("s:tapped_bundle") && s:tapped_bundle != {}
    call neobundle#config(s:tapped_bundle.name, a:config)
  endif
endfunction

function! s:bundle_untap()
  let s:tapped_bundle = {}
endfunction


お分かりでしょうか。実はこれら3つの関数は、neobundle#is_installed関数及びneobundle#config関数のハンドリングを抽象化したものに過ぎず、これに頼らずともそれらの関数を直接使用することでNeoBundleの設定を行うことは(当たり前ですが)可能です。

しかし、これらの関数を利用することで、s:bundle_tap関数とif文により設定のセクションを明確化し、かつ閉じたスコープによりで何度もプラグイン名を記述することなくなることにより、無駄な記述を行わずプラグインの設定コードを書くことに集中することができます。結果として設定の見通しがよくなり、.vimrcのメンテナンスコストも当ももんが比約1/2となりました。

まとめ

べんり