22.2.4 Указание режимов для команд

Многие команды в 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). Такие команды никогда не следует помечать как специфичные для режима, поскольку пользователь может вызвать их практически из любого контекста.