Function: define-alternatives
define-alternatives is a macro defined in simple.el.gz.
Signature
(define-alternatives COMMAND &rest CUSTOMIZATIONS)
Documentation
Define the new command COMMAND.
The argument COMMAND should be a symbol.
Running M-x (execute-extended-command) COMMAND RET for the first time prompts for which
alternative to use and records the selected command as a custom
variable.
Running C-u (universal-argument) M-x (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).
Probably introduced at or before Emacs version 24.4.
Source Code
;; Defined in /usr/src/emacs/lisp/simple.el.gz
;;; 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.
;; (define-alternatives COMMAND) creates a new interactive command
;; M-x COMMAND and a customizable variable COMMAND-alternatives.
;; Typically, the user will not need to customize this variable; packages
;; wanting to add alternative implementations should use
;;
;; ;;;###autoload (push '("My impl name" . my-impl-symbol) COMMAND-alternatives
(defmacro define-alternatives (command &rest customizations)
"Define the new command `COMMAND'.
The argument `COMMAND' should be a 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.
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)."
(let* ((command-name (symbol-name command))
(varalt-name (concat command-name "-alternatives"))
(varalt-sym (intern varalt-name))
(varimp-sym (intern (concat command-name "--implementation"))))
`(progn
(defcustom ,varalt-sym nil
,(format "Alist of alternative implementations for the `%s' command.
Each entry must be a pair (ALTNAME . ALTFUN), where:
ALTNAME - The name shown at user to describe the alternative implementation.
ALTFUN - The function called to implement this alternative."
command-name)
:type '(alist :key-type string :value-type function)
,@customizations)
(put ',varalt-sym 'definition-name ',command)
(defvar ,varimp-sym nil "Internal use only.")
(defun ,command (&optional arg)
,(format "Run generic command `%s'.
If used for the first time, or with interactive ARG, ask the user which
implementation to use for `%s'. The variable `%s'
contains the list of implementations currently supported for this command."
command-name command-name varalt-name)
(interactive "P")
(when (or arg (null ,varimp-sym))
(let ((val (completing-read
,(format-message
"Select implementation for command `%s': "
command-name)
,varalt-sym nil t)))
(unless (string-equal val "")
(when (null ,varimp-sym)
(message
"Use `C-u M-x %s RET' to select another implementation"
,command-name)
(sit-for 3))
(customize-save-variable ',varimp-sym
(cdr (assoc-string val ,varalt-sym))))))
(if ,varimp-sym
(call-interactively ,varimp-sym)
(message "%s" ,(format-message
"No implementation selected for command `%s'"
command-name)))))))