Emacsが動作を始めると、Emacsのコマンドループに自動的に入ります。 このトップレベルのコマンドループからはけっして抜けることはなく、 Emacsが動いている限り動作し続けます。 Lispプログラムからコマンドループを起動することもできます。 そうすると、活性なコマンドループが複数作られることになるので、 それを再帰編集(recursive editing)と呼びます。 再帰編集レベルには、それを起動したコマンドを一時休止させ、 当該コマンドを再開するまでユーザーにどんな編集でも許す効果があります。
再帰編集中に利用可能なコマンドは、トップレベルのコマンドループと 同じものでありキーマップで定義されます。 再帰編集を抜けるための数個の特別なコマンドがあり、 完了すると再帰編集レベルから抜ける別のコマンドもあります。 (再帰編集を抜けるコマンドはつねに利用可能であるが、 再帰編集中でないとなにも行わない。)
再帰編集を含むすべてのコマンドループでは、 コマンドループから実行したコマンドのエラーによって コマンドループから抜け出さないように汎用目的のエラーハンドラを設定します。
ミニバッファでの入力は、特別な種類の再帰編集です。 これには、ミニバッファやミニバッファ用ウィンドウを表示するなどの特別な 処理がありますが、読者が考えるよりは少ないのです。 ミニバッファでは特別なふるまいをするキーもありますが、 それらはミニバッファのローカルマップによるものです。 ウィンドウを切り替えると、Emacsの普通のコマンドを使えます。
再帰編集レベルを起動するには、関数recursive-edit
を呼び出します。
この関数にはコマンドループが含まれています。
さらに、exit
を伴ったcatch
の呼び出しもあり、
これにより、exit
へ投げることで
再帰編集レベルから抜け出せるようになっています
(see Catch and Throw)。
t
以外の値を投げると、recursive-edit
は、
呼び出し側の関数へ普通に戻ります。
コマンドC-M-c(exit-recursive-edit
)は、これを行います。
値t
を投げるとrecursive-edit
に中断を引き起こし、
1つ上のレベルのコマンドループへ制御を戻します。
これを強制終了(aborting)と呼び、
C-](abort-recursive-edit
)で行えます。
ミニバッファを使う場合を除いて、ほとんどのアプリケーションでは 再帰編集を使うべきではありません。 カレントバッファのメジャーモードを 一時的な特別なメジャーモードに変更するほうが、 一般にはユーザーにとってより便利です。 ただし、当該メジャーモードには、 まえのモードに戻るコマンドを用意しておきます。 (rmailのコマンドeは、この方式を使っている。) あるいは、『再帰的に』編集する別のテキストをユーザーに与えたい場合には、 特別なモードの新たなバッファを作成してそれを選択します。 当該モードには、処理を終えてまえのバッファに戻るコマンドを 定義しておきます。 (rmailのコマンドmは、このようにする。)
再帰編集はデバッグに便利です。
ブレークポイントの一種として関数定義に
debug
の呼び出しを挿入しておくと、
その箇所に達したときにいろいろと調べられます。
debug
は再帰編集を起動しますが、デバッガとしての機能も提供します。
query-replace
でC-rを打ったり、
C-x q(kbd-macro-query
)を使ったときにも
再帰編集レベルが使われます。
この関数はエディタコマンドループを起動する。 Emacsの初期化過程で自動的に呼び出され、ユーザーが編集できるようにする。 Lispプログラムから呼ばれると、再帰編集レベルに入る。
以下の例では、関数
simple-rec
は、まず1単語分ポイントを進め、 エコー領域にメッセージを表示して再帰編集に入る。 そうすると、ユーザーは望むことはなんでもできるようになり、 (再帰編集を)抜けるためにC-M-cを打つと、simple-rec
の実行を継続する。(defun simple-rec () (forward-word 1) (message "Recursive edit in progress") (recursive-edit) (forward-word 1)) ⇒ simple-rec (simple-rec) ⇒ nil
この関数は、(ミニバッファでの入力を含む)もっとも内側の再帰編集から抜ける。 その関数定義は実質的には
(throw 'exit nil)
である。
この関数は、再帰編集から抜けたあとで
quit
を通知することで、 (ミニバッファでの入力を含む)もっとも内側の再帰編集を 要請したコマンドを強制終了する。 その関数定義は実質的には(throw 'exit t)
である。 see Quitting。