Package: emacs;
Reported by: Daniel Colascione <dancol <at> dancol.org>
Date: Mon, 9 Jun 2025 20:50:02 UTC
Severity: normal
Message #71 received at 78737 <at> debbugs.gnu.org (full text, mbox):
From: Daniel Colascione <dancol <at> dancol.org> To: Pip Cet <pipcet <at> protonmail.com> Cc: 78737 <at> debbugs.gnu.org, Eli Zaretskii <eliz <at> gnu.org>, Stefan Monnier <monnier <at> iro.umontreal.ca> Subject: Re: bug#78737: sit-for behavior changes when byte-compiled Date: Wed, 11 Jun 2025 07:49:23 -0700
Pip Cet <pipcet <at> protonmail.com> writes: > "Daniel Colascione" <dancol <at> dancol.org> writes: > >> Pip Cet <pipcet <at> protonmail.com> writes: >> >>> "Daniel Colascione" <dancol <at> dancol.org> writes: >>> >>>> On June 10, 2025 10:40:39 AM PDT, Pip Cet <pipcet <at> protonmail.com> wrote: >>>>>"Stefan Monnier" <monnier <at> iro.umontreal.ca> writes: >>>>> >>>>>>> BTW: the problem isn't just with transient. It also manifests with >>>>>>> read-extended-command! It's a nasty race that, AFAICT, has been with us >>>>>>> since the 90s. I think defining read_char to translate quits to quit_char >>>>>>> solves the problem. >>>>>> >>>>>> I like your way of thinking. I'm not completely sure it will solve >>>>>> world hunger, and it may come with regressions, but it's worth a try. >>>>> >>>>>I must be missing something: read_char translates quits to quit_char if >>>>>called with inhibit-quit bound to t, and never returns with quit-flag >>>>>set to t in that case. >>>> >>>> You shouldn't have to call it with inhibit-quit for it do that. It should just happen all the time. >>> >>> But we don't usually want read-event to eat quits and report them by >>> returning quit_char. The old behavior gave me a choice. >> >> You still have a choice. You can signal quit if you get a quit event. > > Making > > (while t (read-event)) > > infloop without being able to quit is a bad idea. We shouldn't do it. So we should "fix" read-key-sequence so that it, too, quits? >>> (while t (read-event)) >>> >>> on your branch appears to hang the Emacs session unquittably (even >>> SIGUSR2 doesn't seem to work). It should permit quits, because that >>> code says nothing about wanting quits to be reported. >> >> By calling read-event, you're asking Emacs read an event. C-g is an >> event. > > It's not an ordinary event. The problem is that C-g is ordinary event on some code paths and not others. > It's an event that should be handled > specially, which is what we do now and should continue doing. So if I stuff C-g into unread-command-events and then call (read-event), I should get a quit? It's even more confusing to say that C-g is a special event _unless_ it's been unread (perhaps transparently by something somewhere), in which case it's actually a regular event. > There's a > way around that, but the vast majority of callers don't need to worry > about it: (read-event) should read an ordinary event and return it, > without breaking quit. > >> Lisp isn't saying >> read-event-unless-it's-C-g-in-which-case-exit-non-locally. Lisp says >> read-event. > > That's implicit as for any other Lisp command that isn't specifically > documented not to quit. (As, for example, read-key-sequence is). Yes, and one or the other function should change, along with its documentation. What _reason_ is there to quit from one and not the other? >>> Anyway, here are the minor changes to keyboard.c to avoid the original >>> problem (the third change is somewhat independent and avoids quitting in >>> kbd_buffer_get_event): >> >> This change papers over the problem of ambiguous C-g representation > > It doesn't paper over anything. It merely quits before dequeueing > events when throw-on-input is in effect, without any major changes. > >> without trying to fix it or address the even worse problem of the quits >> going to the event loop and not being looked up as commands. > > Are you saying quits should *generally* be treated as commands rather > than by the event loop? Because my opinion is precisely the opposite: > quits should always be handled by C code, never by keyboard-quit, > because that's what they are used for: to break out of misbehaving Lisp > code, with minimal involvement of Lisp machinery which may be > misbehaving. _Quits_ are intended to break out of Lisp code, but C-g doesn't always mean quit. Transient, for example, uses C-g to dismiss its menus. execute-extended-command does too, as does completion. Like it or not, C-g is not merely a signal to Lisp to stop what it's doing, but also a legitimate event to which people bind regular commands, and it's a bug if we don't respect these bindings because in a certain circumstance invisible to users we decided that the C-g is really a stop-the-Lisp-world-now pseudo-error and not the user telling us he wants to run a command. > We'd need new, incompatible versions of almost all callers, because > those do want to quit when we hit C-g. And, again, we're taking away > the choice "act on C-g as usual", replacing it by a new "identify > (somehow) quit events and (somehow) quit when you see one". I haven't seen anything actually malfunction due to having (read-event) return C-g as an event instead of quitting, and some code actually expects it. Some code actually _works_ better. Consider, for example, calc-get-user-defn. (defun calc-get-user-defn () (interactive) (calc-wrapper (message "Get definition of command: z-") (let* ((key (read-char)) (def (or (assq key (calc-user-key-map)) (assq (upcase key) (calc-user-key-map)) (assq (downcase key) (calc-user-key-map)) (error "No command defined for that key"))) ...) If read-char returns \?C-g, the code above produces a _better_ message, "No command defined for that key" (which is the truth) where it used to just say "Quit". Even hairy code like kbd-macro-query works fine when read-char, read-event, and so on report C-g as an event. If you can find something that actually breaks when we do that, we can do something else, but so far, I haven't seen reporting C-g break anything and have seen it make things a bit better.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.