bonar note

京都のエンジニア bonar の技術的なことや技術的でない日常のブログです。

vim7 undo branch - undo を使いこなす


vim, 特にvim7のundoに関して復習したのでメモ。undo/redo で安心快適 happy viming.

undo の基礎

vimではデフォルで無限undoが使えます。何も考えなくても以下のコマンドで自由自在に編集履歴を行き来することができます。

u アンドゥ(undo)
Ctrl+r リドゥ(redao)

挿入モードに入ってから抜けるまでが一つの更新と見なされるため、長い文章を打ったりする場合にはきりのいいところで一旦編集モード(ノーマルモード)に抜けおくと履歴が管理しやすいかもしれません。

undo branch

通常の無限undoだけで問題ないようにも思いますが、たまに困ることもあります。例えば、ある文章やコードを書いていて途中undoでいくつか履歴を戻り修正していたものの、よく考えるとさっきまで書いていたもののほうが良かったのでそっちに戻りたい、みたいな場合です。

vim7 ではそういったundo/redoの行き来を管理する機能「undo branch」がつきました。

ちょっと説明しずらいので例を出すと(vim のヘルプにもまったく同じような例が出ているのであれですが)、以下のような場合に便利です。

point 1
point 2
point 3
point 4

1行書くごとに一旦挿入モードを抜けたと想定して(行毎に履歴として固定)、ここまで書いて最後の2行をundoしたとします。

point 1
point 2

ここからさらに別の行を書き足します。

point 1
point 2
point 5
point 6
point 7
point 8

これでもちょっと違うと思い立ってさらに最後の3行をundoします。

point 1
point 2
point 5

さらに2行書きたします。

point 1
point 2
point 5
point 9
point 10

意味も無く複雑な編集ですが、このようにundoした箇所から再度編集を行うと、vimは編集の流れが分岐したことを把握してその文書の履歴ツリーを作成します。この例の場合だと以下のようなものになります。

1-->2-->3-->4
    |
    +-->5-->6-->7-->8
        |
        +-->9-->10

point 2, point 5 のところでそれぞれ分岐している感じですね。このような場合通常のundoで遡ると、10->9->5->2->1 と一直線に戻ることしかできません。

vim7からはこの編集過程の状態(vim help中ではtext stateという表現)をまさに更新した順番で行ったり来たりすることが可能です。

g- 状態を1つ遡る
g+ 状態を1つ進める

g- を連打していくと、10->9->8->7->6->5->4->3->2->1 と順番通りに手順を逆再生でき、編集の過程で迷走するようすがよくわかります。どういった分岐が作成されているかは以下のコマンドで確認できます。

:undolist

以下のようなリストが表示されます。

number changes  time
     2       2  29 seconds ago
     5       4  16 seconds ago
     6       3  11 seconds ago

左の数字が分岐を区別するための番号で、その番号とともにどれくらいの修正が今からどれくらい前に行われたのかが表示されます。もちろんこの番号を指定して特定の分岐まで戻ることも可能です。29秒前の分岐まで戻りたければ、

:undo 2

でOKです。

:undo 時間指定で戻る

:help undo-branches を見ると、時間でも指定できるようです。

以下一部抜粋

:earlier {count}  Go to older text state {count} times.
:earlier {N}s     Go to older text state about {N} seconds before.
:earlier {N}m     Go to older text state about {N} minutes before.
:earlier {N}h     Go to older text state about {N} hours before.

:later {count}    Go to newer text state {count} times.
:later {N}s       Go to newer text state about {N} seconds later.
:later {N}m       Go to newer text state about {N} minutes later.
:later {N}h       Go to newer text state about {N} hours later.

今編集している文書を30分前の状態に戻したい!みたいなこともコマンド一発できるわけです。

:earlier 30m

いやはや、すばらしいですね。

まとめ

vimの履歴管理機構はとても高機能でありながら非常に使いやすいと思います。特にvim7から追加された undo branch を初めてしったときは悶絶しました。まさに欲しかった機能だったからです。vim7の最も重要な機能追加だと思います。

なんでいきなりこんなことを書き出したのかというと、この本を買いまして。

Hacking Vim: A Cookbook to Get the Most Out of the Latest Vim Editor

Hacking Vim: A Cookbook to Get the Most Out of the Latest Vim Editor

数少ないvim書籍の中でも非常に薄くて読みやすい本です。体系的な操作の解説ではなく、ある程度操作を知っている人を対象にして面白そうな部分をつまみ食いしてる感じで素敵です。普段vimを使っている人が見るといいかもしれませんね。あと、その機能がvimのどのバージョンから使えるのか、vimなのかgvimなのか、みたいなのが全項目についていて良かったです。

vim7 はまだまだ使ってない機能が多いですね。signs とかはいまだに使いどころがわかりません。

Vim script Cookbook」みたいな本出たらいいなあ。1万円でも買うのに!