emacs-diffs
[Top][All Lists]
Advanced

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

master e3e3133: Add a new command for mode-specific commands


From: Lars Ingebrigtsen
Subject: master e3e3133: Add a new command for mode-specific commands
Date: Sat, 20 Feb 2021 09:12:56 -0500 (EST)

branch: master
commit e3e3133f800cf4395dc4594b791276498e426c34
Author: Lars Ingebrigtsen <larsi@gnus.org>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Add a new command for mode-specific commands
    
    * 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 |  9 ++++++
 etc/NEWS                  |  7 +++++
 lisp/simple.el            | 72 +++++++++++++++++++++++++++++++++++------------
 lisp/subr.el              |  1 +
 4 files changed, 71 insertions(+), 18 deletions(-)

diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index 1c762c2..8199ece 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -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
diff --git a/etc/NEWS b/etc/NEWS
index c0c292a..b623b13 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -252,6 +252,13 @@ commands.  The new keystrokes are 'C-x x g' 
('revert-buffer'),
 * 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
 you type TAB.  By default, any command that matches what you have
diff --git a/lisp/simple.el b/lisp/simple.el
index 7c0b6e1..0e3a1ee 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -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.
diff --git a/lisp/subr.el b/lisp/subr.el
index f9bb1bb..cf70b24 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -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.")



reply via email to

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