Subject: 28.0.50; repeat's ability to repeat complex commands is broken

From: Sean Whitton <[email-masked]>
Date: Thu, 04 Feb 2021 00:56:14 -0700

Hello,

In the definition of `repeat' there is

    (if (memq last-repeatable-command '(exit-minibuffer
                                        minibuffer-complete-and-exit
                                        self-insert-and-exit)
            (let ((repeat-command (car command-history)))
              (repeat-message "Repeating %S" repeat-command)
              (eval repeat-command))
          (if (null repeat-arg)
              (repeat-message "Repeating command %S" last-repeatable-command)
            (setq current-prefix-arg repeat-arg)
            (repeat-message
             "Repeating command %S %S" repeat-arg last-repeatable-command))
          ...)

In the "Repeating %S" branch, the idea seems to be that if the previous
command took minibuffer input, then repeat it again without prompting
for input by looking at command-history -- like typing C-x M-: RET.
Otherwise, in the "Repeating command %S" branch, just repeat what's in
last-repeatable-command.

Firstly, I note that there are some additional functions that ought to
go into the list of minibuffer-exiting functions --
read-char-from-minibuffer-insert-char and read--expression-try-read are
two I've found so far.  It's suggested in bug#5264 that this be a defvar.

But secondly, it doesn't seem like the "Repeating %S" branch works at
all.  For if you type M-! date RET C-x z then you get prompted for a
shell command, rather than date(1) just getting executed again right
away.

I added some debug printing to `repeat' and found that after M-! date
RET, last-repeatable-command is set to shell-command, not
exit-minibuffer.  So perhaps the way that last-repeatable-command gets
set has changed since this code in repeat.el was written?

Or does the "Repeating %S" branch have some completely different purpose?

Thanks!

-- 
Sean Whitton