Subject: Re: bug#51390: 29.0.50; repeat-mode: Fails to repeat keys in global-map(?)

From: Juri Linkov <[email-masked]>
Date: Sun, 21 Nov 2021 22:49:40 +0200

>         (defvar teest
>           (let ((map (make-sparse-keymap)))
>             (define-key map "n" #'next-line)
>             (define-key map "p" #'previous-line)
>             map))
>
>         (put 'next-line 'repeat-map 'teest)
>         (put 'previous-line 'repeat-map 'teest)
>...
> 4. Type C-n.  Notice that it does not trigger the repeat map.

I tried to implement what you asked to do, but got horrible results
caused too much damage.  Here is the lossage explaining the problem:

 C-<tab>           ;; tab-next
 o                 ;; tab-next
 n                 ;; gnus-group-next-unread-group

i.e. I typed C-<tab> to switch to the next tab with the text buffer
where I started to type text that begins with the letters "on..."

But instead of inserting letters to the buffer, the letter "o"
switched to the second next tab.  This tab contained the Gnus buffer
where typing the second letter "n" called the bound command
gnus-group-next-unread-group, and I lost all unread messages.

But I never had such a problem when the repeating sequence was
activated only by 'C-x t o ... o o ...' instead of 'C-<tab> o o o ...'
because 'C-<tab>' is a single key, there is no need to activate
other keys doing the same.

This means that by default this behavior should be disabled.
But maybe a new variable should allow to skip this check:

diff --git a/lisp/repeat.el b/lisp/repeat.el
index 4dcd353e34..03e5b032fe 100644
--- a/lisp/repeat.el
+++ b/lisp/repeat.el
@@ -360,6 +360,12 @@ repeat-keep-prefix
   :group 'convenience
   :version "28.1")
 
+(defcustom repeat-foreign-key nil
+  "Whether to check if the last key exists in the repeat map."
+  :type 'boolean
+  :group 'convenience
+  :version "28.1")
+
 (defcustom repeat-echo-function #'repeat-echo-message
   "Function to display a hint about available keys.
 Function is called after every repeatable command with one argument:
@@ -428,7 +434,8 @@ repeat-post-hook
                        (eq current-minibuffer-command (cdr repeat--prev-mb)))
                    ;; Exit when the last char is not among repeatable keys,
                    ;; so e.g. `C-x u u' repeats undo, whereas `C-/ u' doesn't.
-                   (or (lookup-key map (this-command-keys-vector))
+                   (or repeat-foreign-key
+                       (lookup-key map (vector last-nonmenu-event))
                        prefix-arg))
 
               ;; Messaging