emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

scratch/command 064f146 1/2: Change command to interactive ... modes


From: Lars Ingebrigtsen
Subject: scratch/command 064f146 1/2: Change command to interactive ... modes
Date: Sat, 13 Feb 2021 09:12:26 -0500 (EST)

branch: scratch/command
commit 064f1466737b9d6a5293b866948e79b0ae90a675
Author: Lars Ingebrigtsen <larsi@gnus.org>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Change command to interactive ... modes
---
 doc/lispref/commands.texi     | 30 +++++++++++++++++-------------
 doc/lispref/modes.texi        |  2 +-
 lisp/emacs-lisp/autoload.el   | 16 +++++++---------
 lisp/emacs-lisp/bytecomp.el   | 19 +++++--------------
 lisp/emacs-lisp/easy-mmode.el | 22 +++++++++++++++++-----
 lisp/emacs-lisp/edebug.el     |  3 ---
 lisp/simple.el                |  2 +-
 src/callint.c                 | 24 ++++++------------------
 src/data.c                    | 12 +++++-------
 src/eval.c                    |  8 ++------
 10 files changed, 61 insertions(+), 77 deletions(-)

diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index a1d4d7e..03260f1 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -162,7 +162,7 @@ commands by adding the @code{interactive} form to them.
 makes a Lisp function an interactively-callable command, and how to
 examine a command's @code{interactive} form.
 
-@defspec interactive arg-descriptor
+@defspec interactive &optional arg-descriptor &rest modes
 This special form declares that a function is a command, and that it
 may therefore be called interactively (via @kbd{M-x} or by entering a
 key sequence bound to it).  The argument @var{arg-descriptor} declares
@@ -183,6 +183,22 @@ forms are executed; at this time, if the 
@code{interactive} form
 occurs within the body, the form simply returns @code{nil} without
 even evaluating its argument.
 
+The @var{modes} list allows specifying which modes the command is
+meant to be used in.  This affects, for instance, completion in
+@kbd{M-x} (commands won't be offered as completions if they don't
+match (using @code{derived-mode-p}) the current major mode, or if the
+mode is a minor mode, whether it's switched on in the current buffer).
+This will also make @kbd{C-h m} list these commands.
+
+For instance:
+
+@lisp
+(interactive "p" dired-mode)
+@end lisp
+
+This will mark the command as applicable for modes derived from
+@code{dired-mode} only.
+
 By convention, you should put the @code{interactive} form in the
 function body, as the first top-level form.  If there is an
 @code{interactive} form in both the @code{interactive-form} symbol
@@ -192,18 +208,6 @@ interactive form to an existing function, or change how 
its arguments
 are processed interactively, without redefining the function.
 @end defspec
 
-@defspec command modes &optional arg-descriptor
-The @code{command} special form is identical to @code{interactive} in
-its effect, but allows specifying which modes the command is meant to
-be used in.  This affects, for instance, completion in @kbd{M-x}
-(commands won't be offered as completions if they don't match (using
-@code{derived-mode-p}) the current major mode), and will make
-@kbd{C-h m} list these commands.
-
-@var{modes} can be either a single symbol (a mode name), or a list of
-symbols (several mode names).
-@end defspec
-
 There are three possibilities for the argument @var{arg-descriptor}:
 
 @itemize @bullet
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index 28bb7dc..0a8cc09 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -864,7 +864,7 @@ if @var{parent} is @code{nil}.  (Again, a @code{nil} value 
is
 @item :interactive
 Modes are interactive commands by default.  If you specify a
 @code{nil} value, the derived mode won't be interactive and can't be
-activated with @kbd{M-x whatver-mode RET}.
+activated with @kbd{M-x whatever-mode RET}.
 
 @item :group
 If this is specified, the value should be the customization group for
diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el
index ae7e763..861b02c 100644
--- a/lisp/emacs-lisp/autoload.el
+++ b/lisp/emacs-lisp/autoload.el
@@ -141,13 +141,10 @@ expression, in which case we want to handle forms 
differently."
                       ((stringp (car-safe rest)) (car rest))))
            ;; Look for an interactive spec.
            (interactive (pcase body
-                          ((or `((interactive . ,_) . ,_)
-                               `(,_ (interactive . ,_) . ,_))
-                           t)
-                          (`((command . ,modes) . ,_)
-                           (list 'quote (car modes)))
-                          (`(,_ (command . ,modes) . ,_)
-                           (list 'quote (car modes))))))
+                          ((or `((interactive . ,iargs) . ,_)
+                               `(,_ (interactive . ,iargs) . ,_))
+                           ;; List of modes or just t.
+                           (or (nthcdr 1 iargs) t)))))
         ;; Add the usage form at the end where describe-function-1
         ;; can recover it.
         (when (consp args) (setq doc (help-add-fundoc-usage doc args)))
@@ -211,8 +208,9 @@ expression, in which case we want to handle forms 
differently."
                                   easy-mmode-define-minor-mode
                                   define-minor-mode))
                      t)
