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.
Any help would be appreciated, thanks in advance,
Thorsten
thorsten kracht <···············@desy.de> writes:
> 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------
Pascal Bourguignon wrote:
> thorsten kracht <···············@desy.de> writes:
>
>
>>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.
>
>
Dear Pascal,
thanks for Your answer. Your code solved my problem.
With best regards, Thorsten
thorsten kracht <···············@desy.de> writes:
> Pascal Bourguignon wrote:
> > thorsten kracht <···············@desy.de> writes:
> >
> >>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.
> >
>
> 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
Pascal Bourguignon <····@mouse-potato.com> wrote:
+---------------
| thorsten kracht <···············@desy.de> writes:
| > 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). ...
|
| 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))))
+---------------
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 <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
From: Edi Weitz
Subject: Re: single keystrokes, cbreak mode
Date:
Message-ID: <u4qgxpp0o.fsf@agharta.de>
On Mon, 31 Jan 2005 16:10:44 +0100, thorsten kracht <···············@desy.de> wrote:
> 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 ·········@agharta.de" 5) "edi")