Многие команды в 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):
(declare (modes dired-mode))
Какие команды помечать режимами — в некоторой степени дело вкуса, но команды, которые явно не работают вне режима, следует помечать. Это включает команды, которые выдают ошибку при вызове из другого места, а также команды, которые являются разрушительными при вызове из неожиданного режима. (Обычно это включает большинство команд, написанных для специальных (то есть нередактируемых) режимов.)
Некоторые команды могут быть безвредными и «работать» при вызове из других
режимов, но их всё равно следует помечать режимом, если они не
имеют особого смысла при использовании в другом месте. Например, во многих
специальных режимах есть команды для выхода из буфера, привязанные к q,
которые могут не делать ничего, кроме выдачи сообщения типа «Goodbye from this mode»
и вызова kill-buffer. Эта команда будет «работать» в любом режиме,
но крайне маловероятно, что кто-то захочет использовать эту
команду вне контекста данного специального режима.
Во многих режимах есть набор различных команд, которые запускают режим
разными способами (например, eww-open-in-new-buffer и
eww-open-file). Такие команды никогда не следует помечать как
специфичные для режима, поскольку пользователь может вызвать их практически из любого
контекста.