-                (or (eq (car-safe (car body)) 'interactive)
-                    (eq (car-safe (car body)) 'command)))
+                (and (eq (car-safe (car body)) 'interactive)
+                     ;; List of modes or just t.
+                     (or (nthcdr 1 (car body)) t)))
            ,(if macrop ''macro nil))))
 
      ;; For defclass forms, use `eieio-defclass-autoload'.
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index eb13a5d..5c6b9c2 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -2939,8 +2939,7 @@ for symbols generated by the byte compiler itself."
                     ;; unless it is the last element of the body.
                     (if (cdr body)
                         (setq body (cdr body))))))
-        (int (or (assq 'interactive body)
-                  (assq 'command body)))
+        (int (assq 'interactive body))
          command-modes)
     (when lexical-binding
       (dolist (var arglistvars)
@@ -2953,23 +2952,15 @@ for symbols generated by the byte compiler itself."
       (if (eq int (car body))
          (setq body (cdr body)))
       (cond ((consp (cdr int))
-            (when (or (and (eq (car int) 'interactive)
-                            (cdr (cdr int)))
-                       (and (eq (car int) 'command)
-                            (cdr (cdr (cdr int)))))
-              (byte-compile-warn "malformed interactive spec: %s"
+            (unless (seq-every-p #'symbolp (cdr (cdr int)))
+              (byte-compile-warn "malformed interactive specc: %s"
                                  (prin1-to-string int)))
-             (when (eq (car int) 'command)
-               (setq command-modes (cadr int))
-               (unless (listp command-modes)
-                 (setq command-modes (list command-modes))))
+             (setq command-modes (cdr (cdr int)))
             ;; If the interactive spec is a call to `list', don't
             ;; compile it, because `call-interactively' looks at the
             ;; args of `list'.  Actually, compile it to get warnings,
             ;; but don't use the result.
