次: Prefix Command Arguments, 前: Waiting, 上: Command Loop
Lisp関数が動作中にC-gを打つと、 Emacsがなにを行っていても中断を引き起こします。 つまり、もっとも内側の活性なコマンドループに制御が戻ります。
コマンドループがキーボード入力を待っているときにC-gを打っても、
中断を引き起こさずに、普通の入力文字として動作します。
もっとも単純な場合、C-gはコマンドkeyboard-quitを実行しますが、
その効果は中断を引き起こすことですから、読者には区別できないはずです。
しかし、プレフィックスキーに続けてC-gを打つと、
それらは組み合わされて未定義キーになります。
その効果は、前置引数を含めてプレフィックスキーを取り消します。
ミニバッファでは、C-gには別の定義があって、 ミニバッファを強制終了させます。 つまり、ミニバッファから抜け出て中断します。 (単に中断したのでは、ミニバッファ内で コマンドループに戻るだけである。) コマンドループで入力を読んでいるときにC-gで直接中断しない理由は、 このようにミニバッファでその意味を再定義できるようにするためです。 ミニバッファでは、プレフィックスキーに続くC-gは再定義してなく、 プレフィックスキーと前置引数を取り消すという通常の効果を持ちます。 C-gがつねに直接中断するのでは、このようにすることさえ不可能です。
C-gが直接に中断するときには、
変数quit-flagにtを設定します。
Emacsはこの変数を適切なときに検査しnilでないと中断します。
したがって、quit-flagにnil以外を設定すると
中断を引き起こします。
Cのコードのレベルでは、どこでも中断できるわけではありません。
quit-flagを検査している特別な箇所だけです。
このようにするのは、それ以外の箇所で中断すると
Emacsの内部状態に矛盾をきたす可能性があるからです。
中断は安全な場所まで延期されるので、
中断によってEmcasがクラッシュすることはありません。
read-key-sequenceやread-quoted-charなどのある種の関数は、
入力を待っている場合であっても中断を完全に抑制します。
中断するかわりに、C-gは入力として働きます。
read-key-sequenceの場合、コマンドループにおいて
C-gの特別なふるまいをもたらします。
read-quoted-charの場合、
C-qでC-gをクォートできるようになります。
変数inhibit-quitにnil以外の値を束縛することで
Lisp関数のある部分において中断を抑制できます。
そうすると、C-gはそれでもいつもどおり
quit-flagをtにしますが、
その通常の結果である中断は抑制されます。
最終的にフォームletの終りで束縛が解除されるなどして
inhibit-quitが再度nilになります。
その時点でもquit-flagがnil以外であると
要求した中断がただちに起こります。
このふるまいは、プログラムの『臨界領域』では
中断が起こらないことを保証する理想的なものです。
(read-quoted-charなどの)ある種の関数では、
C-gは特別に処理され中断を引き起こしません。
inhibit-quitにtを束縛して入力を読み取り、
inhibit-quitが再度nilになるまえに
quit-flagをnilにすることでそのようにします。
これをread-quoted-charの定義の以下の抜粋で示しましょう。
最初の入力文字のあとで通常の中断を許す方法も示しています。
(defun read-quoted-char (&optional prompt)
"...documentation..."
(let ((message-log-max nil) done (first t) (code 0) char)
(while (not done)
(let ((inhibit-quit first)
...)
(and prompt (message "%s-" prompt))
(setq char (read-event))
(if inhibit-quit (setq quit-flag nil)))
...変数codeに設定する...)
code))
inhibit-quitがnilであれば、 この変数がnil以外であるとEmacsはただちに中断する。 C-gは、inhibit-quitに関わらず、 通常、quit-flagにnil以外を設定する。
この変数は、
quit-flagがnil以外の値に設定されたときに Emacsが中断すべきかどうかを決定する。inhibit-quitがnil以外であると、quit-flagに特別な意味はない。
中断として使うC-g以外の特殊文字を使えます。
Terminal Inputの関数set-input-modeを参照してください。