vim-users.jp

Hack #195: virtualedit tip

Posted at 2011/01/16
このエントリーをはてなブックマークに追加

virtualeditはすばらしいものです。 文字が存在しない部分にもカーソルを移動させることができる、 それだけなのですが筆者はこのオプションを知った時ずいぶんと移動が楽になったように感じました。 ちなみにTeraPadやApsalyなどのエディタでも「フリーカーソル」として実装されているようです。 またvirtualeditについてはHack #125も参照してください。

ちなみに自分は.vimrcで

set virtualedit=all

のように設定しています。

問題

しかし、set virtualedit=allをしているとpでのペーストで もし右端($で移動できる場所です)よりも右にいた場合に、 現在いる場所にテキストが挿入されてしまいます。

hello,$      |

$は行末の位置であり、|はカーソルです。 ここで無名レジスタ(:help registers)には「world」が入っているとします。種類はcharacterwise(:help characterwise)とします。 ここでpを押すと

hello,      world

このようになってしまいます。 私が望んだのは

hello,world

であり、余計な空白は入れてほしくありません。 set virtualedit=allだといともたやすく存在しない場所へカーソルを動かすことができるので、 ただ末尾に付け加えたいだけの場合に余計な神経を使ってしまうのです。なんとかできないでしょうか。

解決

以下のコードを.vimrcに貼り付ければ無事解決です。

if has('virtualedit') && &virtualedit =~# '\<all\>'
    nnoremap <expr> <SID>($-if-right-of-$)  (col('.') >= col('$') ? '$' : '')
    nnoremap        <SID>(noremap-p)        p
    nmap p <SID>($-if-right-of-$)<SID>(noremap-p)
endif

一行で書いてもいいでしょう。

if has('virtualedit') && &virtualedit =~# '\<all\>'
    nnoremap <expr> p (col('.') >= col('$') ? '$' : '') . 'p'
endif

<SID>マッピングや<expr>を使うとマッピングを関数のように定義できます。
また<expr>の中では式であればよく、関数も使えるのでぐんと表現力が上がります。
しかし一行で書ける範囲であれば一行で書いた方が可読性は高いでしょう。
また<SID>マッピングを使うなら最低限mapとnoremapの違いは把握してないと使えません。

tyru

もどる
blog comments powered by Disqus