GNU bug report logs - #78916
31.0.50; C-g fails to exit loop

Previous Next

Package: emacs;

Reported by: Mike Kupfer <kupfer <at> rawbw.com>

Date: Fri, 27 Jun 2025 21:37:02 UTC

Severity: normal

Found in version 31.0.50

Full log


View this message in rfc822 format

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 78916 <at> debbugs.gnu.org, kupfer <at> rawbw.com
Subject: bug#78916: 31.0.50; C-g fails to exit loop
Date: Mon, 30 Jun 2025 16:15:17 -0400
Eli Zaretskii [2025-06-30 22:00:02] wrote:

>> From: Stefan Monnier <monnier <at> iro.umontreal.ca>
>> Cc: Mike Kupfer <kupfer <at> rawbw.com>,  78916 <at> debbugs.gnu.org
>> Date: Mon, 30 Jun 2025 12:01:02 -0400
>> 
>> >> > - Both keys behave like the "old C-g".
>> >> > ?
>> >> I'm fine with that.
>> > Same, but does it mean 'C-g' will do the same as 'q'?  If not, what is
>> > the difference between them?
>> 
>> Hmm... so `q` is bound to `exit` which consumes the key and exits the
>> Q&R loop.  In contrast `C-g` and `C-]` were bound to `quit` which is
>> not handled exlicitly by the Q&R loop, instead it just pushes the event
>> back on the `unread-commend-events` before exiting the loop, so in
>> Mike's test case, `q` exits the inner Q&R and passes to the next,
>> whereas `C-]` aborts all the subsequent Q&R calls after which it runs
>> the global binding of `C-[`.
>
> I think I understand what you are saying about the difference between
> 'q' and 'C-g', but I don't see any nested query-replace in Mike's test
> case, or what did I miss?  Or maybe I misunderstood what you mean by
> "the next"?

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).

> In practice, typing 'q' stops query-replace and leaves point at the
> last match where Emacs asked me whether to replace.  And 'C-g' does
> the same, AFAICT.
> If I'm right, then what would be an example where 'q' and 'C-g' would
> behave differently?

`C-g` (and `C-]`) behave just like "`q` followed by C-g/C-]".
Usually hitting C-g or C-] right after `q` has no effect, which is why
they are often perceived as doing the same, but in the above loop the
difference becomes more significant.

> In any case, this difference between 'q' and 'C-g' is not explained in
> the user manual.  The manual uses different wording to describe them,
> but my interpretation of the text is that they have the same effect.

So in effect we've had 3 "identical" yet subtly different behaviors for
years:

- 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.


        Stefan





This bug report was last modified 25 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.