]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve repeat-continue property handling
authorPaul Nelson <ultrono@gmail.com>
Tue, 10 Jun 2025 07:21:52 +0000 (09:21 +0200)
committerEshel Yaron <me@eshelyaron.com>
Wed, 18 Jun 2025 08:07:57 +0000 (10:07 +0200)
* lisp/repeat.el (repeat-get-map-sym): Support 'repeat-continue'
property value of t to continue any active repeat map (suggested
by Karthik Chikmagalur <karthikchikmagalur@gmail.com>).
Simplify logic so that repeat-continue does not interfere with
repeat-map activation.
(repeat-check-map): Allow commands with 'repeat-continue'
property value of t to continue without checking the key.
(repeat-mode): Update and tweak docstring.
* lisp/bind-key.el (bind-keys-form): Update handling of
':continue-only' keyword: only add keymap to 'repeat-continue'
if current value is a list.
(bind-keys): Update documentation, mirroring bind-keys-form.
* lisp/keymap.el (defvar-keymap): Update handling of ':continue'
keyword: only add keymap to 'repeat-continue' if current value
is a list.
* test/lisp/repeat-tests.el (repeat-tests-continue)
(repeat-tests-continue-another): Enable previously commented
tests that now work correctly.
* etc/NEWS: Update announcement of 'repeat-continue' (bug#78742).

(cherry picked from commit 3a0def802cf576902faafde404d15f079786a2f8)

lisp/bind-key.el
lisp/keymap.el
lisp/repeat.el
test/lisp/repeat-tests.el

index 27865415c580c37e5ae5b18b9e759efd9e25e4f7..2303f9399fd62d912189232cf9818402064fbdbb 100644 (file)
@@ -404,13 +404,11 @@ function symbol (unquoted)."
                           ;; repeat-map is non-nil, map is always
                           ;; non-nil
                           (if (eq repeat-type :continue-only)
-                              `((unless (memq ',repeat-map
-                                              (or (get ,fun 'repeat-continue)
-                                                  '()))
-                                  (put ,fun 'repeat-continue
-                                       (append (or (get ,fun 'repeat-continue)
-                                                   '())
-                                               (list ',repeat-map))))
+                              `((let ((cur (get ,fun 'repeat-continue)))
+                                  (when (and (listp cur)
+                                             (not (memq ',repeat-map cur)))
+                                    (put ,fun 'repeat-continue
+                                         (append cur (list ',repeat-map)))))
                                 (bind-key ,(car form) ,fun ,map ,filter))
                             `(,@(when (and repeat-map (not (eq repeat-type :exit)))
                                   `((put ,fun 'repeat-map ',repeat-map)))
@@ -448,6 +446,9 @@ Accepts keyword arguments:
                          same behavior as if no special keyword had
                          been used (that is, the command is bound, and
                          it's `repeat-map' property set)
+:continue-only BINDINGS - Within the scope of `:repeat-map', will make
+                         the command continue but not enter the repeat
+                         map, via the `repeat-continue' property
 :filter FORM           - optional form to determine when bindings apply
 
 The rest of the arguments are conses of keybinding string and a
index dc9bd9a8e200e5fb7bae4fd96ff42f18e24a324c..a0048817cfa2c96d91025851bf40f0f059022951 100644 (file)
@@ -746,8 +746,10 @@ in the echo area.
         (dolist (def (plist-get repeat :enter))
           (push `(put ',def 'repeat-map ',variable-name) props))
         (dolist (def (plist-get repeat :continue))
-          (push `(put ',def 'repeat-continue
-                      (cons ',variable-name (get ',def 'repeat-continue)))
+          (push `(let ((val (get ',def 'repeat-continue)))
+                   (when (listp val)
+                     (put ',def 'repeat-continue
+                          (cons ',variable-name val))))
                 props))
         (while defs
           (pop defs)
index 9a4336424bedc4fa4141b089be3ca4341b7da319..191e335ae2465a5321376676441189b7119b58af 100644 (file)
@@ -425,9 +425,18 @@ the map can't be set on the command symbol property `repeat-map'.")
 When Repeat mode is enabled, certain commands bound to multi-key
 sequences can be repeated by typing a single key, after typing the
 full key sequence once.
-The commands which can be repeated like that are those whose symbol
- has the property `repeat-map' which specifies a keymap of single
-keys for repeating.
+
+The commands that can be repeated in this way are those whose symbols
+have the `repeat-map' property, which specifies a keymap of single keys
+for repeating.
+
+Normally, invoking a command outside that keymap terminates the
+repeating sequence.  However, if the command's `repeat-continue'
+property is non-nil, it may instead continue the current repeating
+sequence: if the property is a list of keymaps, then the command
+continues when the current repeat map is in the list; if the property is
+t, the command always continues the sequence.
+
 See `describe-repeat-maps' for a list of all repeatable commands."
   :global t :group 'repeat
   (if (not repeat-mode)
@@ -458,12 +467,11 @@ See `describe-repeat-maps' for a list of all repeatable commands."
   (when repeat-mode
     (let ((map-sym (or repeat-map (repeat--command-property 'repeat-map)))
           (continue (repeat--command-property 'repeat-continue)))
-      (when continue
-        (if repeat-in-progress
-            (when (and (consp continue)
-                       (memq repeat-in-progress continue))
-              (setq map-sym repeat-in-progress))
-          (setq map-sym nil)))
+      (when (and repeat-in-progress
+                 (or (eq continue t)
+                     (and (consp continue)
+                          (memq repeat-in-progress continue))))
+        (setq map-sym repeat-in-progress))
       map-sym)))
 
 (defun repeat-get-map (map)
@@ -495,7 +503,8 @@ See `describe-repeat-maps' for a list of all repeatable commands."
            (eq (when-let ((win (active-minibuffer-window)))
                  (window-buffer win))
                (cdr repeat--prev-mb)))
-       (repeat-check-key last-command-event map)))
+       (or (eq (repeat--command-property 'repeat-continue) t)
+           (repeat-check-key last-command-event map))))
 
 (defun repeat-pre-hook ()
   "Function run before commands to handle repeatable keys."
index f96d8df2ebd8564d8194669d73c15d9e1c612bf1..6bf9badf31d50dce036ab91b28ffba513ba40062 100644 (file)
        "C-M-e c z"
        '((1 e)) "cz")
       ;; 'C-M-o' should also activate
-      ;; (repeat-tests--check
-      ;;  "C-M-o c z"
-      ;;  '((1 o) (1 c)) "z")
+      (repeat-tests--check
+       "C-M-o c z"
+       '((1 o) (1 c)) "z")
       )))
 
 (ert-deftest repeat-tests-continue-another ()
        "C-M-e t z"
        '((1 e)) "tz")
       ;; 'C-M-u' should also activate
-      ;; (repeat-tests--check
-      ;;  "C-M-u t z"
-      ;;  '((1 u) (1 t)) "z")
+      (repeat-tests--check
+       "C-M-u t z"
+       '((1 u) (1 t)) "z")
       ;; 'C-M-o' shared with another map should continue current map
       (repeat-tests--check
        "C-M-s t C-M-o C-M-o t z"