Next: , Previous: , Up: Command Loop   [Contents][Index]


20.13 Recursive Editing

Emacsスタートアップ時に、自動的にEmacsコマンドループにエンターします。このトップレベルのコマンドループ呼び出しは決してexitせず、Emacs実行中は実行を続けます。Lispプログラムもコマンドループを呼び出せます。これは複数のコマンドループを活性化するため、これを再帰編集(recursive editing)と呼んでいます。再帰編集レベルは、呼び出したコマンドが何であれそれをサスペンドして、そのコマンドを再開する前にユーザーが任意の編集を行うことを可能にする効果をもちます。

再帰編集の間に利用可能なコマンドは、トップレベルの編集ループ内で利用できるコマンドと同じであり、キーマップ内で定義されます。数少ない特別なコマンドだけが再帰編集レベルをexitし、他のコマンドは再帰編集レベルが終了したときに再帰編集レベルからリターンします(exitするための特別なコマンドは常に利用できますが、再帰編集が行われていないときは何も行いません)。

再帰コマンドループを含むすべてのコマンドループは、コマンドループから実行されたコマンド内のエラーによりそのループをexitしないように、汎用エラーハンドラーをセットアップします。

ミニバッファー入力は、特殊な再帰編集です。これは、ミニバッファーとミニバッファーウィンドウの表示を有効にするなどの欠点をもちますが、それはあなたが思うより少ないでしょう。ミニバッファー内では特定のキーの振る舞いが異なりますが、これははミニバッファーのローカルマップによるものです。ウィンドウを切り替えれば、通常のEmacsコマンドを使用できます。

再帰編集レベルを呼び出すには、関数をrecursive-editを呼び出します。この関数はコマンドループを含んでいます。さらにexitをthrowすることにより再帰編集レベルのexitを可能にする、タグexitをともなうcatch呼び出しも含んでいます(Catch and Throwを参照)。t以外の値をthrowした場合、recursive-editは通常それを呼び出した関数にリターンします。コマンドC-M-c(exit-recursive-edit)がこれを行います。値tをthrowすることによりrecursive-editがquitされるので、1レベル上位のコマンドループに制御がリターンされます。これはabortと呼ばれ、C-](abort-recursive-edit)がこれを行います。

ほとんどのアプリケーションはミニバッファー使用の一部として使用する場合を除き、再帰編集を使用するべきではありません。カレントバッファーのメジャーモードから、特殊なメジャーモードに一時的に変更する場合に、そのモードに戻るコマンドをもつ必要があるときは、通常は再帰編集のほうが便利です(Rmailのeコマンドはこのテクニックを使用している)。またはユーザーが新たなバッファーの特殊なモードで、異なるテキストを“再帰的”に編集・作成・選択できるようにしたい場合が該当します。このモードでは処理を完了させるコマンドを定義して、前のバッファーに戻ります(Rmailのmコマンドはこれを使用している)。

再帰編集はデバッグに便利です。一種のブレークポイントとして関数定義内にdebugを挿入して、関数がそこに達したときにその箇所を調べることができます。debugは再帰編集を呼び出しますが、デバッガのその他の機能も提供します。

query-replace内でC-rをタイプしたときやC-x q(kbd-macro-query)を使用したときも、再帰編集レベルが使用されます。

Command: recursive-edit

この関数はエディターコマンドループを呼び出す。これはユーザーに編集を開始させるために、Emacsの初期化により自動的に呼び出されるLispプログラムから呼び出されたときは、再帰編集レベルにエンターする。

カレントバッファーが選択されたウィンドウのバッファーと異なる場合、recursive-editはカレントバッファーの保存とリストアを行う。それ以外では、バッファーを切り替えた場合には、recursive-editがリターンした後その切り替えたバッファーがカレントになる。

以下の例では、関数simple-recが最初にポイントを1単語分進めてからメッセージをエコーエリアにプリントして再帰編集にエンターする。その後ユーザーは望む編集を行い、C-M-cをタイプすれば再帰編集をexitして、simple-recの実行を継続できる。

(defun simple-rec ()
  (forward-word 1)
  (message "Recursive edit in progress")
  (recursive-edit)
  (forward-word 1))
     ⇒ simple-rec
(simple-rec)
     ⇒ nil
Command: exit-recursive-edit

この関数は最内の再帰編集(ミニバッファー入力を含む)からexitする。関数の実質的な定義は(throw 'exit nil)である。

Command: abort-recursive-edit

この関数は、再帰編集をexitした後にquitをシグナルすることにより、最内の再帰編集(ミニバッファー入力を含む)を要求したコマンドをabortする。関数の実質的な定義は(throw 'exit t)である。Quittingを参照のこと。

Command: top-level

この関数はすべての再帰編集レベルをexitする。これはすべての計算を直接抜け出してメインのコマンドループに戻り、値をリターンしない。

Function: recursion-depth

この関数は再帰編集のカレントの深さをリターンする。アクティブな再帰編集が存在しない場合は、0をリターンする。