GNU Emacs 32.0.50 (9008bf64c3) のマニュアルを PLaMo 翻訳で機械翻訳したものです。誤訳を含むことがあります。原文: https://www.gnu.org/software/emacs/manual/html_node/elisp/Quitting.html ・ emacs-doc.conao3.com

22.11 退職

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の内部状態に不整合が生じる可能性があるためです。安全な場所まで終了を遅らせることで、終了によってEmacsがクラッシュすることはありません。

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)))
      ...set the variable code...)
    code))
変数: quit-flag

この変数が nil 以外の場合、inhibit-quit が nil 以外でない限り、Emacs は直ちに終了します。通常、C-g と入力すると、inhibit-quit に関わらず quit-flag が nil 以外に設定されます。

変数: inhibit-quit

この変数は、quit-flag に nil 以外の値が設定された際に Emacs を終了させるかどうかを決定します。inhibit-quit が nil 以外の場合、quit-flag に特別な効果はありません。

マクロ: with-local-quit body…

このマクロはbody形式を順次実行しますが、この構文の外でinhibit-quitがnon-nilであったとしても、body内では少なくともローカルに終了することが可能です。終了して抜け出さない限り、bodyにある最後の形式の値を返し、終了した場合はnilを返します。

inhibit-quit が with-local-quit への進入時に nil である場合、body のみが実行され、quit-flag を設定すると通常の終了が発生します。しかし、inhibit-quit が nil 以外であるため通常の終了が遅延している場合、nil 以外である quit-flag が特殊な種類のローカル終了をトリガーします。これにより body の実行が終了し、quit-flag が依然として nil ではない状態で with-local-quit 本体から抜け出すため、それが許可され次第、別の(通常の)終了が発生します。body の開始時点で quit-flag がすでに nil 以外である場合、ローカル終了が直ちに発生し、本体は全く実行されません。

このマクロは主に、タイマー、プロセスフィルタ、プロセスセンチネル、pre-command-hook、post-command-hook、および通常inhibit-quitがtにバインドされているその他の箇所から呼び出せる関数で有用です。

コマンド: keyboard-quit

この関数は、quit 条件を (signal 'quit nil) で通知します。これは終了処理が行う動作と同じです。(Errors の signal を参照してください。)

キーボードマクロの定義や実行を中断せずに終了するには、minibuffer-quit 条件を指定できます。これは quit 条件とほぼ同様の効果がありますが、コマンドループ内のエラー処理によって、キーボードマクロの定義や実行を終了させることなく処理される点が異なります。

終了に使用する文字として C-g 以外を指定できます。入力モード の関数 set-input-mode を参照してください。