Цикл команд Emacs запускается автоматически при старте Emacs. Этот вызов цикла команд на верхнем уровне никогда не завершается; он продолжает работать до тех пор, пока работает Emacs. Программы на Lisp также могут вызывать цикл команд. Поскольку это приводит к более чем одному активации цикла команд, мы называем это рекурсивным редактированием. Уровень рекурсивного редактирования имеет эффект приостановки любой команды, которая его вызвала, и позволяет пользователю выполнить произвольное редактирование перед возобновлением этой команды.
Команды, доступные во время рекурсивного редактирования, те же самые, что и в основном цикле редактирования, и определены в картах клавиш. Только несколько специальных команд выходят из уровня рекурсивного редактирования; остальные возвращаются к уровню рекурсивного редактирования, когда завершаются. (Специальные команды для выхода всегда доступны, но ничего не делают, когда рекурсивное редактирование не выполняется.)
Все циклы команд, включая рекурсивные, настраивают обработчики ошибок общего назначения, чтобы ошибка в команде, запущенной из цикла команд, не приводила к выходу из цикла.
Ввод в минибуфере — это особый вид рекурсивного редактирования. Он имеет несколько особых особенностей, таких как включение отображения минибуфера и окна минибуфера, но их меньше, чем вы могли бы предположить. Некоторые клавиши ведут себя по-разному в минибуфере, но это происходит только из-за локальной карты минибуфера; если вы переключаете окна, вы получаете обычные команды Emacs.
Чтобы вызвать уровень рекурсивного редактирования, вызовите функцию
recursive-edit. Эта функция содержит цикл команд; она также
содержит вызов catch с тегом exit, что
позволяет выйти из уровня рекурсивного редактирования, бросая в
exit (см. Явные нелокальные выходы: catch и throw).
Бросание значения t заставляет recursive-edit
завершиться, и управление возвращается к циклу команд на уровень выше.
Это называется прерыванием, и это делается с помощью
C-] (abort-recursive-edit). Аналогично, вы
можете бросить строковое значение, чтобы заставить recursive-edit
сигнализировать об ошибке, выводя эту строку в качестве сообщения. Если вы
бросаете функцию, recursive-edit вызовет ее без
аргументов перед возвратом. Бросание любого другого значения заставит
recursive-edit нормально вернуться к функции, которая его
вызвала. Команда C-M-c (exit-recursive-edit)
делает это.
Большинство приложений не должны использовать рекурсивное редактирование, за исключением использования минибуфера. Обычно пользователю удобнее, если вы временно меняете основной режим текущего буфера на специальный основной режим, который должен иметь команду для возврата к предыдущему режиму. (Команда e в Rmail использует эту технику.) Или, если вы хотите предоставить пользователю другой текст для рекурсивного редактирования, создайте и выберите новый буфер в специальном режиме. В этом режиме определите команду для завершения обработки и возврата к предыдущему буферу. (Команда m в Rmail делает это.)
Рекурсивное редактирование полезно при отладке. Вы можете вставить вызов
debug в определение функции в качестве своего рода
точки останова, чтобы вы могли осмотреться, когда функция до нее дойдет.
debug вызывает рекурсивное редактирование, но также предоставляет
другие функции отладчика.
Уровни рекурсивного редактирования также используются, когда вы вводите
C-r в query-replace или используете C-x q
(kbd-macro-query).
Эта функция вызывает цикл команд редактора. Она вызывается автоматически при инициализации Emacs, чтобы позволить пользователю начать редактирование. Когда она вызывается из программы на Lisp, она входит в уровень рекурсивного редактирования.
Если текущий буфер не совпадает с буфером выбранного окна,
recursive-edit сохраняет и восстанавливает текущий буфер.
В противном случае, если вы переключаете буферы, буфер, на который вы
переключились, становится текущим после возврата recursive-edit.
В следующем примере функция simple-rec сначала
перемещает курсор на одно слово, затем входит в рекурсивное редактирование,
выводя сообщение в область эхо. Затем пользователь может выполнить любое
желаемое редактирование, а затем нажать C-M-c, чтобы выйти
и продолжить выполнение simple-rec.
(defun simple-rec ()
(forward-word 1)
(message "Recursive edit in progress")
(recursive-edit)
(forward-word 1))
⇒ simple-rec
(simple-rec)
⇒ nil
Эта функция выходит из самого внутреннего рекурсивного редактирования
(включая ввод в минибуфере). Ее определение фактически равно
(throw 'exit nil).
Эта функция прерывает команду, запросившую самое внутреннее
рекурсивное редактирование (включая ввод в минибуфере), сигнализируя
quit после выхода из рекурсивного редактирования. Ее
определение фактически равно
(throw 'exit t). См. Выход.
Эта функция выходит из всех уровней рекурсивного редактирования; она не возвращает значение, поскольку полностью выходит из любого вычисления непосредственно обратно в основной цикл команд.
Эта функция возвращает текущую глубину рекурсивного редактирования. Когда рекурсивное редактирование не активно, она возвращает 0.