Next: , Previous: , Up: Text   [Contents][Index]


33.31 グループのアトミックな変更

データベース用語においてのアトミック(atomic: 原子的、不可分)な変更とは、全体として成功か失敗をすることはできるが、部分的にはできない個別の変更のことです。Lispプログラムは単一もしくは複数のバッファーにたいする一連の変更をアトミック変更グループ(atomic change group)にすることができます。これはその一連の変更全体がそれらのバッファーに適用されるか、またはエラーの場合は何も適用されないかの、いずれかであることを意味します。

すでにカレントであるような単一のバッファーにたいしてこれを行うには、以下のように単に変更を行うコードの周囲にatomic-change-groupの呼び出しを記述します:

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

atomic-change-groupのbody内部でエラー(またはその他の非ローカルexit)が発生した場合には、そのbodyの実行の間にそのバッファーでのすべての変更が行われなかったことになります。この類の変更グループは他のバッファーには影響を与えず、それらのバッファーにたいする変更はそのまま残されます。

さまざまなバッファー内で行った変更から1つのアトミックグループを構成する等、より複雑な何かを必要とする場合には、atomic-change-groupが使用する、より低レベルな関数を直接呼び出さなければなりません。

Function: prepare-change-group &optional buffer

この関数はbuffer (デフォルトはカレントバッファー)にたいする変更グループをセットアップする。これはその変更グループを表すhandleをリターンする。変更グループをactivateしたり、その後でそれを完了するためにはこのhandleを使用しなければならない。

変更グループを使用するためには、それをactivate(アクティブ化)しなければなりません。これはbufferのテキストを変更する前に行わなければなりません。

Function: activate-change-group handle

これはhandleが指定する変更グループをactiveにする。

変更グループをactivateした後には、そのバッファー内で行ったすべての変更は変更グループの一部となります。そのバッファー内で目論んでいたすべての変更を行ったら、変更グループをfinish(完了)しなければなりません。すべての変更を受け入れる(確定する)か、すべてをキャンセルするという2つの方法により、これを行うことができます。

Function: accept-change-group handle

この関数はhandleにより指定される変更グループ内のすべての変更にたいして、finalizeすることにより変更を受け入れる。

Function: cancel-change-group handle

この関数はhandleにより指定される変更グループ内のすべての変更をキャンセルしてundoする。

undo-amalgamate-change-groupを使用すれば、いくつか、あるいはすべての変更をundoコマンド(Undoを参照)の対象として単一の単位とみなせる変更グループにすることができます。

Function: undo-amalgamate-change-group

handleにより識別される状態以降にお子なわれた変更グループへの変更をすべてまとめる。この関数はhandleにより記述された状態以降の変更にたいするアンドゥレコード間のアンドゥ境界すべてを削除する。handleは通常はprepare-change-groupがリターンしたハンドルであり、この場合には変更先頭以降のすべての変更は、単一のアンドゥ単位にまとめられる。

グループが常に確実にfinishされるようにするために、コードではunwind-protectを使用するべきです。activate-change-groupの呼び出しは、実行直後にユーザーがC-gをタイプする場合に備えてunwind-protect内部にあるべきです(これがprepare-change-groupactivate-change-groupが別関数となっている1つの理由。なぜなら通常はunwind-protect開始前にprepare-change-groupを呼び出すであろうから)。グループを一度finishしたら、そのhandleを再度使用してはなりません。特に同じ変更グループを2回finishしないでください。

複数バッファー変更グループ(multibuffer change group)を作成するためには、カバーしたいバッファーそれぞれでprepare-change-groupを一度呼び出してから、以下のようにリターン値を結合するためにnconcを使用してください:

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

その後は1回のactivate-change-group呼び出しで複数変更グループをアクティブにして、1回のaccept-change-groupcancel-change-group呼び出しでそれをfinishしてください。

同一バッファーにたいするネストされた複数の変更グループ使用は、あなたが期待するであろう通りに機能します。同一バッファーにたいするネストされていない変更グループの使用によりEmacsが混乱した状態になるので、これが発生しないようにしてください。与えられた何らかのバッファーにたいして最初に開始した変更グループは最後にfinishする変更グループです。