置換のためのコマンドラインで g が欠ける問題

長らく悩まされていた問題が解決したのでメモ。

現象

カーソルの下にある語(cword)を一括置換するためのキーマッピングを実行すると、コマンドラインモードにて以下の状態になるように設定してあります。(ここでは、cword が get_foo で、][ がカーソル位置を表すものとします)

:%s/get_foo/][/g

ここで、置換する文字列を組み立てるために、C-r, C-w を押下すると、こうなります。
 ↓

:%s/get_foo/et_foo/g

g が欠けて、et_foo が挿入されます。うっかり気付かないでいると、意図しない置換を行って泣きを見ます。

今回、なぜに g が欠けるのか、原因を調べてみました。

原因

結論としては、どうもこれが原因のようです。(はやw)

:h c_^R^W
                Insert the object under the cursor: 
                        CTRL-F  the Filename under the cursor 
                        CTRL-P  the Filename under the cursor, expanded with
                                'path' as in |gf|
                        CTRL-W  the Word under the cursor
                        CTRL-A  the WORD under the cursor; see |WORD|
        
                When 'incsearch' is set the cursor position at the end of the
                currently displayed match is used.  With CTRL-W the part of
                the word that was already typed is not inserted again.

With CTRL-W the part of the word that was already typed is not inserted again.

すなわち、挿入済みの部分は削りますよってことなんですが、どうも挿入位置の後ろにある、:s コマンドのフラグ文字 g が挿入済みの部分とみなされるために、そこが削られてしまう模様

試しにコマンドライン末尾の g をなくすと

:%s/get_foo/][/

 ↓

:%s/get_foo/get_foo/

ちゃんと入りました。

どうやら、挿入済みの部分を調べるときに、挿入位置の直前ではなく、コマンドライン全体を見るようです。

対処

コマンドラインの末尾に適当にダミーの文字を入れて、挿入される語の先頭部分にマッチさせなければいいので、無害な文字としてコメント開始文字である " を末尾に付加することで解決できました。

:%s/get_foo/][/g "

 ↓

:%s/get_foo/get_foo/g "