職場で学んだ快適なVim操作のためのtips


2014年 09月 04日

テキスト編集にVimを利用しているのですが、とても奥が深い道具なので一人で使う分には気づかない機能が沢山あります。
日頃職場の先輩方から教わりとても効率的に出来るようになったVimのtipsを、いくつかこの記事にまとめます。
知ってる人は既に使いこなしているものばかりだと思いますが、Vimのそんな便利だけど気付きにくい機能を共有できればと思います。

カーソルの位置を移動する直前に戻す

うっかりggしてしまい作業場所を見失ってしまった、という時や検索などによってカーソル位置を変更した時に元の位置に戻りたい、ということはよくあります。
こういった移動履歴はジャンプリストと呼ばれる場所に記録されているので1手で戻る事ができます。

元いた場所に戻る:<C-o>
元いた場所に進む:<C-i>

これはバッファ内だけでなく、ファイル間の移動を記録しているため、タグジャンプなどで別のファイルに移動した後も元いた場所に戻ることが出来ます。

参考help: :h CTRL-o, :h CTRL-i

直前に開いていたバッファに戻る

新しいファイルはUnite.vimを使って開くことにしています。
すると一つのウィンドウ内で複数のバッファをどんどん開いていくことになります。
ここで直前に開いてたバッファに戻りたい、そんな時は:Unite file_mru経由でもう一度ファイルを選び直していたのですが、実はデフォルト操作で1手で実現できることを教わりました:

<c-^>

これはオルタネートファイル(前に編集したファイル)を編集するキーバインドです。
実際には”^”を打つ必要はなく、CTRLを押しながら”^”と同じキーの数字(英字配列なら6)を押せばOKです。

参考help: :h CTRL-^

OSのクリップボードを使ってコピペする

行番号や不可視文字は表示する派なので普段:set list number環境で作業しています。
この環境でバッファ中の文章をコピーしてvim以外のプログラムに貼り付けしたい時、おもむろに:set nolist nonumberと設定し、画面をマウスでドラッグして選択範囲をコピーしてました。
今思うと非常に非効率です。

そこでクリップボードにアクセスするレジスタを使います。
レジスタとは削除(d), ヤンク(y), プット(p)を行う時にテキストを格納する場所で、特に指定をしていない場合は無名レジスタ("")が使われます。
ここで、クリップボードに直接出来るレジスタ("* または "+)というものもあります。
すなわち、クリップボードの内容をvimに貼り付けたい場合は、

"*p

と打ち、逆にテキストをクリップボードにコピーしたい場合は

"*y{motion}

と打ちます。

この*と+は厳密には違いがあるのですが、Windows/Mac上では同じ扱いが出来るので, 筆者はホームポジションから近い"*の方を基本的に使用しています。

参考help: :h quote+, :h quotestar

コマンドラインモードでテキストの貼り付けをする

: を入力してコマンドラインモードに入ると挿入モードでのプット(p)は出来ません。
しかし別の方法で貼り付けを行えます。

コマンドラインモード中では


と操作することでノーマルモードでのプットと同様の結果が得られます。

参考help: :h c_CTRL-R

*による検索文字列を微調整する

例えば、次のようなSQLクエリについて '2014/07/01' を別の日時に一斉置換したいと考えています。

UPDATE Projects SET updated_date_at = '2014/07/01' WHERE staff_id = 'yysaki'
GO
UPDATE Staffs SET updated_date_at = '2014/07/01' WHERE staff_id = 'yysaki'
GO
UPDATE Facilities SET updated_date_at = '2014/07/01' WHERE staff_id = 'yysaki'

まずはこの日時の文字列を*で検索し、%s で置換したい所です。
しかしここで安易に*コマンドを使うとうまい具合にマッチせず、また自分で微調整することが出来ません。

こういった*による検索文字列の範囲を微調整がしたい場合、以下のようなVisualモード用の*コマンドのmapをすることで可能になります。

vnoremap * "zy:let @/ = @zn

これにより、日時の文字列にカーソルを置いて

vi'*:%s//{変更後の日にち}/g

といった操作が出来るようになります。

参考記事: めも – ビジュアルモードで選択した文字列を検索

テキストの差分を確認する

2つのテキストファイルを差分を確認したい場合、いろいろな方法があると思います。
コマンドラインならdiffコマンドがありますし、webサービスにもデュフフとかありますよね。

Vimには :diffthis という差分を取る機能があります。
これを使うことで2つのバッファに取り込んだファイルを比較することができます。
用途としては、SQLサーバーのカラムのインポート前後での比較や、 git push する直前の git lop -p の比較など、様々なシーンで使っています。
また、unimpaired.vimというプラグインを導入するとdiffモードのON/OFFが簡単にできます。
ON/OFFはそれぞれ、

'[od' => :diffthis

']od' => :diffoff

のようにマッピングされており非常に快適に操作できます。

参考help: :h diff

検索しては編集、という繰り返し作業を快適に行う

複数のファイルに”hoge”という文字列が至る所にあり、これを文脈によって”foo”か”bar”に置換する必要があるとします。
その場合、こういった作業はQuickfixを使うことで快適に作業出来ます。

まずは、下記のようにして”hoge”をgrepした結果をQuickfixに流し込みます。

:vimgrep hoge *
:cfile %

ここで行うgrepはツールを問わず、git-grepでもOKです。
あとは:cnextで次のgrep結果に、:cprevで前のgrep結果に行き来出来るようになります。
またいちいちこのコマンドを叩くのは不便なので、unimpaired.vimプラグインを導入しておくとそれぞれ

'[q' => :cprev

']q' => :cnext

でさくさく移動出来るようになり便利です。

参考help: :h quickfix