Vimのpatch-7.4.849について

Vim の patch-7.4.849 欲しさに野良ビルドに手を出してしまいました。これは例えば括弧を自動的に閉じるような設定をしている場合に便利なのです。

inoremap ( ()<Left>

この設定自体には賛否両論あるらしいのですがその点はスルーします。ただ、賛だとしても Vim の操作として考えた時大きな短所があるのは認めざるを得なくて、今まではその点に目をつぶりながら似たような設定を使ってきました。

その短所がどういうものかというと、例えば上記のような設定をせずに、空のバッファで a(foo)<Esc>. と打ち込むと当然バッファの内容は次の通りになります。

(foo)(foo)

. は直近の入力を繰り返しているのでこうなりますね。期待通りの結果だと思います。しかし、上記のような設定をしていた場合(その場合は入力は a(foo<Esc>l.)はこうはならず、次のようになります。

(foo)foo

これは設定に含まれている <Left> キーが少し特殊な扱いになるからです。一部のキーは、挿入モードで押下されると、あたかもそこでいったん挿入モードを抜け、もう一度挿入モードに入ったかのように解釈されます。 <Left><Right> のような文字入力を伴わずにカーソルを移動するものや、 <C-o> のように挿入モードでノーマルモードコマンドを使うためのキーなどを含めいろいろあり :help ins-special-special に列挙されています。さて、この関係で上記のような設定をしていた場合、キー入力は a(foo<Esc>l. ですが、キーマップを展開すると a()<Left>foo<Esc>l. となります。 . が繰り返す直近の入力は <Left> より後の foo のみ、とみなされたというわけです。<Left> でインサートモードを抜けて、カーソルを移動、インサートモードに入りなおしている、と考えるとここでドットリピートの単位が区切られてしまっているのです。

小さいといえば小さいのですけど、これがなかなか入力を繰り返す時にネックになることが多いのです。私は smartinput を使って似たような設定を使っていたのですけど、この問題のために一時的にすべての設定を停止するキーマップをvimrcに書いてなんとか誤魔化していました。とはいえ、このキーマップも意図的に操作しないといけないので、先に繰り返すと決めていた場合にしか効果がないので気休めにしかなりません。件の挙動はヘルプにもしっかり書いてあるし、仕様だと諦めていたところに Patch-7.4.849 がきました。これはこのように使います。

inoremap ( ()<C-g>U<Left>

<Left><Right> の前に <C-g>U を挟むことでドットリピートで繰り返される単位を区切らないようにすることができるようになりました。()<Left>foo の入力を繰り返すということですね。すばらしい。ただし、制限がないわけではなくて、どうも同一の行内で編集が完結する場合のみしか有効ではないみたいです。

" | はカーソル
{|}

これを <Enter> 一発で

{
    |
}

こうするような設定とかだとダメなんでしょう。使ってないからいいかな。 <C-g>U はまだ使い始めたところだけどいろいろ便利そうです。単純に括弧の件だけでも十分すぎるほどに朗報で興奮しています。

完全に余談ではあるけどビルドにあたって、ずっと欲しいと思っていた このパッチ をあててみました。もやもやしていたのが解決されて、とても幸せです。これも早く本体に取り込まれてほしいです。