vim/neovimにおいて、カレントなバッファの文章を検索して結果をQuickfixにリストアップするという機能は無いようです。
(nvim v0.8.3、vim9.0時点)
「vim buffer grep」などの単語でネットを検索するとそれなりの数の記事がヒットします。
それらの記事では大体は以下の方法が紹介されています。
:vimgrep {検索語} %
しかし、この方法は「バッファをgrepする」方法ではなく、「バッファで開いているファイルの内容をgrepする」方法です。
Exコマンドで%
は現在開いているファイルパス文字列に展開されるので、上記はあくまで「ファイルに対してgrepする」操作です。
そうではなく、無名バッファの内容であったり、ファイルに保存前の編集中の状態だったりといった「バッファの内容そのもの」をgrepしたいとしてもその方法がありません。
Vim本体への実装提案
調べてみると、この「バッファを直接grepする方法」は実装を試みられたことがあるようです。
Vimの開発メーリングリストにて以下のスレッドがあり、それに続けてGithubでのプルリクエストも作成されています。
- [patch] allow to vimgrep current buffer
- Add bvimgrep command by chrisbra · Pull Request #858 · vim/vim · GitHub
2014年10月ごろにMLでの提案が出されて検討が行われ、2016年にbvimgrep
というコマンド名で実装のPRが出されています。その後にvimgrep[!] <buffer>
というコマンドが良いのではと方向転換された後に、2020年ごろに動きが止まってしまったようです。
プラグインでの代替
標準での機能が無いとなると、プラグインで代替機能を探すことになります。
私が見つけた方法としては、coc.nvim
のcoc-lists
拡張を使う方法があります。
- neoclide/coc.nvim: Nodejs extension host for vim & neovim, load extensions like VSCode and host language servers.
- neoclide/coc-lists: Common lists for coc.nvim
coc-lists
拡張によって、:CocList
コマンドにlines
機能が追加されます。これが、バッファを検索した結果を一覧表示することができます。
操作例は以下のようになります。
:CocList lines
↓
検索用モードになるので、`INTERACTIVE>`に検索したい正規表現を入力
↓
<C-o>をキー入力してnormal modeに移行
ちなみに、この時の検索結果一覧の表示はQuickfixそのものではありません。あくまでcoc.nvim固有の機能です。coc.nvimでは、CocListでの検索結果をQuickfixに移す方法があるので、それを組み合わせることもできます。
CocListでの検索結果のnormal mode状態において、操作対象の行を選択する
(<Space>で1行ずつにToggleで選択on/offしたり、Visualmodeで行を選択状態にする)
↓
<Tab>キーで操作メニューを表示
↓
<q>キーでQuickfixに送る
↓
Quickfixが開き、選択された検索結果の一覧が表示される
ただし、残念ながら無名バッファの場合はQuickfix上で検索結果の行の内容などは表示されません。
(coc.nvim version: 0.0.82-79e9e048 2023-02-15 時点)
おまけ:Quickfixを使わずに似たようなことをする方法
私がバッファの内容を検索したいシチュエーションは、tail -n 100 application.log | vim -
という感じで、ターミナルで何かのコマンドを実行し、その結果をvimで見るときです。
上記操作に続けてvim上で内容を調べる時に、ある検索結果にマッチした行のみを抜粋したいときは:global
(:g
)コマンドで以下のようなことができます。
1. マッチした行のみの内容にする
:g!/{検索語}/d
:g!
で検索語にマッチしなかった行を操作対象として、d
でその行を削除する。(→ 結果的にマッチした行のみの内容になる)
2. バッファの内容を維持したまま、マッチした行のみを抜粋する
:g/{検索語}/copy $
:g
で検索にマッチした行をcopy $
でバッファの末尾($
)に行コピーする。
3. マッチした行と、マッチしなかった行を分ける
:g/{検索語}/m$
m$
(move $
)でマッチした行をバッファの末尾に移動させる。マッチしなかった行は元の場所に残っている。