summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2023-08-15 17:08:12 +0300
committerEli Zaretskii <eliz@gnu.org>2023-08-15 17:08:12 +0300
commit221ed70b90a4af0b514634ab5765511ccae9328b (patch)
tree199585ce6208e919e07d9fb5319766ae9cd48b6e
parent32280205e2727425e40094bf39b881634d8572f6 (diff)
downloademacs-221ed70b90a4af0b514634ab5765511ccae9328b.tar.gz
; Improve documentation of 'define-alternatives'
* doc/lispref/commands.texi (Generic Commands): * lisp/simple.el (define-alternatives): Improve documentation of 'define-alternatives'.
-rw-r--r--doc/lispref/commands.texi84
-rw-r--r--lisp/simple.el53
2 files changed, 100 insertions, 37 deletions
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index f84afcf52bd..0298a5d77ee 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -710,29 +710,77 @@ context.
@node Generic Commands
@subsection Select among Command Alternatives
@cindex generic commands
-@cindex alternatives, defining
-
-The macro @code{define-alternatives} can be used to define
-@dfn{generic commands}. These are interactive functions whose
-implementation can be selected from several alternatives, as a matter
-of user preference.
+@cindex alternative commands, defining
+
+Sometimes it is useful to define a command that serves as a ``generic
+dispatcher'' capable of invoking one of a set of commands according to
+the user's needs. For example, imagine that you want to define a
+command named @samp{open} that can ``open'' and display several
+different types of objects. Or you could have a command named
+@samp{mua} (which stands for Mail User Agent) that can read and send
+email using one of several email backends, such as Rmail, Gnus, or
+MH-E. The macro @code{define-alternatives} can be used to define such
+@dfn{generic commands}. A generic command is an interactive function
+whose implementation can be selected from several alternatives, as a
+matter of user preference.
@defmac define-alternatives command &rest customizations
-Define the new command @var{command}, a symbol.
+This macro defines the new generic @var{command}, which can have
+several alternative implementations. The argument @var{command}
+should be an unquoted symbol.
+
+When invoked, the macro creates an interactive Lisp closure
+(@pxref{Closures}). When the user runs @w{@kbd{M-x @var{command}
+@key{RET}}} for the first time, Emacs asks to select one of the
+alternative implementations of @var{command}, offering completion for
+the names of these alternatives. These names come from the user
+option whose name is @code{@var{command}-alternatives}, which the
+macro creates (if it didn't exist before). To be useful, this
+variable's value should be an alist whose elements have the form
+@w{@code{(@var{alt-name} . @var{alt-func})}}, where @var{alt-name} is
+the name of the alternative and @var{alt-func} is the interactive
+function to be called if this alternative is selected. When the user
+selects an alternative, Emacs remembers the selection, and will
+thereafter automatically call that selected alternative without
+prompting when the user invokes @kbd{M-x @var{command}} again. To
+choose a different alternative, type @w{@kbd{C-u M-x @var{command}
+@key{RET}}}--then Emacs will again prompt for one of the alternatives,
+and the selection will override the previous one.
+
+The variable @code{@var{command}-alternatives} can be created before
+calling @code{define-alternatives}, with the appropriate values;
+otherwise the macro creates the variable with a @code{nil} value, and
+it should then be populated with the associations describing the
+alternatives. Packages that wish to provide their own implementation
+of an existing generic command can use @code{autoload} cookies
+(@pxref{Autoload}) to add to the alist, for example:
+
+@lisp
+;;;###autoload (push '("My name" . my-foo-symbol) foo-alternatives
+@end lisp
+
+If the optional argument @var{customizations} is non-@code{nil}, it
+should consist of alternating @code{defcustom} keywords (typically
+@code{:group} and @code{:version}) and values to add to the definition
+of the @code{defcustom} @code{@var{command}-alternatives}.
-When a user runs @kbd{M-x @var{command} @key{RET}} for the first time,
-Emacs prompts for which real form of the command to use, and records
-the selection by way of a custom variable. Using a prefix argument
-repeats this process of choosing an alternative.
+Here is an example of a simple generic dispatcher command named
+@code{open} with 3 alternative implementations:
-The variable @code{@var{command}-alternatives} should contain an alist
-with alternative implementations of @var{command}.
-Until this variable is set, @code{define-alternatives} has no effect.
+@example
+@group
+(define-alternatives open
+ :group 'files
+ :version "42.1")
+@end group
+@group
+(setq open-alternatives
+ '(("file" . find-file)
+ ("directory" . dired)
+ ("hexl" . hexl-find-file)))
+@end group
+@end example
-If @var{customizations} is non-@code{nil}, it should consist of
-alternating @code{defcustom} keywords (typically @code{:group} and
-@code{:version}) and values to add to the declaration of
-@code{@var{command}-alternatives}.
@end defmac
@node Interactive Call
diff --git a/lisp/simple.el b/lisp/simple.el
index 86f65d9d98e..abd587245fe 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -10664,10 +10664,13 @@ warning using STRING as the message.")
;;; Generic dispatcher commands
-;; Macro `define-alternatives' is used to create generic commands.
-;; Generic commands are these (like web, mail, news, encrypt, irc, etc.)
-;; that can have different alternative implementations where choosing
-;; among them is exclusively a matter of user preference.
+;; Macro `define-alternatives' can be used to create generic commands.
+;; Generic commands are commands that can have different alternative
+;; implementations, and choosing among them is the matter of user
+;; preference in each case. For example, you could have a generic
+;; command `open' capable of "opening" a text file, a URL, a
+;; directory, or a binary file, and each of these alternatives would
+;; invoke a different Emacs function.
;; (define-alternatives COMMAND) creates a new interactive command
;; M-x COMMAND and a customizable variable COMMAND-alternatives.
@@ -10677,26 +10680,38 @@ warning using STRING as the message.")
;; ;;;###autoload (push '("My impl name" . my-impl-symbol) COMMAND-alternatives
(defmacro define-alternatives (command &rest customizations)
- "Define the new command `COMMAND'.
+ "Define a new generic COMMAND which can have several implementations.
-The argument `COMMAND' should be a symbol.
+The argument `COMMAND' should be an unquoted symbol.
Running `\\[execute-extended-command] COMMAND RET' for \
-the first time prompts for which
-alternative to use and records the selected command as a custom
-variable.
+the first time prompts for the
+alternative implementation to use and records the selected alternative.
+Thereafter, `\\[execute-extended-command] COMMAND RET' will \
+automatically invoke the recorded selection.
Running `\\[universal-argument] \\[execute-extended-command] COMMAND RET' \
-prompts again for an alternative
-and overwrites the previous choice.
-
-The variable `COMMAND-alternatives' contains an alist with
-alternative implementations of COMMAND. `define-alternatives'
-does not have any effect until this variable is set.
-
-CUSTOMIZATIONS, if non-nil, should be composed of alternating
-`defcustom' keywords and values to add to the declaration of
-`COMMAND-alternatives' (typically :group and :version)."
+again prompts for an alternative
+and overwrites the previous selection.
+
+The macro creates a `defcustom' named `COMMAND-alternatives'.
+CUSTOMIZATIONS, if non-nil, should be pairs of `defcustom'
+keywords and values to add to the definition of that `defcustom';
+typically, these keywords will be :group and :version with the
+appropriate values.
+
+To be useful, the value of `COMMAND-alternatives' should be an
+alist describing the alternative implementations of COMMAND.
+The elements of this alist should be of the form
+ (ALTERNATIVE-NAME . FUNCTION)
+where ALTERNATIVE-NAME is the name of the alternative to be shown
+to the user as a selectable alternative, and FUNCTION is the
+interactive function to call which implements that alternative.
+The variable could be populated with associations describing the
+alternatives either before or after invoking `define-alternatives';
+if the variable is not defined when `define-alternatives' is invoked,
+the macro will create it with a nil value, and your Lisp program
+should then populate it."
(declare (indent defun))
(let* ((command-name (symbol-name command))
(varalt-name (concat command-name "-alternatives"))