Programmer's Note

コード読み書きの備忘録。

vimで単語の置換を一発でやる関数を作ってみる

vimを使い始めて2ヶ月ちょっとか。感覚的には半年くらい使ってる気がするな。 もはや日々の仕事に欠かせないツールになっている。 プラグインの方もも欲しいと思ってたものをいくつか入れて、IDE相当なリッチな環境になってきた。

プラグインも各々使いこなしがまだまだで、慣れればもっと効率が飛躍しそう。 (なんかプラグインもそれぞれ作者の世界観があって面白い)

今使っているのは、

  • Gtags
  • CtrlP
  • vim-bookmark

この3つでソースコード編集&読解がだいぶ楽になった。 もちろん、:makeとQuickFixは言うまでもない。

CtrlPはまだよく分かってなくて、慣れてきたら整理したいところだ。

さて、単語の置換の話

たとえばCでコードを書いてて良くあるのは、一回マジックナンバーを入れて書いたところに、 マクロ名に置換したいときだ。

たとえば、

char buf[256];
int i;

for(i = 0; i< 256; i++) {
 ...
}

とかの、256をBUF_SIZEとかに置換する。どうするか? たかだか一関数内の数カ所の置換なので、:%s/256/BUF_SIZE/gcとかは、ちと大げさかな。と。

vimのコマンドでやろうとすると、ひとつめの256にカーソルを合わせておいて、 ciwてやってBUF_SIZEを入れて[ESC]、2つ目の256で.か。

でも、とりあえずどっかのヘッダファイルに、

#define BUF_SIZE 256

と書いた後には、このBUF_SIZEをyiwして、256と置換したいよな。

この時は、256にカーソルをあてて、まずは256を消さなきゃいけない。 普通にdiwとかで消すと、直前ヤンクした内容が消えてしまう。

ので、

  1. 256にカーソルを当てて"_diwでは、ブラックホールレジスタ"_を指定する
  2. 続いてhpで、左に移動してからペースト

とすればよいと。まあ、続けて書けば"_diwhpですね。

上記の例は問題ないが、置換したい単語が行の先頭にある場合だと、 一文字後ろにずれてしまう。

置換前:
256
置換後
 BUF_SIZE

この場合は、"_diwPと大文字のPでペーストする必要がある。 (左には移動できないのでhは意味をなさない) pの場合はカーソルの後ろにペーストするので、どうして空白が一個できるからだ。

また、行末の単語の場合は削除した場合も、勝手にいっこ左移動になるので、hはいらない。

さて、場合よって使い分けるというのもあるが、"_diwhpの入力が面倒。 比較的頻繁に行う操作なので、自分でキーマップを作ってしまいたい。 と思って作ったのが以下のvimscript。

function! ReplaceWord()
    execute ":normal \"_diw"
    if col('.') == 1
        execute ":normal P"
    elseif col('.') == col('$')-1 && getline('.')[col('.')-1] == ' '
        execute ":normal p"
    else
        execute ":normal hp"
    endif
endfunction
:command! ReplaceWord call ReplaceWord()
nmap <C-y> :ReplaceWord<CR>

これを.vimrcに放り込んだ後にvimを実行すれば、 任意の単語の上にカーソルを当てた状態でCtrl-yを押すと、 直前にコピーした文字列に置換される。行頭、行末の場合もOK。