-            (let* ((form (if (eq (car int) 'interactive)
-                              (nth 1 int)
-                            (nth 2 int)))
+            (let* ((form (nth 1 int))
                     (newform (byte-compile-top-level form)))
               (while (memq (car-safe form) '(let let* progn save-excursion))
                 (while (consp (cdr form))
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el
index 2916ae4..a881378 100644
--- a/lisp/emacs-lisp/easy-mmode.el
+++ b/lisp/emacs-lisp/easy-mmode.el
@@ -172,6 +172,10 @@ BODY contains code to execute each time the mode is 
enabled or disabled.
 :lighter SPEC  Same as the LIGHTER argument.
 :keymap MAP    Same as the KEYMAP argument.
 :require SYM   Same as in `defcustom'.
+:interactive VAL  Whether this mode should be a command or not.  The default
+                is to make it one; use nil to avoid that.  If VAL is a list,
+                it's interpreted as a list of major modes this minor mode
+                is useful in.
 :variable PLACE        The location to use instead of the variable MODE to 
store
                the state of the mode.  This can be simply a different
                named variable, or a generalized variable.
@@ -226,6 +230,7 @@ For example, you could write
         (hook (intern (concat mode-name "-hook")))
         (hook-on (intern (concat mode-name "-on-hook")))
         (hook-off (intern (concat mode-name "-off-hook")))
+         (interactive t)
         keyw keymap-sym tmp)
 
     ;; Check keys.
@@ -245,6 +250,7 @@ For example, you could write
        (:type (setq type (list :type (pop body))))
        (:require (setq require (pop body)))
        (:keymap (setq keymap (pop body)))
+       (:interactive (setq interactive (pop body)))
         (:variable (setq variable (pop body))
                    (if (not (and (setq tmp (cdr-safe variable))
                                  (or (symbolp tmp)
@@ -303,11 +309,17 @@ or call the function `%s'."))))
        ;; The actual function.
        (defun ,modefun (&optional arg ,@extra-args)
          ,(easy-mmode--mode-docstring doc pretty-name keymap-sym)
-        ;; Use `toggle' rather than (if ,mode 0 1) so that using
-        ;; repeat-command still does the toggling correctly.
-        (interactive (list (if current-prefix-arg
-                                (prefix-numeric-value current-prefix-arg)
-                              'toggle)))
+         ,(when interactive
+           ;; Use `toggle' rather than (if ,mode 0 1) so that using
+           ;; repeat-command still does the toggling correctly.
+            (if (consp interactive)
+                `(command ,interactive
+                          (list (if current-prefix-arg
+                                    (prefix-numeric-value current-prefix-arg)
+                                  'toggle)))
+             '(interactive (list (if current-prefix-arg
+                                     (prefix-numeric-value current-prefix-arg)
+                                   'toggle)))))
         (let ((,last-message (current-message)))
            (,@setter
             (cond ((eq arg 'toggle)
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index 3c86b2e..0733dce 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -2211,9 +2211,6 @@ into `edebug--cl-macrolet-defs' which is checked in 
`edebug-list-form-args'."
 (def-edebug-spec interactive
   (&optional &or stringp def-form))
 
-(def-edebug-spec command
-  (symbolp [&optional &or stringp def-form]))
-
 ;; A function-form is for an argument that may be a function or a form.
 ;; This specially recognizes anonymous functions quoted with quote.
 (def-edebug-spec function-form
diff --git a/lisp/simple.el b/lisp/simple.el
index 4914f91..df106e2 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1975,7 +1975,7 @@ BUFFER."
              (buffer-local-value 'major-mode buffer)
              (command-modes symbol))))
 
-(defun completion-on-button-p (symbol buffer)
+(defun completion-on-button-p (_symbol _buffer)
   "Say whether SYMBOL should be offered as a completion.
 This is true if SYMBOL is a command that's in the local map at
 the current point in BUFFER."
diff --git a/src/callint.c b/src/callint.c
index ba5a406..1862463 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -104,25 +104,14 @@ If the string begins with `^' and `shift-select-mode' is 
non-nil,
  Emacs first calls the function `handle-shift-selection'.
 You may use `@', `*', and `^' together.  They are processed in the
  order that they appear, before reading any arguments.
-usage: (interactive &optional ARG-DESCRIPTOR)  */
-       attributes: const)
-  (Lisp_Object args)
-{
-  return Qnil;
-}
-
-DEFUN ("command", Fcommand, Scommand, 0, UNEVALLED, 0,
-       doc: /* Specify interactive arguments for a mode-specific command.
-This is like `interactive' (which see), except that it allows
-specifying which major mode (or modes) the command is meant for.  This
-has the effect of limiting completion in commands like `M-x' to the
-relevant commands for the current mode, and will also make `C-h m' list
-these commands.
 
-MODES can be either a symbol (a single mode), or a list of symbols
-(several modes).
+If MODES is present, it should be a list of mode names (symbols) that
+this command is applicable for.  The main effect of this is that
+`M-x TAB' (by default) won't list this command if the current buffer's
+mode doesn't match the list.  That is, if either the major mode isn't
+derived from them, or (when it's a minor mode) the mode isn't in effect.
 
-usage: (command MODES &optional ARG-DESCRIPTOR)  */
+usage: (interactive &optional ARG-DESCRIPTOR &rest MODES)  */
        attributes: const)
   (Lisp_Object args)
 {
@@ -909,7 +898,6 @@ a way to turn themselves off when a mouse command switches 
windows.  */);
   Vmouse_leave_buffer_hook = Qnil;
 
   defsubr (&Sinteractive);
-  defsubr (&Scommand);
   defsubr (&Scall_interactively);
   defsubr (&Sfuncall_interactively);
   defsubr (&Sprefix_numeric_value);
diff --git a/src/data.c b/src/data.c
index e9d209e..7bddc03 100644
--- a/src/data.c
+++ b/src/data.c
@@ -936,11 +936,11 @@ Value, if non-nil, is a list (interactive SPEC).  */)
          Lisp_Object form = Fcdr (XCDR (fun));
          if (EQ (funcar, Qclosure))
            form = Fcdr (form);
-         Lisp_Object spec = Fassq (Qcommand, form);
-         if (!NILP (spec))
-           return Fcons (Qinteractive, Fcdr (Fcdr (spec)));
+         Lisp_Object spec = Fassq (Qinteractive, form);
+         if (NILP (Fcdr (Fcdr (spec))))
+           return spec;
          else
-           return Fassq (Qinteractive, form);
+           return list2 (Qinteractive, Fcar (Fcdr (spec)));
        }
     }
   return Qnil;
@@ -1002,9 +1002,7 @@ The value, if non-nil, is a list of mode name symbols.  
*/)
          Lisp_Object form = Fcdr (XCDR (fun));
          if (EQ (funcar, Qclosure))
            form = Fcdr (form);
-         Lisp_Object spec = Fassq (Qcommand, form);
-         if (spec)
-           return list1 (Fcar (Fcdr (spec)));
+         return Fcdr (Fcdr (Fassq (Qinteractive, form)));
        }
     }
   return Qnil;
diff --git a/src/eval.c b/src/eval.c
index c862128..4010517 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2072,12 +2072,9 @@ then strings and vectors are not accepted.  */)
   funcar = XCAR (fun);
   if (EQ (funcar, Qclosure))
     return (!NILP (Fassq (Qinteractive, Fcdr (Fcdr (XCDR (fun)))))
-           || !NILP (Fassq (Qcommand, Fcdr (Fcdr (XCDR (fun))))))
-      ? Qt : if_prop;
+           ? Qt : if_prop);
   else if (EQ (funcar, Qlambda))
-    return (!NILP (Fassq (Qinteractive, Fcdr (XCDR (fun))))
-           || !NILP (Fassq (Qcommand, Fcdr (XCDR (fun)))))
-      ? Qt : if_prop;
+    return !NILP (Fassq (Qinteractive, Fcdr (XCDR (fun)))) ? Qt : if_prop;
   else if (EQ (funcar, Qautoload))
     return !NILP (Fcar (Fcdr (Fcdr (XCDR (fun))))) ? Qt : if_prop;
   else
@@ -4234,7 +4231,6 @@ before making `inhibit-quit' nil.  */);
   DEFSYM (Qexit, "exit");
 
   DEFSYM (Qinteractive, "interactive");
-  DEFSYM (Qcommand, "command");
   DEFSYM (Qcommandp, "commandp");
   DEFSYM (Qand_rest, "&rest");
   DEFSYM (Qand_optional, "&optional");



reply via email to

[Prev in Thread] Current Thread [Next in Thread]