Subject: Re: bug#78916: 31.0.50; C-g fails to exit loop

From: Stefan Monnier <[email-masked]>
Date: Tue, 01 Jul 2025 16:47:40 -0400

>> His Q&R call is inside a loop:
>> 
>>          (while (re-search-forward "bug#[[:digit:]]+:" nil t)
>>            (search-backward "(\"bug")
>>            (let (end (start (point)))
>>              (forward-sexp)
>>              (setq end (point))
>>              (query-replace-regexp "\\(\"bug#[[:digit:]]+:\\).*\"" "\\1\""
>>              		    nil start end))))
>> 
>> so when we exit one we enter the next (as long as there's another match
>> for the main regexp, that is).
>
> OK, but then the issue here is not about query-replace-regexp at all,
> isn't it?  It's about whether C-g is "re-read" after exiting
> query-replace-regexp, and when it is re-read, does it quit.  Or am I
> missing something?

I think you're right.  Which is why I think the intention was not to
"unread it" but rather to give it its "normal" behavior (which the code
tries to do by "unreading" the input, but failing to take into account
that there's no guarantee exiting Q&R will get us back to a normal
command loop).

>> - The behavior of `q`: exit the Q&R and continue with whatever may follow.
>> - The behavior of `C-]`: exit the Q&R and also continue with whatever
>>   may follow, but without consuming the `C-]` so next time we read a key
>>   we'll get this `C-]`.
>> - The old behavior of `C-g` (which we definitely want to recover): abort
>>   the current command.
> If C-g is not consumed, it will produce the expected effect, right?

Hmm... it depends what happens when we exit Q&R and what you think is
"the expected effect".

> If so, the problem seems to be that this is what's expected here,

I don't know what you're trying to say here.

> and it happened in the past because C-g would quite right away, so
> there was no need to re-read it.  Right?

I agree that we want to signal `quit` right away here (and I think both
for `C-g` and for `C-]`) rather than "unread" them.  The question is how
we want to do it:

- (signal 'quit nil)
- call `keyboard-quit`.
- call whatever is bound to `C-g` in the normal keymaps.

[ With a subsidiary question of whether we do it by changing the code
  that handles a key bound to `quit` or whether we just change the
  binding to something else like `keyboard-quit`.  ]

        Stefan