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


21.11 quit

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-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なら、Emacsは即座に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のbodyをexitするので、許され次第(通常の)別のquitが発生する。bodyの先頭ですでにquit-flagが非nilなら即座にローカルquitが発生して結局bodyは実行されない。

このマクロは主にタイマー、プロセスフィルター、プロセスセンチネル、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を参照してください。