Next: , Previous: The Kill Ring, Up: Text


31.9 アンドゥ

ほとんどのバッファには、バッファのテキストに対する変更をアンドゥ(もとに戻す) できるようにすべての変更を記録する アンドゥリスト(undo list)があります。 (アンドゥリストのないバッファは、 Emacsがアンドゥは有用ではないと仮定する特殊目的のバッファである。) バッファのテキストを変更するすべての基本関数は、 変数buffer-undo-listに収めたアンドゥリストの先頭に 自動的に要素を追加します。

— Variable: buffer-undo-list

この変数の値は、カレントバッファのアンドゥリストである。 値tはアンドゥ情報の記録を禁止する。

アンドゥリストの要素として可能なものをつぎに示します。

position
この種の要素は、まえのポイント値を記録する。 この要素をアンドゥするとポイントをpositionへ移動する。 通常のカーソル移動では、いかなる種類のアンドゥ記録も作らないが、 削除操作ではコマンド実行前のポイント位置を記録するためにこの項目を作る。
(beg . end)
この種の要素は、挿入されたテキストを削除する方法を表す。 挿入されたテキストはバッファのbegからendまでの範囲を占める。
(text . position)
この種の要素は、削除されたテキストを再度挿入する方法を表す。 削除されたテキストそのものは文字列textである。 再度挿入する位置は(abs position)である。
(t high . low)
この種の要素は、未変更のバッファが変更されたことを表す。 highlowは2つの整数であり、それぞれ、 まえに訪問したときや保存したときの訪問しているファイルの更新時刻の 16ビットを記録している。 primitive-undoはこれらの値を用いて、 バッファを再度未変更と印を付けるかどうか判定する。 ファイルの更新時刻がこれに一致するときにのみ再度未変更とする。
(nil property value beg . end)
この種の要素は、テキスト属性の変更を記録する。 変更をアンドゥするにはつぎのようにする。
          (put-text-property beg end property value)

(marker . adjustment)
この種の要素は、周りのテキストが削除されたために マーカmarkerを再配置し adjustment文字分位置を移動したことを記録する。 この要素をアンドゥすると、 markeradjustment文字に移動する。
nil
この要素は境界である。 2つの境界のあいだの要素群を変更グループ(change group)と呼ぶ。 通常、各変更グループは1つのキーボードコマンドに対応し、 アンドゥコマンドはグループ全体を1個としてアンドゥする。
— Function: undo-boundary

この関数は、アンドゥリストに境界要素を置く。 アンドゥコマンドはそのような境界で停止し、 連続したアンドゥコマンドはよりまえの境界までアンドゥする。 この関数はnilを返す。

エディタコマンドループは、 各キー列を実行するまえにアンドゥの境界を自動的に作る。 したがって、各アンドゥは、1つのコマンドの効果を普通は取り消す。 自己挿入の入力文字は例外である。 コマンドループはそのような最初の文字に境界を作り、 つぎの19個の連続する自己挿入の入力文字では境界を作らず、 20番目で境界を作るということを自己挿入の入力文字が続く限り行う。

別のバッファでアンドゥ可能な変更を行うたびに バッファのすべての変更で境界を追加する。 これは、各コマンドが変更した箇所で各バッファに境界を作ることを 保証するためである。

1つのコマンドの効果を複数に分けるためにこの関数を直接呼ぶことは有用である。 たとえば、query-replaceは各置換のあとでundo-boundaryを呼び出し、 ユーザーが個々の置換を1つ1つアンドゥできるようにする。

— Function: primitive-undo count list

これは、アンドゥリストの要素をアンドゥする基本的な関数である。 listの先頭のcount個の要素をアンドゥし、listの残りを返す。 この関数をLispで書くこともできるが、Cで書いたほうが便利である。

primitive-undoは、バッファを変更すると バッファのアンドゥリストに要素を追加する。 アンドゥコマンドは一連のアンドゥ操作を始めるときに アンドゥリストを保存して混乱を避ける。 アンドゥ操作では、保存しておいた値を使い更新する。 アンドゥによって追加される新たな要素はこの保存された値の一部ではないので、 それらはアンドゥを続行しても干渉しない。