ほとんどのバッファーは、バッファーのテキストにたいして行われた変更をundoできるように、すべての変更を記録するundoリスト(undo
list)をもっています(undoリストをもたないバッファーとは通常はEmacsがundoを有用とみなさない特殊用途のバッファーである。特に名前がスペースで始まるバッファーはすべてundoの記録がデフォルトでオフになっている。バッファーの名前を参照)。バッファー内でテキストを変更するすべてのプリミティブはundoリストの先頭に自動的に要素を追加して、それは変数buffer-undo-list
に格納されます。
このバッファーローカル変数の値は、カレントバッファーのundoリスト。値がt
ならundo情報の記録を無効にする。
以下はundoリストが保有可能な要素の種類です:
position
この種の要素は前のポイント値を記録する。この要素をundoすることによりポイントはpositionに移動する。通常のカーソル移動はどのような類のundo記録も作成しないが、削除操作はそのコマンド以前にポイントがあった場所を記録するためにこのエントリーを使用する。
(beg . end)
この種の要素は挿入されたテキストを削除する方法を示す。挿入においてそのテキストはバッファー内の範囲begからendを占める。
(text . position)
この種の要素は削除されたテキストを再度挿入する方法を示す。文字列textは削除されたテキストそのもの。削除されたテキストを再挿入する位置は(abs
position)
。positionが正ならポイントがあったのは削除されたテキストの先頭、それ以外では末尾。この要素の直後に0個以上の(marker
. adjustment)要素が続く。
(t . time-flag)
この種の要素は未変更のバッファーが変更されたことを示す。time-flag
(非整数のLispタイムスタンプ)は、visitされたファイルにたいしてそれが以前にvisitや保存されたときの更新時刻(modification
time)を、current-time
と同じ形式を用いて表す。時刻を参照のこと。time-flagが0ならそのバッファーに対応するファイルがないことを、−1ならvisitされたファイルは以前は存在しなかったことを意味する。primitive-undo
はバッファーを再度未変更とマークするかどうかを判断するために、これらの値を使用する(ファイルの状態がtime-flagのそれとマッチする場合のみ未変更とマーク)。
(nil property value beg . end)
この種の要素はテキストプロパティの変更を記録する。変更をundoする方法は以下のようになる:
(put-text-property beg end property value)
(marker . adjustment)
この種の要素はマーカーmarkerがそれを取り囲むテキストの削除により再配置されて、adjustment文字位置を移動したということを記録する。undoリスト内の前にある要素(text . position)とマーカーの位置が一致する場合には、この要素をundoすることによりmarker − adjustment文字移動する。
(apply funname . args)
これは拡張可能なundoアイテムであり、引数argsとともにfunnameを呼び出すことによりundoが行われる。
(apply delta beg end funname . args)
これは拡張可能なundoアイテムであり、begからendまでに限定された範囲にたいして、そのバッファーのサイズをdelta文字増加させる変更を記録する。これは引数argsとともにfunnameを呼び出すことによりundoが行われる。
この種の要素は、それがリージョンと関係するか否かを判断することによりリージョンに限定されたundoを有効にする。
nil
この要素は境界(boundary)である。2つの境界の間にある要素を変更グループ(change group)と呼び、それぞれの変更グループは通常1つのキーボードコマンドに対応するとともに、undoコマンドは通常はグループを1つの単位として全体をundoを行う。
この関数はundoリスト内に境界を配置する。このような境界ごとにundoコマンドは停止して、連続するundoコマンドは、より以前の境界へとundoを行っていく。この関数はnil
をリターンする。
この関数を明示的に呼び出すことは、あるコマンドの効果を複数単位に分割するために有用である。たとえばquery-replace
はユーザーが個別に置換をundoできるように、それぞれの置換後にundo-boundary
を呼び出している。
しかしほとんどの場合には、この関数は適切なタイミングで自動的に呼び出される。
エディターコマンドループは各アンドゥがが通常はそれぞれ1つのコマンドの効果をアンドゥするように、各キーシーケンスを実行する直前にundo-boundary
を呼び出す。少数の例外は融合(amalgamating)コマンドである。これらのコマンドは一般的にバッファーにたいして小さい変更を発生させるので、変更をグループとしてアンドゥできるように、20回目のコマンドごとに境界が挿入される。デフォルトでは自己挿入入力文字を生成するコマンドself-insert-command
(ユーザーレベルの挿入コマンドを参照)、文字を削除するコマンドdelete-char
(テキストの削除を参照)は融合コマンドである。複数バッファーのコンテンツに影響するコマンド、たとえば発生し得るとすればpost-command-hook
上の関数がcurrent-buffer
以外のバッファーに影響を及ぼす場合には、影響を受ける各バッファーごとにundo-boundary
が呼び出されるだろう。
この関数を融合コマンドの前に呼び出すことができる。そのような一連の呼び出しが行われていると、以前のundo-boundary
は削除される。
融合可能な最大の変更数はamalgamating-undo-limit
変数で制御される。この変数が1なら変更は融合されない。
Lispプログラムはundo-amalgamate-change-group
を呼び出すことによって、一連の変更を単一の変更グループにまとめることができます(グループのアトミックな変更を参照)。この関数で生成したグループにたいしてamalgamating-undo-limit
は効果がないことに注意してください。
プロセスバッファーのようないくつかのバッファーでは、何もコマンドを実行していなくても変更が発生し得る。このような場合には、通常はundo-boundary
この変数内のタイマーにより定期的に呼び出される。この挙動を抑制するには、この変数を非nil
にセットすること。
この変数は通常はnil
だが、undoコマンドはこれをt
にバインドする。これによりさまざまな種類の変更フックがundoにより呼び出された際に、それを告げることが可能になる。
これはundoリストの要素のundoにたいする基本的な関数。これはlistの最初のcount要素をundoしてlistの残りをリターンする。
primitive-undo
はバッファー変更時に、そのバッファーのundoリストに要素を追加する。undoコマンドは混乱を避けるためにundo操作シーケンス冒頭にundoリストの値を保存する。その後でundo操作は保存された値の使用と更新を行う。undoにより追加された新たな要素はこの保存値の一部でないので継続するundoと干渉しない。
この関数はundo-in-progress
をバインドしない。
このマクロはbodyの実行中に挿入されたundo境界を削除して、一度にまとめてundoできるようにする。
いくつかのコマンは、コマンドの選択的なアンドゥを妨害する方法により、実行後にリージョンをアクティブなままにします。undo
をそのようなコマンドの直後に呼び出した際にアクティブなリージョンを無視するには、コマンドの関数シンボルのundo-inhibit-region
プロパティに非nil
値をセットします。シンボルの標準的なプロパティを参照してください。