aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuanma Barranquero <[email protected]>2013-07-06 11:35:37 +0200
committerJuanma Barranquero <[email protected]>2013-07-06 11:35:37 +0200
commit61e56e2c8ae166d7a4430b0ba717f71faae78ff9 (patch)
tree0d375c7b824cf1a894f507f15d2063b16ebe120e
parent3323c263c78e74385bc03d5270cdd44399b0a8d1 (diff)
lisp/simple.el (alternatives-define): New macro.
etc/NEWS: Document new "generic commands" support.
-rw-r--r--etc/ChangeLog4
-rw-r--r--etc/NEWS4
-rw-r--r--lisp/ChangeLog4
-rw-r--r--lisp/simple.el61
4 files changed, 73 insertions, 0 deletions
diff --git a/etc/ChangeLog b/etc/ChangeLog
index 93ba05bc37..9dbcc70ee0 100644
--- a/etc/ChangeLog
+++ b/etc/ChangeLog
@@ -1,3 +1,7 @@
+2013-07-06 Juanma Barranquero <[email protected]>
+
+ * NEWS: Document new "generic commands" support.
+
2013-06-27 Juanma Barranquero <[email protected]>
* NEWS: Document new Desktop option `desktop-save-windows'.
diff --git a/etc/NEWS b/etc/NEWS
index 9c76c2e016..077ee1c619 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -133,6 +133,10 @@ monitor, use the new functions above. Similar notes also apply to
`x-display-pixel-width', `x-display-pixel-height', `display-mm-width',
`display-mm-height', `x-display-mm-width', and `x-display-mm-height'.
+** New macro `alternatives-define' can be used to define generic commands.
+Generic commands are interactive functions whose implementation can be
+selected among several alternatives, as a matter of user preference.
+
* Editing Changes in Emacs 24.4
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index dc554bc542..901e582d15 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,7 @@
+2013-07-06 Juanma Barranquero <[email protected]>
+
+ * simple.el (alternatives-define): New macro.
+
2013-07-06 Stefan Monnier <[email protected]>
* subr.el (read-quoted-char): Use read-key.
diff --git a/lisp/simple.el b/lisp/simple.el
index 61f32363db..9e83a224f5 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -7346,6 +7346,67 @@ warning using STRING as the message.")
(with-eval-after-load pkg
(bad-package-check pkg))))
+
+;;; Generic dispatcher commands
+
+;; Macro `alternatives-define' 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.
+
+;; (alternatives-define 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 alternatives-define (command &rest customizations)
+ "Define new command `COMMAND'.
+The variable `COMMAND-alternatives' will contain alternative
+implementations of COMMAND, so that running `C-u M-x COMMAND'
+will allow the user to chose among them.
+CUSTOMIZATIONS, if non-nil, should be composed of alternating
+`defcustom' keywords and values to add to the declaration of
+`COMMAND-alternatives' (typically to add new groups)."
+ (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)
+ :group 'dispatcher
+ ,@customizations)
+
+ (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 "Select implementation for command `%s': " command-name)
+ ,varalt-sym nil t)))
+ (unless (string-equal val "")
+ (customize-save-variable ',varimp-sym
+ (cdr (assoc-string val ,varalt-sym))))))
+ (if ,varimp-sym
+ (funcall ,varimp-sym)
+ (message ,(format "No implementation selected for command `%s'"
+ command-name)))))))
+
(provide 'simple)
;;; simple.el ends here