Spec-Zone.ru › Elisp

Выход

Ввод C-g во время выполнения функции Lisp вызывает выход 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.

Вы можете предотвратить выход в части функции Lisp, присвоив переменной inhibit-quit значение, отличное от nil. Затем, хотя C-g всё ещё устанавливает quit-flag в t, как обычно, обычный результат этого — выход — предотвращается. В конечном итоге inhibit-quit вернётся к значению nil, например, при размотке привязки в конце формы let. В это время, если quit-flag всё ещё отлично от nil, запрашиваемый выход происходит немедленно. Это поведение идеально подходит, когда необходимо убедиться, что выход не произойдёт внутри критической секции программы.

В некоторых функциях (например, read-quoted-char) C-g обрабатывается особым способом, не связанным с выходом. Это делается путём чтения ввода с привязанным к нему inhibit-quit и значением t, и установкой quit-flag в nil до того, как inhibit-quit вернётся к значению 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, то Emacs выходит немедленно, если inhibit-quit имеет значение, отличное от nil. Ввод C-g обычно устанавливает quit-flag в значение, отличное от nil, независимо от inhibit-quit.

Переменная: inhibit-quit

Эта переменная определяет, должен ли Emacs выходить, когда quit-flag установлено в значение, отличное от nil. Если inhibit-quit имеет значение, отличное от nil, то quit-flag не имеет специального эффекта.

Макрос: with-local-quit тело…

Этот макрос последовательно выполняет формы тело, но позволяет выходу, по крайней мере локально, внутри тело, даже если inhibit-quit имело значение, отличное от nil за пределами этого конструкта. Он возвращает значение последней формы в тело, если не произошло выхода из-за выхода, в противном случае он возвращает nil.

Если inhibit-quit равно nil при входе в with-local-quit, он выполняет только тело, а установка quit-flag вызывает обычный выход. Однако, если inhibit-quit имеет значение, отличное от nil, так что обычный выход задерживается, отличное от nil значение quit-flag вызывает специальный вид локального выхода. Это завершает выполнение тело и выходит из тела with-local-quit с quit-flag всё ещё имеющим значение, отличное от nil, так что другой (обычный) выход произойдёт, как только это будет разрешено. Если quit-flag уже имеет значение, отличное от nil в начале тело, локальный выход происходит немедленно, и тело не выполняется вообще.

Этот макрос в основном полезен в функциях, которые могут вызываться из таймеров, фильтров процессов, сторожей процессов, pre-command-hook, post-command-hook и других местах, где inhibit-quit обычно привязан к значению t.

Команда: keyboard-quit

Эта функция сигнализирует условие quit с значением (signal 'quit nil). Это то же самое, что и выход. (См. signal в Ошибка.)

Чтобы выйти без прерывания определения или выполнения макроса клавиатуры, можно сигнализировать условие minibuffer-quit. Это почти тот же эффект, что и условие quit, за исключением того, что обработка ошибок в цикле команд обрабатывает его без выхода из определения или выполнения макроса клавиатуры.

Можно указать другой символ, кроме C-g, для выхода. См. функцию set-input-mode в Режимах ввода.

Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Quitting.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API