Subject: Re: Common Lisp: polling for keyboard input
From: rpw3@rpw3.org (Rob Warnock)
Date: Mon, 23 Oct 2006 05:18:52 -0500
Newsgroups: comp.lang.lisp
Message-ID: <sr2dnd_jjrWRCqHYnZ2dnUVZ_oCdnZ2d@speakeasy.net>
jakemiles <jacob.miles@gmail.com> wrote:
+---------------
| Hello.  I'm writing a game-playing program in common lisp for a class,
| and I'd like to have a process run while waiting for the user to enter
| input (so the program can do more thinking while the user is thinking).
|  I'm familiar with read-char, but I believe this halts everything until
| input is read.  Is there any way to just poll an input buffer or
| something every once in a while?  I'd prefer not to start playing with
| threads, but if anyone knows of a straightforward option like that I'd
| be interested in learning about it.
+---------------

If you're willing to wait until the user has typed a complete line --
or some other form of "push", such as a ^D under Unix/Linux[1] --
then the CL standard function LISTEN may be what you want. That's
what I use when I'm running a long CPU-bound test and don't want to
use interrupts to stop it. Example:

    > (loop for i from 0
	    until (listen)
	do (format t "tick...~%")
	   (sleep 0.1)
	finally (format t "i = ~d~%" i))
    tick...
    tick...
    tick...
    tick...
    tick...
    tick...
				<== [typed <CR> here]
    i = 6
    NIL
    > 

The <CR> has been read at this point, but it's just leading
whitespace and won't interfere with your next REPL input.

The same thing, but without the (SLEEP 0.1):

    > (loop for i from 0
	    until (listen)
	do (format t "tick...~%")
	finally (format t "i = ~d~%" i))
    tick...
    tick...
    tick...
    ...[many, many lines omitted]...
    tick...
    tick...
    tick...
				<== [typed <CR> here]
    i = 7984
    NIL
    > 


-Rob

[1] Picky details: Most people who haven't dug into it don't understand
    that ^D [or whatever character "stty -a" reports for "eof ="]
    *isn't* really an "EOF" character at all!! It's a "push" character.
    The reason it's normally considered to be the EOF character is that
    it's *usually* typed at the beginning of the line, when there is
    nothing to read. So the Unix/Linux "read()" call returns 0, which
    is the convention for EOF. But if you type one or more characters
    other than #\newline and then type your "EOF" character (normally
    <Ctrl-D> or ^D), then you will "push" those characters into the
    "read()" and it will return however many you had typed. Common
    Lisp's READ-LINE lets you tell the difference with its second
    return value:

      > (read-line)
      hello!

      "hello!"
      NIL
      > (read-line)
      hel^D		<== Note: With CMUCL you may have to type 2 ^D's.
      "hel"
      T
      > 

    Here's an example of that:

      > (loop for i from 0
	      until (listen)
	  do (format t "tick...~%")
	     (sleep 1)
	  finally (format t "i = ~d~%" i)
		  (return (multiple-value-list (read-line))))
      tick...
      tick...
      Atick...		<== [Typed A here]
      tick...
      Btick...		<== [Typed B here]
      tick...
      tick...
      Ctick...		<== [typed C then ^D here]
      i = 8
      ("ABC" T)
      >

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607