GNU Emacs 32.0.50 (9008bf64c3) のマニュアルを PLaMo 翻訳で機械翻訳したものです。誤訳を含むことがあります。原文: https://www.gnu.org/software/emacs/manual/html_node/elisp/Atomic-Changes.html ・ emacs-doc.conao3.com

33.33 原子変化グループ

データベース用語において、アトミックな変更とは不可分な変更のことであり、完全に成功するか完全に失敗するかのいずれかであり、部分的に成功することはありません。Lispプログラムでは、1つまたは複数のバッファに対して一連の変更をアトミック変更グループとして行うことができます。これは、一連の変更がすべてバッファに反映されるか、あるいはエラーが発生した場合には一つも反映されないことを意味します。

すでに使用中のバッファ1つに対してこれを行うには、変更を加えるコードの前後に、次のように atomic-change-group の呼び出しを記述するだけです:

(atomic-change-group
  (insert foo)
  (delete-region x y))

atomic-change-group の本体内でエラー(またはその他の非ローカルな終了)が発生した場合、その本体の実行中に行われた当該バッファ内のすべての変更が取り消されます。この種の変更グループは他のバッファには影響を与えず、こうした変更はそのまま残ります。

各種バッファへの変更を一つのアトミックグループとして構成するなど、より高度な処理が必要な場合は、atomic-change-group が使用する低レベル関数を直接呼び出す必要があります。

関数: prepare-change-group &optional buffer

この関数は、バッファ buffer(デフォルトは現在のバッファ)用の変更グループを設定します。変更グループを表すハンドルを返します。このハンドルを使用して変更グループを有効化し、その後終了させる必要があります。

変更グループを使用するには、それを有効化する必要があります。bufferの本文に変更を加える前に、この操作を行ってください。

関数: activate-change-group handle

この関数は、handle が指定する変更グループを有効にします。

変更グループを有効にすると、そのバッファ内で行った変更はすべてそのグループの一部となります。バッファ内で必要な変更をすべて終えたら、変更グループを完了させる必要があります。これには2つの方法があります。すべての変更を承認(および確定)するか、あるいはすべてキャンセルするかです。

関数: accept-change-group handle

この関数は、handleで指定された変更グループ内のすべての変更を取り込み、それらを確定させます。

関数: cancel-change-group handle

この関数は、handle で指定された変更グループ内のすべての変更を取り消し、元に戻します。

undo-amalgamate-change-group を使用することで、変更グループ内の変更の一部または全部を、undo コマンド(Undo を参照)の処理上、単一の単位として扱うことができます。

関数: undo-amalgamate-change-group

handle で特定された状態以降に変更グループ内で行われたすべての変更を統合します。この関数は、handle で記述された状態以降の変更のアンドゥレコード間にあるすべてのアンドゥ境界を削除します。通常、handle は prepare-change-group によって返されるハンドルであり、その場合、変更グループの開始以降のすべての変更が単一のアンドゥユニットに統合されます。

コードでは、グループが必ず終了するように unwind-protect を使用してください。ユーザーが実行直後に C-g と入力した場合に備え、activate-change-group の呼び出しは unwind-protect の中で行うようにしてください。(prepare-change-group と activate-change-group が別々の関数になっている理由の一つはここにあります。通常であれば、その unwind-protect が始まる前に prepare-change-group を呼び出すためです。)グループが終了したら、そのハンドルを再度使用しないでください。特に、同じグループを2回終了させようとしないでください。

マルチバッファ変更グループを作成するには、対象とする各バッファに対して prepare-change-group を1回ずつ呼び出し、次に nconc を使用して返された値を次のように結合します。

(nconc (prepare-change-group buffer-1)
       (prepare-change-group buffer-2))

その後、activate-change-groupを1回呼び出すことでマルチバッファ変更グループを有効にし、accept-change-groupまたはcancel-change-groupを1回呼び出すことで完了できます。

同一バッファに対して複数の変更グループをネストして使用すれば、期待通りに動作します。同一バッファに対して変更グループをネストせずに使用するとEmacsが混乱するため、そのような使い方は避けてください。あるバッファに対して最初に開始した変更グループが、最後に完了するものであるべきです。

Emacsは、buffer-undo-list 内の各 cdr を辿っていけば、最終的に prepare-change-group が呼び出された時点で設定されていた cons に到達すると想定して、変更グループを管理しています。

buffer-undo-list にその cons が含まれていなくなると、Emacs はチェンジグループの追跡ができなくなり、チェンジグループをキャンセルした際にエラーが発生します。これを避けるため、チェンジグループが有効な間は、アンドゥリストをそのような形で編集する可能性のある関数を呼び出さないでください。特に、undo-auto-amalgamate を呼び出す delete-char のような「アマルガメイティング」コマンドには注意してください。