emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

while-no-input


From: Stefan Monnier
Subject: while-no-input
Date: Tue, 01 Oct 2002 17:19:32 -0400

Sometimes I'd like to be able to run something "while there's nothing
else to do".  For example, right now icomplete does not work when
completing file names because getting the list of completions can take
an exceedingly long time.  But if it could say "try to build the list
but abort as soon as the user hits a key", then we could use it
there just fine.

So I have a little patch that does just that.  What it does:

1 - add a quit-on-input variable that causes a quit signal to be sent
    as soon as some user input comes in (and the variable is non-nil).

2 - change QUIT to pass the value of `quit-flag' as part of the quit
    signal so we can tell the difference between a real `quit' and
    a `quit-on-input'.

3 - add a `while-no-input' macro that uses the above facilities to run
    its body and exit as soon as user-input is detected.


        Stefan


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 Vquit_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 (Vquit_on_input)
+      && event->kind != FOCUS_IN_EVENT
+      && event->kind != HELP_EVENT
+      && event->kind != DEICONIFY_EVENT)
+    Vquit_flag = Vquit_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 ("quit-on-input", &Vquit_on_input,
+              doc: /* If non-nil, any input will cause a `quit' signal to be 
thrown.
+The value of that variable is passed to `quit-flag' and is later carried
+by the `quit' signal.  */);
+  Vquit_on_input = Qnil;
 }
 
 void
Index: lisp.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/lisp.h,v
retrieving revision 1.440
diff -u -r1.440 lisp.h
--- lisp.h      11 Sep 2002 01:59:33 -0000      1.440
+++ lisp.h      1 Oct 2002 21:17:54 -0000
@@ -1759,8 +1760,9 @@
   do {                                                 \
     if (!NILP (Vquit_flag) && NILP (Vinhibit_quit))    \
       {                                                        \
+       Lisp_Object flag = Vquit_flag;                  \
        Vquit_flag = Qnil;                              \
-       Fsignal (Qquit, Qnil);                          \
+       Fsignal (Qquit, flag);                          \
       }                                                        \
   } while (0)
 
Index: subr.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/subr.el,v
retrieving revision 1.326
diff -u -r1.326 subr.el
--- subr.el     29 Sep 2002 18:37:43 -0000      1.326
+++ subr.el     1 Oct 2002 21:18:28 -0000
@@ -1606,11 +1622,25 @@
 
 (defmacro with-local-quit (&rest body)
   "Execute BODY with `inhibit-quit' temporarily bound to nil."
+  (declare (debug t) (indent 0))
   `(condition-case nil
        (let ((inhibit-quit nil))
         ,@body)
      (quit (setq quit-flag t))))
 
+(defmacro while-no-input (&rest body)
+  "Execute BODY as long as there's no pending input."
+  (declare (debug t) (indent 0))
+  (let ((quit-sym (make-symbol "input")))
+    `(with-local-quit
+       (condition-case err
+          (let ((quit-on-input ',quit-sym))
+            (when (sit-for 0 0 t)
+              ,@body))
+        ;; Check it is indeed a quit-on-input.  If not, rethrow the signal.
+        (quit (unless (eq (cdr err) ',quit-sym)
+                (signal (car err) (cdr err))))))))
+
 (defmacro combine-after-change-calls (&rest body)
   "Execute BODY, but don't call the after-change functions till the end.
 If BODY makes changes in the buffer, they are recorded





reply via email to

[Prev in Thread] Current Thread [Next in Thread]