読者です 読者をやめる 読者になる 読者になる

unite.vim の設定を一部晒してみる

Shougo さんの unite.vim がかなり便利。
unite 自体に関する説明は省略するとして*1、特に unite#set_substitute_pattern() を使うといろいろできる。ので、私の unite の設定の中にある unite#set_substitute_pattern() に関する部分を晒してみる。

unite#set_substitute_pattern() について簡単に説明

フィルタリングのための入力文字列を内部で置換するための設定。
これはバッファ名毎に設定できる。バッファ名は :Unite で起動するときに指定できる。


例えば、デフォルトではバッファ名 "files" には先頭の ~ を $HOME に置換する設定がされている。なので、

:Unite -buffer-name=files file

のように起動して ~ と入力すると、内部的には $HOME を入力したのと同じことになる。
また、同じように "files" では / を */* にする設定がしてあるので、結果的にディレクトリ単位での部分マッチを実現している。
第4引数で優先度を指定することで置換の適用順序を制御できる。大きい方が先に処理される。

私の設定

call unite#set_substitute_pattern('file', '\$\w\+', '\=eval(submatch(0))', 200)

call unite#set_substitute_pattern('file', '[^~.]\zs/', '*/*', 20)
call unite#set_substitute_pattern('file', '/\ze[^*]', '/*', 10)

call unite#set_substitute_pattern('file', '^@@', '\=fnamemodify(expand("#"), ":p:h")."/*"', 2)
call unite#set_substitute_pattern('file', '^@', '\=getcwd()."/*"', 1)
call unite#set_substitute_pattern('file', '^\\', '~/*')

call unite#set_substitute_pattern('file', '^;v', '~/.vim/*')
call unite#set_substitute_pattern('file', '^;r', '\=$VIMRUNTIME."/*"')
if has('win32') || has('win64')
  call unite#set_substitute_pattern('file', '^;p', 'C:/Program Files/*')
endif

call unite#set_substitute_pattern('file', '\*\*\+', '*', -1)
call unite#set_substitute_pattern('file', '^\~', escape($HOME, '\'), -2)
call unite#set_substitute_pattern('file', '\\\@<! ', '\\ ', -20)
call unite#set_substitute_pattern('file', '\\ \@!', '/', -30)

簡単に解説

まず、"files" ではなく "file" を使っている。これはデフォルトから独立して設定をしたかったから。
上から順に。

環境変数
call unite#set_substitute_pattern('file', '\$\w\+', '\=eval(submatch(0))', 200)

環境変数を置換している。滅多に使わないけど、たまに $VIM とかやりたいこともあるかもわからない。

部分マッチ
call unite#set_substitute_pattern('file', '[^~.]\zs/', '*/*', 20)
call unite#set_substitute_pattern('file', '/\ze[^*]', '/*', 10)

部分マッチの設定。まずは ~ と . の後ろではない / を */* に置換。
ただし、これだけだと ~/ や ../ などの後に部分マッチできないので、後ろに * のない / を /* に置換。

ショートカット
call unite#set_substitute_pattern('file', '^@@', '\=fnamemodify(expand("#"), ":p:h")."/*"', 2)
call unite#set_substitute_pattern('file', '^@', '\=getcwd()."/*"', 1)
call unite#set_substitute_pattern('file', '^\\', '~/*')

call unite#set_substitute_pattern('file', '^;v', '~/.vim/*')
call unite#set_substitute_pattern('file', '^;r', '\=$VIMRUNTIME."/*"')
if has('win32') || has('win64')
  call unite#set_substitute_pattern('file', '^;p', 'C:/Program Files/*')
endif

入力の先頭で入力すると展開される、いわゆるショートカットの設定。本当はもう少し色々あるけど個人的なディレクトリなのでそこは省略した。
@ とか地味に便利。file_mru と組み合わせると、カレントディレクトリ以下にあるもののみに絞り込まれる。@@ で現在のファイルのある場所以下に絞り込まれる。
ちなみにショートカットは部分マッチされると逆に嫌なのであえて部分マッチより後に処理している。なのでショートカット後の位置から部分マッチさせるために最後に * がいる。

調整
call unite#set_substitute_pattern('file', '\*\*\+', '*', -1)

** の連続を 1 つの * に置換。再帰検索はまずやらないのと、部分マッチの設定によって // が */**/* になってしまうのでここの調整。
これがあることで /// と / を連射すると */*/*/* になるのでこれだけで1つずつ階層を降りていける。単一ディレクトリで深い階層を辿るのに便利。

call unite#set_substitute_pattern('file', '^\~', escape($HOME, '\'), -2)

ホームディレクトリ展開。

call unite#set_substitute_pattern('file', '\\\@<! ', '\\ ', -20)
call unite#set_substitute_pattern('file', '\\ \@!', '/', -30)

パスの調整。"file" ではスペース区切りによる and 検索はまずやらない。それよりもパスにスペースが含まれていた場合のトラブルの方が面倒なので、エスケープされていないスペースを全てエスケープしている。
最後に、unite では \ はエスケープでパス区切りには使えないので、スペースをエスケープしていない \ は全てパス区切りとみなして / に置換している。
この場合部分マッチにならないが、基本的には / で入力するしむしろ先頭マッチが使えると考えれば問題ない。これはどちらかと言うと Windows での $HOME とかに対する処理。

以上

多分やろうと思えばもっと色々できると思う。ここの設定で unite の使い勝手はすごく変わるので、何もしてない人は見直してみるといいかも。

*1:そろそろ誰か書いてくれるはず。私はめんどいのでパス