[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: while-no-input
From: |
Richard Stallman |
Subject: |
Re: while-no-input |
Date: |
Tue, 30 Nov 2004 02:03:08 -0500 |
> The only thing programs do to control quitting is to bind inhibit-quit
> on and off. That is not relevant to handling with-no-input, so I think
Could you substantiate that claim?
AFAIK inhibit-quit is used to get more-or-less-atomic behavior in places
where it matters. while-no-input should very clearly obey inhibit-quit
I am not sure about that point, but the issue at hand is how to do the
nonlocal exit. If while-no-input's implementation looks at
inhibit-quit, that is orthogonal to how do to the nonlocal exit. So
let me make my statement more precise:
The only thing programs do to control quitting is to bind inhibit-quit
on and off. Since inhibit-quit has no effect on what either Fsignal
or Fthrow does when it is called, using Fthrow instead of Fsignal is
entirely orthogonal to anything user programs do to control quitting.
Here is another way to say the ame thing: of all the non-local
exits we have right now, `quit' is the only one that's
asynchronous.
The setting of Vquit_flag is asynchronous, but I don't see that
that relates to the issue. Quitting itself can be done asynchronously
in a few primitives, but usually it occurs synchronously in a place
that checks for it and does QUIT.
The operational difference between signal and throw is that the former
is caught by `condition-case' while the latter is caught by `catch'.
So the way to decide the issue is based on whether `condition-case'
ought to catch this. If the definition of with-no-input is that
it alone catches this, then it has to use `catch'.
So here's my simpler proposal for how to implement this.
(defmacro while-no-input (&rest body)
"Execute BODY only as long as there's no pending input.
If input arrives, that ends the execution of BODY."
(declare (debug t) (indent 0))
(let ((catch-sym (make-symbol "input")))
`(with-local-quit
(catch ',catch-sym
(let ((throw-on-input ',catch-sym))
(when (sit-for 0 0 t)
,@body))))))
#define QUIT \
do { \
if (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) \
{ \
Lisp_Object flag = Vquit_flag; \
Vquit_flag = Qnil; \
if (EQ (Vthrow_on_input, flag)) \
Fthrow (Vthrow_on_input, Qnil); \
Fsignal (Qquit, Qnil); \
} \
else if (interrupt_input_pending) \
handle_async_input (); \
} while (0)
Index: keyboard.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/keyboard.c,v
retrieving revision 1.708
diff -u -u -b -r1.708 keyboard.c
--- keyboard.c 27 Sep 2002 17:03:46 -0000 1.708
+++ keyboard.c 1 Oct 2002 21:15:14 -0000
@@ -3374,6 +3402,9 @@
}
#endif
+
+Lisp_Object Vthrow_on_input;
+
/* Store an event obtained at interrupt level into kbd_buffer, fifo */
void
@@ -3501,6 +3538,14 @@
ASET (kbd_buffer_gcpro, idx + 1, event->arg);
++kbd_store_ptr;
}
+
+ /* If we're in a section that requested to be interrupted as soon
+ as input comes, then set quit-flag to cause an interrupt. */
+ if (!NILP (Vthrow_on_input)
+ && event->kind != FOCUS_IN_EVENT
+ && event->kind != HELP_EVENT
+ && event->kind != DEICONIFY_EVENT)
+ Vquit_flag = Vthrow_on_input;
}
@@ -11038,6 +11029,12 @@
doc: /* *How long to display an echo-area message when the
minibuffer is active.
If the value is not a number, such messages don't time out. */);
Vminibuffer_message_timeout = make_number (2);
+
+ DEFVAR_LISP ("throw-on-input", &Vthrow_on_input,
+ doc: /* If non-nil, any keyboard input throws to this symbol.
+The value of that variable is passed to `quit-flag' and later causes a
+peculiar kind of quitting. */);
+ Vthrow_on_input = Qnil;
}
void