簡単な unite の source の作り方

と言うわけで、unite の source の作り方を紹介します。本格的に作って配布したい場合は専用のファイルに書くのがいいのですが、今回は手軽に作ろう、ということで vimrc に書きます。そう。unite の source は vimrc でも書けます。

今回作るもの

サンプルってことで、実用性とか無視して、lines という source を作ることにします。これは、現在のバッファの各行を候補とした source です。

source となるオブジェクトを用意する

本当はオブジェクトなんて呼び方ではなくて辞書(Dictionary)なんだけど、この場合扱い的にもオブジェクトと呼んだ方がわかりやすいと思ったのであえてこう呼んでみます。

let s:unite_source = {
\   'name': 'lines',
\ }

名前は必須です。他に指定できる属性については、:help unite-source-attributes を見てください。

候補を返す関数を定義する

ここがキモです。候補のリストを返します。

function! s:unite_source.gather_candidates(args, context)
  let lines = getbufline('#', 1, '$')
  let path = expand('#:p')
  let format = '%' . strlen(len(lines)) . 'd: %s'
  return map(lines, '{
  \   "word": printf(format, v:key + 1, v:val),
  \   "source": "lines",
  \   "kind": "jump_list",
  \   "action__path": path,
  \   "action__line": v:key + 1,
  \ }')
endfunction

まずは全行を取得する必要があるので、getbufline() で取得しています。この関数が実行される際にはカレントは unite バッファになっているので、裏バッファから取得します。
で、format とかあるけどこの辺は割とどうでもよくて、重要なのは return のところです。すでにあるリスト(この場合は lines) を map() を使って unite の候補の形式に変換します。map() の第2引数は文字列です。よく見ると '' で囲われてるのがわかります。このため内部で '' は直接使えないので、"" を使っています。
unite の各候補は辞書で、何が必要かは :help unite-notation-{candidate} に書いてあります。とりあえず word, source, kind は必須です。
word は絞り込み対象となる文字列、source はそのまま source、kind は候補の種類で、候補に対してどのような操作が可能かがここで決まります。ここでは対象の行にジャンプしたいので、"jump_list" を指定しています。そして "jump_list" はジャンプするのに必要な情報として "action__path" と "action__line" を設定する必要があるので、ここで設定しています。
他にどのような kind があるかは、:help unite-kind で見れます。その気さえあれば自分で定義することも可能です。

登録する

call unite#define_source(s:unite_source)
unlet s:unite_source

これで登録されます。最後に unlet してますが、これは好みの問題なのでなくても問題ありません。私はなんとなくもう使わない変数が残ってるのが嫌なので消してます。

全体

let s:unite_source = {
\   'name': 'lines',
\ }
function! s:unite_source.gather_candidates(args, context)
  let path = expand('#:p')
  let lines = getbufline('#', 1, '$')
  let format = '%' . strlen(len(lines)) . 'd: %s'
  return map(lines, '{
  \   "word": printf(format, v:key + 1, v:val),
  \   "source": "lines",
  \   "kind": "jump_list",
  \   "action__path": path,
  \   "action__line": v:key + 1,
  \ }')
endfunction
call unite#define_source(s:unite_source)
unlet s:unite_source

たったこれだけです。やってることが単純なだけあって大した量じゃないですね。

使う

他の source と同じように使えます。

:Unite lines



まとめ

割と簡単に拡張できるので、後はアイディア次第です。最初はこの程度でも問題ないので、まずは書いてみましょう。