Указание режимов для команд
Многие команды в Emacs являются общими и не привязаны к какому-либо конкретному режиму. Например, M-x kill-region можно использовать практически в любом режиме, имеющем редактируемый текст, а команды, отображающие информацию (например, M-x list-buffers), можно использовать практически в любом контексте.
Однако многие другие команды конкретно связаны с режимом и не имеют смысла вне этого контекста. Например, M-x
dired-diff просто выдаст ошибку, если используется вне буфера Dired.
Поэтому в Emacs есть механизм для указания режима (или режимов), к которому «принадлежит» команда:
(defun dired-diff (...) ... (interactive "p" dired-mode) ...)
Это пометит команду как применимую только к dired-mode (или к любым режимам, которые являются производными от dired-mode). В форму interactive можно добавить любое количество режимов.
Указание режимов влияет на завершение команд в M-S-x (execute-extended-command-for-buffer, см. Интерактивный вызов). Это также может повлиять на завершение в M-x, в зависимости от значения read-extended-command-predicate.
Например, при использовании предиката command-completion-default-include-p в качестве значения read-extended-command-predicate, M-x не будет отображать команды, которые были помечены как применимые к определённому режиму (если вы, конечно, не находитесь в буфере, использующем этот режим). Это относится как к основным, так и к дополнительным режимам. (В противоположность этому, M-S-x всегда исключает неприменимые команды из кандидатов на завершение.)
По умолчанию, read-extended-command-predicate равно nil, и завершение в M-x перечисляет все команды, которые соответствуют введённому пользователем тексту, независимо от того, помечены ли эти команды как применимые к режиму текущего буфера или нет.
Пометка команд как применимых к режиму также позволит C-h m отобразить эти команды (если они не привязаны к каким-либо клавишам).
Если использование этой расширенной формы interactive неудобно (потому что код должен работать в более старых версиях Emacs, которые не поддерживают расширенную форму interactive), можно использовать вместо этого следующее эквивалентное объявление (см. Форму объявления):
(declare (modes dired-mode))
Выбор команд, которые нужно пометить режимами, в некоторой степени вопрос вкуса, но команды, которые явно не работают вне режима, должны быть помечены. Это относится к командам, которые выдадут ошибку, если их вызвать из другого места, а также к командам, которые являются разрушительными, если их вызвать из неожиданного режима. (Это обычно включает большинство команд, написанных для специальных (т. е. нередактирующих) режимов.)
Некоторые команды могут быть безвредными и «работать», когда их вызывают из других режимов, но их всё равно следует отмечать режимом, если они фактически не имеют большого смысла для использования в другом месте. Например, многие специальные режимы имеют команды для выхода из буфера, привязанные к q, и могут просто вывести сообщение, например, "До свидания из этого режима", а затем вызвать kill-buffer. Эта команда будет «работать» из любого режима, но маловероятно, что кто-то захочет использовать её вне контекста этого специального режима.
Многие режимы имеют набор различных команд, которые запускают режим различными способами (например, eww-open-in-new-buffer и eww-open-file). Такие команды никогда не следует отмечать как специфичные для режима, так как они могут быть вызваны пользователем практически из любого контекста.
Обратите внимание, что указание режимов команд не поддерживается в нативно скомпилированных функциях в Emacs 28.1 (но это исправлено в более поздних версиях Emacs). Это означает, что read-extended-command-predicate тоже не поддерживается в сборках с нативным компилированием.
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/Command-Modes.html