columnmove.vim を書き直した

Vim 組み込みの f t F T ; , w b e ge W B E gE コマンドを縦 (列) 方向に模倣したモーションを提供するプラグインです。長いことバグとか放置していたのを何とかしました。

columnmove.vim

columnmove-f

f t F T コマンドは特定の文字が出てくるところまでカーソルを移動するコマンドです。そのままだととんでもねぇ眼力を要求されるので、移動先をハイライトするようになっています。

columnmove-f

そんな軟弱なものはいらん、という硬派な方、眼力MAXな方、 set cursorcolumn 運用の方は次の行を vimrc に追加してください。

let g:columnmove_highlight = 0

また、移動先ハイライト中 (ユーザーの入力待ち中) には以下のキーでスクロールできます。

上へスクロール 下へスクロール
一行ずつ <C-y> <C-e>
半ページずつ('scroll' オプションに依存) <C-u> <C-d>
一ページずつ <C-b> <C-f>

columnmove-w

w b e ge コマンドは単語の境界まで移動するコマンドです。列方向なので「単語」という言い方は適切ではないかもしれませんが。書いてから、欲しかったやつとは微妙に違うことに気が付いてやっつけで機能を追加した経緯があります。

let g:columnmove_strict_wbege = 0

このように vimrc に書いておくと文字があるかないかの境界に沿ってカーソルを移動します。つまり iskeyword オプションを考慮しませんし、スペースだろうがタブ文字だろうが文字があればカーソルを止める点が通常の w 等のコマンドとは違ってきます。例えば次のような列を考えてみましょう、ハイフンはスペースだと思ってください。

a
b

"
c
d

-
e

一行目の a から、 通常であれば w コマンドが止まるのは ", c, e です。しかし上記の設定をしていた場合、止まるのは ", - になります。ちなみに W コマンドであれば ", e ですね。

キーマッピングについて

私は gvim を使うことが多いので、デフォルトだと <M-f> <M-w> などのメタキー (Altキー) を使ったキーシークエンスへマッピングされます。ターミナルをお使いの方の場合これらのキーシークエンスは有効でないかもしれないので、お手数ですがマッピングしなおしてお使いください。 columnmove#utility#map() 関数が便利です。

" デフォルトのキーマッピングはいらない
let g:columnmove_no_default_key_mappings = 1

" columnmove#utility#map({モード}, {コマンドの種類}, {キーシークエンス})
" モード : n -> ノーマルモード
"         x -> ビジュアルモード
"         o -> オペレータ待機モード
"         i -> インサートモード
" 種類 : `f` `t` `F` `T` `;` `,` `w` `b` `e` `ge` `W` `B` `E` `gE` のどれか
" キーシークエンス : `:map` コマンドの `{lhs}` と同じように解釈される。
call columnmove#utility#map('nxo', 'f', '\f')
call columnmove#utility#map('nxo', 'w', '\w')

必要なものだけで十分だと思いますが、次のようにすると、まとめてマップできて便利です。

let g:columnmove_no_default_key_mappings = 1
for s:x in split('ftFT;,wbeWBE', '\zs') + ['ge', 'gE']
    call columnmove#utility#map('nxo', s:x, '\' . s:x)
endfor
unlet s:x

ユーザーさんに教えてもらいました。\ 始まりのキーシークエンスへマップされます。

オペレータと組み合わせて使う場合

もともと、 j k コマンドの延長のように考えていたので、デフォルトだとオペレータ待機モードで行指向に働きます。つまりカーソルの通る行全体が処理の対象です。

call columnmove#utility#map('nxo', 'e', '\e')

" Press \e to delete all.
abc
def     ->
ghi

ただし、columnmove#utility#map() 関数の第四引数に 'block' を与えていると矩形指向で働きます。

call columnmove#utility#map('nxo', 'w', '\w', 'block')

" Press \e to delete block-wise.
abc            bc
def     ->     ef
ghi            hi

こっちの方が便利な場合も多いかもしれませんね。どちらの場合でも o_v o_V o_CTRL-V は有効 (参考 :help o_v :help o_V :help o_CTRL-V) なのでどちらにしてもさほど困らないと思います。 o_v とか自体あまり使う人いない気もしますが。ビジュアルモード使えばいいですし。


もともと、 Vim script の練習のつもりで書き始めた初めてのプラグインなのですが、思いのほか長いこと使ってます。実際のところ、すでに世の中にはもっと万能で汎用的なモーションコマンドがたくさん発明されているので、それらに比べると、とりわけ便利というものでもないです。ただ、単純なのでマクロ (:help complex-repeat) のなかでよく使ったりしてます。地味に便利。