1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-06 06:20:55 -08:00

Improve repeat-continue property handling

* 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).
This commit is contained in:
Paul Nelson 2025-06-10 09:21:52 +02:00 committed by Juri Linkov
parent 38c57855ae
commit 3a0def802c
5 changed files with 46 additions and 31 deletions

View file

@ -2448,12 +2448,15 @@ will be calculated based on the window width.
+++ +++
** New symbol property 'repeat-continue' for 'repeat-mode'. ** New symbol property 'repeat-continue' for 'repeat-mode'.
A command with this symbol property whose value is a list of repeat A command with the 'repeat-continue' symbol property, which can be a
maps will not activate the repeat map in 'repeat-mode'. It will only list of keymaps or t, will continue an already active repeating sequence
continue the already activated repeating sequence. Also 'defvar-keymap' for a keymap in that list (resp. all keymaps). The new property does
supports a new keyword ':continue' with a list of commands that only not affect whether the command starts a repeating sequence, which
continue the active repeating sequence, and the 'use-package' and remains governed by the 'repeat-map' property. 'defvar-keymap' supports
'bind-keys' macros support a similar keyword ':continue-only'. a new keyword ':continue', a list of commands, and adds the keymap to
the 'repeat-continue' property of each command in that list. The
'use-package' and 'bind-keys' macros support a similar keyword
':continue-only'.
** New function 'completion-table-with-metadata'. ** New function 'completion-table-with-metadata'.
It offers a more concise way to create a completion table with metadata. It offers a more concise way to create a completion table with metadata.

View file

@ -402,13 +402,11 @@ function symbol (unquoted)."
;; repeat-map is non-nil, map is always ;; repeat-map is non-nil, map is always
;; non-nil ;; non-nil
(if (eq repeat-type :continue-only) (if (eq repeat-type :continue-only)
`((unless (memq ',repeat-map `((let ((cur (get ,fun 'repeat-continue)))
(or (get ,fun 'repeat-continue) (when (and (listp cur)
'())) (not (memq ',repeat-map cur)))
(put ,fun 'repeat-continue (put ,fun 'repeat-continue
(append (or (get ,fun 'repeat-continue) (append cur (list ',repeat-map)))))
'())
(list ',repeat-map))))
(bind-key ,(car form) ,fun ,map ,filter)) (bind-key ,(car form) ,fun ,map ,filter))
`(,@(when (and repeat-map (not (eq repeat-type :exit))) `(,@(when (and repeat-map (not (eq repeat-type :exit)))
`((put ,fun 'repeat-map ',repeat-map))) `((put ,fun 'repeat-map ',repeat-map)))
@ -446,6 +444,9 @@ Accepts keyword arguments:
same behavior as if no special keyword had same behavior as if no special keyword had
been used (that is, the command is bound, and been used (that is, the command is bound, and
it's `repeat-map' property set) 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 :filter FORM - optional form to determine when bindings apply
The rest of the arguments are conses of keybinding string and a The rest of the arguments are conses of keybinding string and a

View file

@ -754,8 +754,10 @@ in the echo area.
(dolist (def (plist-get repeat :enter)) (dolist (def (plist-get repeat :enter))
(push `(put ',def 'repeat-map ',variable-name) props)) (push `(put ',def 'repeat-map ',variable-name) props))
(dolist (def (plist-get repeat :continue)) (dolist (def (plist-get repeat :continue))
(push `(put ',def 'repeat-continue (push `(let ((val (get ',def 'repeat-continue)))
(cons ',variable-name (get ',def 'repeat-continue))) (when (listp val)
(put ',def 'repeat-continue
(cons ',variable-name val))))
props)) props))
(while defs (while defs
(pop defs) (pop defs)

View file

@ -427,9 +427,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 When Repeat mode is enabled, certain commands bound to multi-key
sequences can be repeated by typing a single key, after typing the sequences can be repeated by typing a single key, after typing the
full key sequence once. 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 The commands that can be repeated in this way are those whose symbols
keys for repeating. 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." See `describe-repeat-maps' for a list of all repeatable commands."
:global t :group 'repeat :global t :group 'repeat
(if (not repeat-mode) (if (not repeat-mode)
@ -460,12 +469,11 @@ See `describe-repeat-maps' for a list of all repeatable commands."
(when repeat-mode (when repeat-mode
(let ((map-sym (or repeat-map (repeat--command-property 'repeat-map))) (let ((map-sym (or repeat-map (repeat--command-property 'repeat-map)))
(continue (repeat--command-property 'repeat-continue))) (continue (repeat--command-property 'repeat-continue)))
(when continue (when (and repeat-in-progress
(if repeat-in-progress (or (eq continue t)
(when (and (consp continue) (and (consp continue)
(memq repeat-in-progress continue)) (memq repeat-in-progress continue))))
(setq map-sym repeat-in-progress)) (setq map-sym repeat-in-progress))
(setq map-sym nil)))
map-sym))) map-sym)))
(defun repeat-get-map (map) (defun repeat-get-map (map)
@ -495,7 +503,8 @@ See `describe-repeat-maps' for a list of all repeatable commands."
;; in the middle of repeating sequence (bug#47566). ;; in the middle of repeating sequence (bug#47566).
(or (< (minibuffer-depth) (car repeat--prev-mb)) (or (< (minibuffer-depth) (car repeat--prev-mb))
(eq current-minibuffer-command (cdr repeat--prev-mb))) (eq current-minibuffer-command (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))
t)) t))
(defun repeat-pre-hook () (defun repeat-pre-hook ()

View file

@ -224,9 +224,9 @@
"C-M-e c z" "C-M-e c z"
'((1 e)) "cz") '((1 e)) "cz")
;; 'C-M-o' should also activate ;; 'C-M-o' should also activate
;; (repeat-tests--check (repeat-tests--check
;; "C-M-o c z" "C-M-o c z"
;; '((1 o) (1 c)) "z") '((1 o) (1 c)) "z")
))) )))
(ert-deftest repeat-tests-continue-another () (ert-deftest repeat-tests-continue-another ()
@ -246,9 +246,9 @@
"C-M-e t z" "C-M-e t z"
'((1 e)) "tz") '((1 e)) "tz")
;; 'C-M-u' should also activate ;; 'C-M-u' should also activate
;; (repeat-tests--check (repeat-tests--check
;; "C-M-u t z" "C-M-u t z"
;; '((1 u) (1 t)) "z") '((1 u) (1 t)) "z")
;; 'C-M-o' shared with another map should continue current map ;; 'C-M-o' shared with another map should continue current map
(repeat-tests--check (repeat-tests--check
"C-M-s t C-M-o C-M-o t z" "C-M-s t C-M-o C-M-o t z"