[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");