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


20.11 Quitting

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-ggヴぁ常に直接quitするなら、これは不可能でしょう。

C-gが直接quitを行うときは、変数quit-flagtにセットすることによりそれを行います。Emacsは適切なときにこの変数をチェックして、nilでない場合はquitします。どのような方法でも、quit-flagを非nilにセットするとquitが発生します。

Cコードのレベルでは、どこでもquitを発生させることはできず、quit-flagをチェックする特別な場所でのみquitが発生します。この理由は、他の場所でquitすると、Emacsの内部状態が矛盾が生じるかもしれないからです。安全な場所までquitが遅延されるので、quitがEmacsをクラッシュさせることがなくなります。

read-key-sequenceread-quoted-charのような特定の関数は、たとえ入力を待機中でもquitを抑制します。quitするかわりに、C-gは要求された入力として処理されます。read-key-sequenceの場合、これはコマンドループ内でのC-gの特別な振る舞いを引き起こすのに役立ちます。read-quoted-charの場合、これはC-gをクォートするのにC-qを使用できるようにします。

変数inhibit-quitを非nil値にバインドすることにより、Lisp関数の一部でquitを抑止できます。その場合は、quit-flagtにセットされていても、C-gの通常の結果であるquitは抑止されます。letフォームの最後でこのバインディングがunwindされるなどして、結果としてinhibit-quitは再びnilになります。このときquit-flagnilの場合には、即座に要求されたquitが発生します。この挙動は、プログラム中の“クリティカルセクション”内でquitが発生しないことを確実にしたいときに理想的です。

(read-quoted-charのような)いくつかの関数では、quitを起こさない特別な方法でC-gが処理されます。これはinhibit-quittにバインドして入力を読み取り、再びinhibit-quitnilになる前にquit-flagnilにセットすることにより行われます。以下は、これを行う方法を示すための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))
Variable: quit-flag

この変数が非nilinhibit-quitnilの場合、macsは即座にquitする。C-gをタイプすると、通常はinhibit-quitとは無関係にquit-flagを非nilにセットする。

Variable: inhibit-quit

この変数は、quit-flagが非nilにセットされているときEmacsがquitするかどうかを決定する。inhibit-quitが非nilの場合、quit-flagは特に効果がない。

Macro: with-local-quit body…

このマクロはbodyを順番に実行するが、たとえこの構成の外部でinhibit-quitが非nilでも、少なくともローカルにbody内でのquitを許す。このマクロはquitによりexitした場合はnil、それ以外はbody内の最後のフォームの値をリターンする。

inhibit-quitnilの場合with-local-quitへのエントリーでbodyだけが実行され、quit-flagをセットすることにより通常のquitが発生する。しかし通常のquitが遅延されるようにinhibit-quitが非nilにセットされている場合、非nilquit-flagは特別な種類のローカルquitを引き起こす。これはbodyの実行を終了して、quit-flagを非nilのままでwith-local-quitボディーをexitするので、許され次第(通常の)他のquitが発生する。bodyの先頭ですでにquit-flagが非nilの場合、即座にローカルquitが発生して結局ボディーは実行されない。

このマクロは主にタイマー、プロセスフィルター、プロセスセンチネル、pre-command-hookpost-command-hook、およびinhibit-quitが通常はtにバイドされている場所で役に立つ。

Command: keyboard-quit

この関数は(signal 'quit nil)によりquit条件をシグナルする。これはquitが行うことと同じである(Errorssignalを参照)。

quitに使用するC-g以外の文字を指定できます。Input Modes内の関数set-input-modeを参照してください。