]> git.eshelyaron.com Git - emacs.git/commitdiff
Add a new command for mode-specific commands
authorLars Ingebrigtsen <larsi@gnus.org>
Sat, 20 Feb 2021 14:12:45 +0000 (15:12 +0100)
committerLars Ingebrigtsen <larsi@gnus.org>
Sat, 20 Feb 2021 14:12:45 +0000 (15:12 +0100)
* doc/lispref/commands.texi (Interactive Call): Document it.
* lisp/simple.el (command-completion-using-modes-p): Refactored
out into its own function for reuse...
(command-completion-default-include-p): ... from here.
(execute-extended-command-for-buffer): New command and keystroke
(`M-S-x').

doc/lispref/commands.texi
etc/NEWS
lisp/simple.el
lisp/subr.el

index 1c762c27e8e2a2c8c647b75c51fd648b118d7f7c..8199ece1101649ba7fc0573d7d51ea413b1ed314 100644 (file)
@@ -851,6 +851,15 @@ non-@code{nil} if the command is to be included when completing in
 that buffer.
 @end deffn
 
+@deffn Command execute-extended-command-for-buffer prefix-argument
+This is like @code{execute-extended-command}, but limits the commands
+offered for completion to those commands that are of particular
+relevance to the current major mode (and enabled minor modes).  This
+includes commands that are tagged with the modes (@pxref{Using
+Interactive}), and also commands that are bound to locally active
+keymaps.
+@end deffn
+
 @node Distinguish Interactive
 @section Distinguish Interactive Calls
 @cindex distinguish interactive calls
index c0c292aebc8061cb5e375d54e2bb8a2b6c9559d8..b623b13b34f2e3c199c55cd88c04a4b2da3aff5e 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -251,6 +251,13 @@ commands.  The new keystrokes are 'C-x x g' ('revert-buffer'),
 \f
 * Editing Changes in Emacs 28.1
 
++++
+** New command 'execute-extended-command-for-buffer'.
+This new command, bound to 'M-S-x', works like
+'execute-extended-command', but limits the set of commands to the
+commands that have been determined to be particularly of use to the
+current mode.
+
 +++
 ** New user option 'read-extended-command-predicate'.
 This option controls how 'M-x' performs completion of commands when
index 7c0b6e1d745a17eb1c2b468cdbdf9262566a8d3e..0e3a1ee9053ff9d43c6d3dc5536d8e61cdf3a677 100644 (file)
@@ -1994,6 +1994,26 @@ This function uses the `read-extended-command-predicate' user option."
                        (funcall read-extended-command-predicate sym buffer)))))
        t nil 'extended-command-history))))
 
+(define-inline command-completion-using-modes-p (symbol buffer)
+  "Say whether SYMBOL has been marked as a mode-specific command in BUFFER."
+  ;; Check the modes.
+  (let ((modes (command-modes symbol)))
+    ;; Common case: Just a single mode.
+    (if (null (cdr modes))
+        (or (provided-mode-derived-p
+             (buffer-local-value 'major-mode buffer) (car modes))
+            (memq (car modes)
+                  (buffer-local-value 'local-minor-modes buffer))
+            (memq (car modes) global-minor-modes))
+      ;; Uncommon case: Multiple modes.
+      (apply #'provided-mode-derived-p
+             (buffer-local-value 'major-mode buffer)
+             modes)
+      (seq-intersection modes
+                        (buffer-local-value 'local-minor-modes buffer)
+                        #'eq)
+      (seq-intersection modes global-minor-modes #'eq))))
+
 (defun command-completion-default-include-p (symbol buffer)
   "Say whether SYMBOL should be offered as a completion.
 If there's a `completion-predicate' for SYMBOL, the result from
@@ -2004,24 +2024,8 @@ BUFFER."
   (if (get symbol 'completion-predicate)
       ;; An explicit completion predicate takes precedence.
       (funcall (get symbol 'completion-predicate) symbol buffer)
-    ;; Check the modes.
-    (let ((modes (command-modes symbol)))
-      (or (null modes)
-          ;; Common case: Just a single mode.
-          (if (null (cdr modes))
-              (or (provided-mode-derived-p
-                   (buffer-local-value 'major-mode buffer) (car modes))
-                  (memq (car modes)
-                        (buffer-local-value 'local-minor-modes buffer))
-                  (memq (car modes) global-minor-modes))
-            ;; Uncommon case: Multiple modes.
-            (apply #'provided-mode-derived-p
-                   (buffer-local-value 'major-mode buffer)
-                   modes)
-            (seq-intersection modes
-                              (buffer-local-value 'local-minor-modes buffer)
-                              #'eq)
-            (seq-intersection modes global-minor-modes #'eq))))))
+    (or (null (command-modes symbol))
+        (command-completion-using-modes-p symbol buffer))))
 
 (defun command-completion-with-modes-p (modes buffer)
   "Say whether MODES are in action in BUFFER.
@@ -2189,6 +2193,38 @@ invoking, give a prefix argument to `execute-extended-command'."
                          suggest-key-bindings
                        2))))))))
 
+(defun execute-extended-command-for-buffer (prefixarg &optional
+                                                      command-name typed)
+  "Query usert for a command relevant for the current mode and then execute it.
+This is like `execute-extended-command', but limits the
+completions to commands that are particularly relevant to the
+current buffer.  This includes commands that have been marked as
+being specially designed for the current major mode (and enabled
+minor modes), as well as commands bound in the active local key
+maps."
+  (declare (interactive-only command-execute))
+  (interactive
+   (let* ((execute-extended-command--last-typed nil)
+          (keymaps
+           ;; The major mode's keymap and any active minor modes.
+           (cons
+            (current-local-map)
+            (mapcar
+             #'cdr
+             (seq-filter
+              (lambda (elem)
+                (symbol-value (car elem)))
+              minor-mode-map-alist))))
+          (read-extended-command-predicate
+           (lambda (symbol buffer)
+             (or (command-completion-using-modes-p symbol buffer)
+                 (where-is-internal symbol keymaps)))))
+     (list current-prefix-arg
+           (read-extended-command)
+           execute-extended-command--last-typed)))
+  (with-suppressed-warnings ((interactive-only execute-extended-command))
+    (execute-extended-command prefixarg command-name typed)))
+
 (defun command-execute (cmd &optional record-flag keys special)
   ;; BEWARE: Called directly from the C code.
   "Execute CMD as an editor command.
index f9bb1bb3ad15c06bc018ed10fc30a57bfb7eff9a..cf70b249cfc1f95b3912ad7164d31d994874668b 100644 (file)
@@ -1305,6 +1305,7 @@ in a cleaner way with command remapping, like this:
     (define-key map "l" #'downcase-word)
     (define-key map "c" #'capitalize-word)
     (define-key map "x" #'execute-extended-command)
+    (define-key map "X" #'execute-extended-command-for-buffer)
     map)
   "Default keymap for ESC (meta) commands.
 The normal global definition of the character ESC indirects to this keymap.")