Subject: Re: bug#78737: sit-for behavior changes when byte-compiled

From: Daniel Colascione <[email-masked]>
Date: Fri, 13 Jun 2025 07:02:14 -0700

On June 13, 2025 6:42:58 AM PDT, Daniel Colascione <[email-masked]> wrote:
>
>
>On June 13, 2025 5:23:34 AM PDT, Lynn Winebarger <[email-masked]> wrote:
>>On Fri, Jun 13, 2025, 2:26 AM Eli Zaretskii <[email-masked]> wrote:
>>
>>> > From: Daniel Colascione <[email-masked]>
>>> > Cc: Eli Zaretskii <[email-masked]>,  [email-masked],
>>> >   [email-masked]
>>> > Date: Thu, 12 Jun 2025 11:48:50 -0700
>>> >
>>> > Pip Cet <[email-masked]> writes:
>>> >
>>> > > I'd like read-event, when called while inhibit-quit is t, to report
>>> > > quits by setting quit-flag in addition to returning quit_char: it'll
>>> > > simplify the C code, and it would make
>>> > >
>>> > > (while t
>>> > >   (let ((inhibit-quit t))
>>> > >     (read-event)))
>>> >
>>> > I strongly disagree.  read-event should read an event.
>>> > Setting quit-flag by side effect when it happens to read one key and not
>>> > others makes the interface less regular and understandable.
>>>
>>> We should start by agreeing that the capability of interrupting a
>>> running Lisp program is a real need.  Are we in agreement about that?
>>> If not, let's first hear the arguments why not.
>>>
>>> If we _are_ in agreement about that, we should discuss how this should
>>> be possible if read-event (and perhaps others?) return C-g instead of
>>> raising quit-flag.  The alternatives mentioned until now are:
>>>
>>>  . restore the old behavior, whereby C-g interrupts read-event
>>>  . have a variable that, if set, will restore the old behavior in
>>>    read-event and other affected primitives, to be interruptible by a
>>>    single C-g
>>>  . make two C-g presses "in quick succession" set quit-flag, IOW
>>>    "C-g C-g" will have the same effect as C-g previously
>>>
>>> Are there other alternatives?
>>>
>>
>>What about keeping a (possibly buffer-local?) lisp variable holding a list
>>of keystrokes mapped to thunks that are treated as generating lisp machine
>>"interrupts"?  The key strokes would be processed by C machinery and never
>>seen directly by lisp code and not be considered "events".
>>Then C-g could be bound to a thunk signalling quit, and the effect of
>>"inhibit-quit" achieved by removing C-g from the list in a given dynamic
>>scope.  Then user code could make other key-strokes "special" without
>>resorting to read-event.  For example, this read-event call in term.el:
>>(message "Hit space to flush")
>>      (let ((ch (read-event)))
>> (if (eq ch ?\s)
>>     (set-window-configuration conf)
>>   (push ch unread-command-events)))
>>
>>Could be replaced by something like
>>(with-interrupts ((?\s (signal term-flush)))
>>  (condition-case nil
>>    (while t (sit-for 100))
>>     (term-flush (set-window-configuration conf))))
>>
>>Then some of these use-case concerns could be mooted altogether.
>
>We already have something like that. :-) read-event already runs the events it reads through special-event-map, right? We don't even need to create a separate thunk list concept: we could just bind C-g in special event map and do what we want, right?
>
>The only special thing about C-g is how we treat it when Lisp is running. When it's instead reading an event, it can and be a boring event processed the same way every other event is.

Oh yeah, one thing I forgot to mention: for the *asynchronous* case, the C code is pretty deeply coupled to quit_char, and IIRC, even hard codes 7, C-g, in some places instead of quit_char. In your proposal, we'd references to quit_char and literal 7 to calls to a new bool is_quit_char(int c) function -- and this function would return true for any raw keys bound in special-event-map. In this way, you'd be able to define as many asynchronous-input characters as you wanted.

We wouldn't get the special SIGINT behavior this way (because in termios there can be only one interrupt key, right?), but I think that's okay, since quitting works without the SIGINT wiring and I suspect that we could remove the SIGINT wiring and simplify the codebase without losing any actual functionality.