From 61e56e2c8ae166d7a4430b0ba717f71faae78ff9 Mon Sep 17 00:00:00 2001 From: Juanma Barranquero Date: Sat, 6 Jul 2013 11:35:37 +0200 Subject: [PATCH] lisp/simple.el (alternatives-define): New macro. etc/NEWS: Document new "generic commands" support. --- etc/ChangeLog | 4 ++++ etc/NEWS | 4 ++++ lisp/ChangeLog | 4 ++++ lisp/simple.el | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+) diff --git a/etc/ChangeLog b/etc/ChangeLog index 93ba05bc377..9dbcc70ee01 100644 --- a/etc/ChangeLog +++ b/etc/ChangeLog @@ -1,3 +1,7 @@ +2013-07-06 Juanma Barranquero + + * NEWS: Document new "generic commands" support. + 2013-06-27 Juanma Barranquero * NEWS: Document new Desktop option `desktop-save-windows'. diff --git a/etc/NEWS b/etc/NEWS index 9c76c2e0165..077ee1c6196 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 dc554bc542d..901e582d15e 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,7 @@ +2013-07-06 Juanma Barranquero + + * simple.el (alternatives-define): New macro. + 2013-07-06 Stefan Monnier * subr.el (read-quoted-char): Use read-key. diff --git a/lisp/simple.el b/lisp/simple.el index 61f32363dbe..9e83a224f5d 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 -- 2.39.2