Previous: , Up: テキスト   [Contents][Index]


33.32 フックの変更

以下のフック変数によりバッファー(これらをバッファーローカルにした場合には特定のバッファー)での変更にたいして、通知を受け取るようにアレンジすることができます。テキストの特定部分にたいする変更の検出方法については特殊な意味をもつプロパティも参照してください。

これらのフック内で使用する関数は、もしそれらが正規表現を使用して何かを行う場合にはマッチしたデータの保存とリストアを行うべきです。さもないとそれらが呼び出す編集処理に奇妙な方法で干渉するでしょう。

Variable: before-change-functions

この変数はEmacsがバッファー変更を行おうとする際に呼び出す関数のリストを保持する。各関数は変更されようとするリージョンの先頭と終端を整数で表す2つの引数を受け取る。変更されようとするバッファーは関数の呼び出しの際には常にカレントバッファーである。

Variable: after-change-functions

この変数はEmacsがバッファー変更を行った後に呼び出す関数のリストを保持する。各関数は正に変更されたリージョンの先頭と終端、およびその変更前に存在したテキストの長さという3つの引数を受け取る。これら3つの変数は、すべて整数。変更されたバッファーは関数の呼び出しの際には常にカレントバッファーである。

古いテキストの長さは、変更される前のテキストでのテキストの前後のバッファー位置の差で与えられる。変更されたテキストでは、その長さは単に最初の2つの引数の差で与えられる。

これらの関数は*Messages*バッファーへのメッセージの出力では呼び出されず、特定の処理用にEmacsが作成する内部的なバッファーのようなLispプログラムからは可視であるべきではないバッファーへの変更でも呼び出されません。

バッファーを変更するプリミティブのほとんどは、バランスされたカッコ内でのそれぞれの変更にたいしてbefore-change-functionsafter-change-functionsを1回呼び出し、これらのフックにたいする引数は行われた変更を正確に区切ります。しかしフック関数は常にこのように行われると信頼すべきではありません。なぜなら複雑なプリミティブのいくつかは変更を行う前にbefore-change-functionsを呼び出してから、プリミティブが行なった個別の変更の数にもとづいてafter-change-functionsを0回以上呼び出すからです。これが発生した場合には、before-change-functionsの引数は個別の変更が行われたリージョンを囲むでしょうが、そのようなリージョンが最小である必要はなく、連続したafter-change-functions呼び出しそれぞれにたいする引数は変更されたテキスト部分を正確に区切るでしょう。一般的には、before-changeかafter-changeのいずれかのフックを使用して、両方は使用しないことを推奨します。

Macro: combine-after-change-calls body…

このマクロは普通にbodyを実行するが、もしそれが安全なように見えるなら一連の複数の変更にたいして正に一度、after-change関数を呼び出すようにアレンジする。

そのバッファーの同じ領域内でプログラムが複数のテキスト変更を行う場合には、その部分のプログラムの周囲でマクロcombine-after-change-callsを使用することにより、after-changeフック使用中の実行がかなり高速になり得る。after-changeフックが最終的に呼び出される際には、その引数はcombine-after-change-callsのbody内で行われたすべての変更にたいして含むバッファーの範囲を指定する。

警告: フォームcombine-after-change-callsのbody内でafter-change-functionsの値を変更してはならない。

警告: 組み合わされた変更がバッファーの広い範囲に点在してに出現する場合でも、これは依然として機能するが推奨できない。なぜならこれは、ある変更フック関数を非効率的な挙動へと導くかもしれないからである。

Macro: combine-change-calls beg end body…

これは通常のようにbodyを実行するが、before-change-functionsおよびafter-change-functionsの呼び出しをトリガーしないすべてのバッファー変更を除く。かわりにbegendで囲まれるリージョンにたいしてこれらのフックそれぞれを1回呼び出し、bodyが変更するサイズを反映したパラメーターをafter-change-functionsに与える。

このマクロの結果はbodyのリターンした結果。

このマクロはある関数がバッファーにたいして繰り返し多数の変更を行う可能性があり、このマクロ以外では個別のバッファー変更ごとにそれらの変更フックを実行するために実行に長時間を要する際に有用。Emacs自身は、たとえばコマンドcomment-regionuncomment-regionの中でこのマクロを使用している。

警告: body内でbefore-change-functionsafter-change-functionの値を変更してはならない。

警告: begendで指定したリージョン外部でのバッファー変更は何も行ってはならない。

Variable: first-change-hook

この変数は以前は未変更の状態だったバッファーが変更された際は常に実行されるノーマルフック。

Variable: inhibit-modification-hooks

この変数が非nilならすべての変更フックは無効。それらは何も実行されない。これはこのセクションで説明したすべてのフック変数、同様に特定のスペシャルテキストプロパティ(特殊な意味をもつプロパティを参照)とオーバーレイプロパティ(オーバーレイのプロパティを参照)にアタッチされたフックに影響を与える。

これらの同一フック変数上の関数の実行の間、バッファー変更によるデフォルトの変更フックが他の変更フック実行中に実行されないように、この変数は非nilにバインドされる。それ自体が変更フックから実行される特定のコード断片内で変更フックを実行したければ、inhibit-modification-hooksnilにローカルに再バインドすること。しかしこれを行うことで変更フックが再帰的に呼び出されるかもしれないのでそれに備えること(たとえばフックが何も行わないようにいくつかの変数をバインドする)。

バッファーのテキストコンテンツに永続的な変更をもたらさない変更(たとえばフェイス変更や一時的な変更)だけにこの変数をバインドすることを推奨する。一連の変更の間は変更フックを遅延させる必要がある(通常は性能上な理由による)なら、かわりにcombine-change-callscombine-after-change-callsを使用すること。