22.2.4 Specifying Modes For Commands

Many commands in Emacs are general, and not tied to any specific mode. For instance, M-x kill-region can be used in pretty much any mode that has editable text, and commands that display information (like M-x list-buffers) can be used in pretty much any context.

Many other commands, however, are specifically tied to a mode, and make no sense outside of that context. For instance, M-x dired-diff will just signal an error if used outside of a Dired buffer.

Emacs therefore has a mechanism for specifying what mode (or modes) a command “belongs” to:

(defun dired-diff (...)
  ...
  (interactive "p" dired-mode)
  ...)

This will mark the command as applicable to dired-mode only (or any modes that are derived from dired-mode). Any number of modes can be added to the interactive form.

Specifying modes affects command completion in M-S-x (execute-extended-command-for-buffer, see Interactive Call). It may also affect completion in M-x, depending on the value of read-extended-command-predicate.

For instance, when using the command-completion-default-include-p predicate as the value of read-extended-command-predicate, M-x won’t list commands that have been marked as being applicable to a specific mode (unless you are in a buffer that uses that mode, of course). This goes for both major and minor modes. (By contrast, M-S-x always omits inapplicable commands from the completion candidates.)

By default, read-extended-command-predicate is nil, and completion in M-x lists all the commands that match what the user has typed, whether those commands are or aren’t marked as applicable to the current buffer’s mode.

Marking commands to be applicable to a mode will also make C-h m list these commands (if they aren’t bound to any keys).

If using this extended interactive form isn’t convenient (because the code is supposed to work in older versions of Emacs that don’t support the extended interactive form), the following equivalent declaration (see The declare Form) can be used instead:

(declare (modes dired-mode))

Which commands to tag with modes is to some degree a matter of taste, but commands that clearly do not work outside of the mode should be tagged. This includes commands that will signal an error if called from somewhere else, but also commands that are destructive when called from an unexpected mode. (This usually includes most of the commands that are written for special (i.e., non-editing) modes.)

Some commands may be harmless, and “work” when called from other modes, but should still be tagged with a mode if they don’t actually make much sense to use elsewhere. For instance, many special modes have commands to exit the buffer bound to q, and may not do anything but issue a message like "Goodbye from this mode" and then call kill-buffer. This command will “work” from any mode, but it is highly unlikely that anybody would actually want to use the command outside the context of this special mode.

Many modes have a set of different commands that start the mode in different ways (e.g., eww-open-in-new-buffer and eww-open-file). Commands like that should never be tagged as mode-specific, as they can be issued by the user from pretty much any context.