Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

single keystrokes, cbreak mode

30 views
Skip to first unread message

thorsten kracht

unread,
Jan 31, 2005, 10:10:44 AM1/31/05
to

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

Pascal Bourguignon

unread,
Jan 31, 2005, 10:55:20 AM1/31/05
to
thorsten kracht <thorste...@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------

Edi Weitz

unread,
Jan 31, 2005, 11:00:23 AM1/31/05
to
On Mon, 31 Jan 2005 16:10:44 +0100, thorsten kracht <thorste...@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 "spam...@agharta.de" 5) "edi")

thorsten kracht

unread,
Jan 31, 2005, 12:05:12 PM1/31/05
to
Pascal Bourguignon wrote:
> thorsten kracht <thorste...@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

Pascal Bourguignon

unread,
Jan 31, 2005, 1:14:14 PM1/31/05
to
thorsten kracht <thorste...@desy.de> writes:

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

Rob Warnock

unread,
Feb 1, 2005, 5:19:35 AM2/1/05
to
Pascal Bourguignon <sp...@mouse-potato.com> wrote:
+---------------

| thorsten kracht <thorste...@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 <rp...@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

0 new messages