interactive
This section describes how to write the interactive
form that
makes a Lisp function an interactively-callable command, and how to
examine a command’s interactive
form.
This special form declares that a function is a command, and that it may therefore be called interactively (via M-x or by entering a key sequence bound to it). The argument arg-descriptor declares how to compute the arguments to the command when the command is called interactively.
A command may be called from Lisp programs like any other function, but then the caller supplies the arguments and arg-descriptor has no effect.
The interactive
form must be located at top-level in the
function body, or in the function symbol’s interactive-form
property (see Symbol Properties). It has its effect because the
command loop looks for it before calling the function
(see Interactive Call). Once the function is called, all its body
forms are executed; at this time, if the interactive
form
occurs within the body, the form simply returns nil
without
even evaluating its argument.
The modes list allows specifying which modes the command is meant to be used in. See Specifying Modes For Commands for more details about the effect of specifying modes, and when to use it.
By convention, you should put the interactive
form in the
function body, as the first top-level form. If there is an
interactive
form in both the interactive-form
symbol
property and the function body, the former takes precedence. The
interactive-form
symbol property can be used to add an
interactive form to an existing function, or change how its arguments
are processed interactively, without redefining the function.
There are three possibilities for the argument arg-descriptor:
nil
; then the command is called with no
arguments. This leads quickly to an error if the command requires one
or more arguments.
interactive
) optionally followed by a prompt (which
some code characters use and some ignore). Here is an example:
(interactive "P\nbFrobnicate buffer: ")
The code letter ‘P’ sets the command’s first argument to the raw command prefix (see Prefix Command Arguments). ‘bFrobnicate buffer: ’ prompts the user with ‘Frobnicate buffer: ’ to enter the name of an existing buffer, which becomes the second and final argument.
The prompt string can use ‘%’ to include previous argument values
(starting with the first argument) in the prompt. This is done using
format-message
(see Formatting Strings). For example, here is how
you could read the name of an existing buffer followed by a new name to
give to that buffer:
(interactive "bBuffer to rename: \nsRename buffer %s to: ")
If ‘*’ appears at the beginning of the string, then an error is signaled if the buffer is read-only.
If ‘@’ appears at the beginning of the string, and if the key sequence used to invoke the command includes any mouse events, then the window associated with the first of those events is selected before the command is run.
If ‘^’ appears at the beginning of the string, and if the command
was invoked through shift-translation, set the mark and activate
the region temporarily, or extend an already active region, before the
command is run. If the command was invoked without shift-translation,
and the region is temporarily active, deactivate the region before the
command is run. Shift-translation is controlled on the user level by
shift-select-mode
; see Shift Selection in The GNU
Emacs Manual.
You can use ‘*’, ‘@’, and ^
together; the order does
not matter. Actual reading of arguments is controlled by the rest of
the prompt string (starting with the first character that is not
‘*’, ‘@’, or ‘^’).
Providing point or the mark as an argument value is also common, but if you do this and read input (whether using the minibuffer or not), be sure to get the integer values of point or the mark after reading. The current buffer may be receiving subprocess output; if subprocess output arrives while the command is waiting for input, it could relocate point and the mark.
Here’s an example of what not to do:
(interactive (list (region-beginning) (region-end) (read-string "Foo: " nil 'my-history)))
Here’s how to avoid the problem, by examining point and the mark after reading the keyboard input:
(interactive (let ((string (read-string "Foo: " nil 'my-history))) (list (region-beginning) (region-end) string)))
Warning: the argument values should not include any data
types that can’t be printed and then read. Some facilities save
command-history
in a file to be read in the subsequent
sessions; if a command’s arguments contain a data type that prints
using ‘#<…>’ syntax, those facilities won’t work.
There are, however, a few exceptions: it is ok to use a limited set of
expressions such as (point)
, (mark)
,
(region-beginning)
, and (region-end)
, because Emacs
recognizes them specially and puts the expression (rather than its
value) into the command history. To see whether the expression you
wrote is one of these exceptions, run the command, then examine
(car command-history)
.
This function returns the interactive
form of function.
If function is an interactively callable function
(see Interactive Call), the value is the command’s
interactive
form (interactive spec)
, which
specifies how to compute its arguments. Otherwise, the value is
nil
. If function is a symbol, its function definition is
used.
When called on an OClosure, the work is delegated to the generic
function oclosure-interactive-form
.
Just like interactive-form
, this function takes a command and
returns its interactive form. The difference is that it is a generic
function and it is only called when function is an OClosure
(see Open Closures). The purpose is to make it possible for some
OClosure types to compute their interactive forms dynamically instead
of carrying it in one of their slots.
This is used for example for kmacro
functions in order to
reduce their memory size, since they all share the same interactive
form. It is also used for advice
functions, where the
interactive form is computed from the interactive forms of its
components, so as to make this computation more lazily and to
correctly adjust the interactive form when one of its component’s
is redefined.