Lisp関数を実行中にC-gをタイプすると、Emacsが何を行っていてもEmacsをquit(中止、終了)させます。これはアクティブなコマンドループの最内に制御がリターンすることを意味します。
コマンドループがキーボード入力の待機中にC-gをタイプしてもquitはしません。これは通常の入力文字として機能します。もっともシンプルなケースでは、通常C-gはquitの効果をもつkeyboard-quit
を実行するので区別はできません。しかしプレフィクスキーの後のC-gは、未定義のキー組み合わせになります。これはプレフィクスキーやプレフィクス引数も同様にキャンセルする効果をもちます。
ミニバッファー内ではC-gは異なる定義をもち、それはミニバッファーをabort(失敗、中止、中断)します。これは実際にはミニバッファーをexitしてquitします(単にquitするのはミニバッファー内のコマンドループにリターンするだろう)。C-gがなぜコマンドリーダーが入力読み取り時に直接quitしないかという理由は、ミニバッファー内でのC-gの意味をこの方法によって再定義可能にするためです。プレフィクスキーの後のC-gはミニバッファー内で再定義されておらず、プレフィクスキーおよびプレフィクス引数のキャンセルという通常の効果をもちます。もしC-gが常に直接quitするならこれは不可能でしょう。
C-gが直接quitを行うときは、変数quit-flag
をt
にセットすることによってそれを行います。Emacsは適切なタイミングでこの変数をチェックして、nil
でなじぇればquitします。どのような方法でもquit-flag
を非nil
にセットするとquitが発生します。
Cコードのレベルでは任意の場所でquitを発生させることはできず、quit-flag
をチェックする特別な場所でのみquitが発生します。この理由は他の場所でquitすると、Emacsの内部状態で矛盾が生じるかもしれないからです。安全な場所までquitが遅延されるので、quitがEmacsをクラッシュさせることがなくなります。
read-key-sequence
やread-quoted-char
のような特定の関数は、たとえ入力を待機中でもquitを抑制します。quitするかわりにC-gは要求された入力として処理されます。read-key-sequence
の場合、これはコマンドループ内でのC-gの特別な振る舞いを引き起こすのに役立ちます。read-quoted-char
の場合、これはC-gをクォートするのにC-qを使用できるようにします。
変数inhibit-quit
を非nil
値にバインドすることにより、Lisp関数の一部でquitを抑止できます。その場合はquit-flag
がt
にセットされていても、C-gの通常の結果であるquitは抑止されます。let
フォームの最後でこのバインディングがunwindされるなどして、結果としてinhibit-quit
は再びnil
になります。このときquit-flag
がnil
なら、即座に要求されたquitが発生します。この挙動はプログラム中のクリティカルセクション内でquitが発生しないことを確実にしたいときに理想的です。
(read-quoted-char
のような)いくつかの関数では、quitを起こさない特別な方法でC-gが処理されます。これはinhibit-quit
をt
にバインドして入力を読み取り、再びinhibit-quit
がnil
になる前にquit-flag
をnil
にセットすることにより行われます。以下はこれを行う方法を示すためのread-quoted-char
の抜粋です。この例は入力の最初の文字の後で通常のquitを許す方法も示しています。
(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))
この変数が非nil
でinhibit-quit
がnil
なら、Emacsは即座にquitする。C-gをタイプすると通常はinhibit-quit
とは無関係にquit-flag
を非nil
にセットする。
この変数はquit-flag
が非nil
にセットされているときEmacsがquitするかどうかを決定する。inhibit-quit
が非nil
ならquit-flag
に特に効果はない。
このマクロはbodyを順番に実行するが、たとえこの構文の外部でinhibit-quit
が非nil
でも、少なくともローカルにbody内でのquitを許容する。このマクロはquitによりexitしたらnil
、それ以外はbody内の最後のフォームの値をリターンする。
inhibit-quit
がnil
ならwith-local-quit
へのエントリーでbodyだけが実行され、quit-flag
をセットすることにより通常のquitが発生する。しかし通常のquitが遅延されるようにinhibit-quit
が非nil
にセットされていれば、非nil
のquit-flag
は特別な種類のローカルquitを引き起こす。これはbodyの実行を終了して、quit-flag
を非nil
のままにしてwith-local-quit
のbodyをexitするので、許され次第(通常の)別のquitが発生する。bodyの先頭ですでにquit-flag
が非nil
なら即座にローカルquitが発生して結局bodyは実行されない。
このマクロは主にタイマー、プロセスフィルター、プロセスセンチネル、pre-command-hook
、post-command-hook
、およびinhibit-quit
が通常のようにt
にバイドされている場所で役に立つ。
キーボードマクロの定義や実行をabortさせることなくquitするために、minibuffer-quit
条件をシグナルすることができます。これはキーボードマクロの定義や実行をexitせずに、コマンド内のエラーハンドラーがこの条件を処理することを除き、quit
とほとんど同じ効果をもつ。
quitに使用するC-g以外の文字を指定できます。入力のモード内の関数set-input-mode
を参照してください。