(loop
(setf l (read-char-no-hang *standard-input*))
(unless (null l) (format t "-> ~D~%" l))
(if (equal l #\x ) (return))
(sleep 0.5))
If I run the above lines, i have to terminate the input
with a newline before the characters that I typed are
printed.
Any help would be appreciated, thanks in advance,
Thorsten
> Dear all,
> I am running Lisp on Linux and I would like to read single
> keystrokes from the terminal without supplying a newline
> (cbreak mode, no echo).
> The function read-char-no-hang doesn't do it:
>
> (loop
> (setf l (read-char-no-hang *standard-input*))
> (unless (null l) (format t "-> ~D~%" l))
> (if (equal l #\x ) (return))
> (sleep 0.5))
>
> If I run the above lines, i have to terminate the input
> with a newline before the characters that I typed are
> printed.
Obviously, this feature will be highly implementation dependent.
In clisp, you can use the keyboard:
(EXT:WITH-KEYBOARD
(loop for ch = (system::input-character-char
(read-char EXT:*KEYBOARD-INPUT*))
until (and ch (char= #\return ch))
do (print `(got character ,ch))))
but of course, this works only from a _terminal_, not from slime for example.
--
__Pascal Bourguignon__ http://www.informatimago.com/
-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS d? s++:++ a+ C+++ UL++++ P--- L+++ E+++ W++ N+++ o-- K- w---
O- M++ V PS PE++ Y++ PGP t+ 5+ X++ R !tv b+++ DI++++ D++
G e+++ h+ r-- z?
------END GEEK CODE BLOCK------
> I am running Lisp on Linux
I suppose you're talking about Common Lisp but still you have to tell
us which implementation you're using. CMUCL? SBCL? CLISP? ECL?
GCL? AllegroCL? LispWorks?
> and I would like to read single keystrokes from the terminal without
> supplying a newline (cbreak mode, no echo). The function
> read-char-no-hang doesn't do it:
>
> (loop
> (setf l (read-char-no-hang *standard-input*))
The line above invokes undefined behaviour unless you've previously
declared the variable L with DEFPARAMETER or DEFVAR.
> (unless (null l) (format t "-> ~D~%" l))
> (if (equal l #\x ) (return))
> (sleep 0.5))
>
> If I run the above lines, i have to terminate the input with a
> newline before the characters that I typed are printed.
This is implementation-dependent (see above).
HTH,
Edi.
--
Lisp is not dead, it just smells funny.
Real email: (replace (subseq "spam...@agharta.de" 5) "edi")
Dear Pascal,
thanks for Your answer. Your code solved my problem.
With best regards, Thorsten
Ok. For finest results, you should have a look at the
input-character-char structure
(EXT:WITH-KEYBOARD (print (read-char EXT:*KEYBOARD-INPUT*)))
and use judiciously the other fields:
system::input-character-bits
system::input-character-key
and even:
system::input-character-font
depending on the kind of input you can do.
--
__Pascal Bourguignon__ http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
For comparison, this is what I use in CMUCL (on FreeBSD):
(use-package :alien)
(use-package :unix)
(defun read-char-no-echo-cbreak (&optional (stream *query-io*))
(with-alien ((old (struct termios))
(new (struct termios)))
(let ((e0 (unix-tcgetattr 0 old))
(e1 (unix-tcgetattr 0 new))
(bits (logior tty-icanon tty-echo tty-echoe tty-echok tty-echonl)))
(declare (ignorable e0 e1))
(unwind-protect
(progn
(setf (slot new 'c-lflag) (logandc2 (slot old 'c-lflag) bits))
(setf (deref (slot new 'c-cc) vmin) 1)
(setf (deref (slot new 'c-cc) vtime) 0)
(unix-tcsetattr 0 tcsadrain new)
(read-char stream))
(unix-tcsetattr 0 tcsadrain old)))))
[And people say Lisp can't be used for bitbanging... Hah! ;-} ]
-Rob
-----
Rob Warnock <rp...@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607