read-line
and read-char
both require you press Enter key after typing something. Is there any mechanism in Common Lisp that would allow the program to continue upon the press of any single character immediately, without requiring the additional step of pressing Enter?
I'm trying to build a quick, dynamic text input interface for a program so users can quickly navigate around and do different things by pressing numbers or letters corresponding to onscreen menus. All the extra presses of the Enter key seriously interrupt the workflow. This would also be similar to a "y/n" type of interrogation from a prompt, where just pressing "y" or "n" is sufficient.
I am using SBCL, if that makes a difference. Perhaps this is implementation specific, as I tried both examples on this page and it does not work (I still need to press Enter); here's the first one:
(defun y-or-n ()
(clear-input *standard-input*)
(loop as dum = (format t "Y or N for yes or no: ")
as c = (read-char)
as q = (and (not (equal c #\n)) (not (equal c #\y)))
when q do (format t "~%Need Y or N~%")
unless q return (if (equal c #\y) 'yes 'no)))
I found cl-charms, which seems to be a fork of the abandoned cl-curses. However, the included example program
charms-paint
uses 100 % CPU to run the trivial paint application. The problem seems to be that the main loop busy-waits for input.read-char
doesn't require you to press enter. E.g.,Similarly, if you send some input into SBCL from the command line, it will be read without a newline:
After reading and printing
#\h
, SBCL saw theello
:I think this is enough to confirm that it's not that
read-char
needs a newline, but rather that the buffering of the input is the problem. I think this is the same problem (or non-problem) that's described in a comp.lang.lisp thread from 2008: Re: A problem with read-char. The user asks:There were four responses (see the thread index to get to all of them). These explain why this behavior is observed (viz., that the Lisp process isn't getting raw input from the terminal, but rather buffered input). Pascal Bourguignon described the problem, and a way to handle this with CLISP (but doesn't provide all that much help, aside from the usual good advice) about working around this in SBCL:
Rob Warnock's response included some workaround code for CMUCL that might or might not work for SBCL:
User vippstar's response provided a link to what might be the most portable solution