Next: Prefix Command Arguments, Previous: Waiting, Up: 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
を参照してください。