Vim - agやackの検索結果を表示するctrlsfプラグイン
この記事はVim Advent Calendar 2013の89日目です。
前日はmanga_osyoさんの誤った goto 文で到達しないコード箇所を直ちに検知する方法でした。
Intro
動きは上記リンクのGIFを見て頂ければお分かり頂けると思います。
- キーワード検索をして
- 結果を新規に開いた左Windowに表示して
- 選択したファイルの該当行へジャンプします
Sublime Text 2のCtrl + Shift + F
みたいなやつ、ってことらしいです。
必要なもの
ag(the_silver_searcher)かackが必要です。
私はagを使っています。
参考:ackを捨てて、より高速なag(The Silver Searcher)に切り替えた
なおctrlsfはag -> ackの順でコマンドを探しますので、両方入っている場合はagが使われるはずです。
似たようなこと
以下の方法でも似たようなことは可能だと思います。
- 標準のgrep + quickfix
- Untie grepを使う(Shougo/unite.vim)
- CtrlPQuickfixを使う(kien/ctrlp.vim)
- (ackの場合)mileszs/ack.vim
- (agの場合)rking/ag.vim
- などなど
上記と比較した時の利点
マッチした行の前後も表示してくれたりして見やすい。
こちらはag.vimで検索した結果です。
一覧でスッキリしていて、これはこれで見やすいです。
一方こちらはctrlsf.vimで検索した結果です。
なにで検索したか、どこにマッチしたかがより分かりやすいのではないかと思います。
使い方
READMEに細かく書いてありますので、詳細はそちらやHelpをご覧ください。
コマンドの簡単な説明です。
- 基本は
:CtrlSF {pattern}
で検索します。:CtrlSF foo
などのように。 - オプションを指定することも出来ます。
:CtrlSF -i -C 2 {pattern}
- オプションはagやackのオプションに準拠しているようです
- 特定のディレクトリを指定することも可能です。
:CtrlSF {pattern} /path/to/dir
- 指定しなければ現在のディレクトリ(
:pwd
で表示されるディレクトリ)を対象に動きます
- 指定しなければ現在のディレクトリ(
:CtrlSFOpen
で結果Windowを開き直します。再検索しているわけではなくWindowを開き直しているだけのようです
検索結果Windowでのキーマップについて。
<o>, <Enter> ファイルを開く
<p> プレビューとして開く
<q> 結果Windowを閉じる。プレビューも開いていればそっちも閉じる
<C-J> 結果Window内で、次の一致行へ移動
<C-K> 結果Window内で、前の一致行へ移動
.vimrcに書く設定値の一部について簡単な説明です。
g:ctrlsf_auto_close
- 1だと検索結果からジャンプした時に検索結果を閉じる(デフォルト)
- 0だと検索結果からジャンプした時に検索結果を閉じない
- 例:
let g:ctrlsf_auto_close = 0
g:ctrlsf_context
- マッチした行の前後をどれだけ表示するか。grepでいう-B -A。agでいう-C
- デフォルトは
-C 3
- 例:
let g:ctrlsf_context = '-C 5'
g:ctrlsf_selected_line_hl
- プレビューやジャンプした際に、対象行をハイライトするかどうか
o
はジャンプしたあとにハイライトする、p
はプレビューのとき- デフォルトは
let g:ctrlsf_selected_line_hl = 'p'
- 例えば両方ハイライトさせるなら
let g:ctrlsf_selected_line_hl = 'op'
ハイライトはこんな感じです。右Windowのs:exists_openbrowserの行がハイライトされています。
物足りない点
- 今のところジャンプする時にタブで開くとか、細かい開き方の指定ができない
- 追記: コメント参照。タブで開くのを実装して頂けました
- CtrlSFという名前というかコマンド名がctrlp.vimのCtrlPとかぶりすぎていて、コマンド打つのがちょっとダルい
- 'CtrlS' まで打たないと補完の結果がCtrlPとかぶるので
- マッピングもしくは独自に別コマンドとして定義すればいいんですけど
- そしてCtrlSFって何か打ちにくい(自分だけ?)
- 良くも悪くも(今のところ)ag/ack依存。他の検索コマンドで使うことはできない
とはいえ、良さそうな気はするのでちょっと使ってみようかなと思います。