Subject: Re: single keystrokes, cbreak mode
From: rpw3@rpw3.org (Rob Warnock)
Date: Tue, 01 Feb 2005 04:19:35 -0600
Newsgroups: comp.lang.lisp
Message-ID: <leOdnUq8TrkqymLcRVn-tw@speakeasy.net>
Pascal Bourguignon  <spam@mouse-potato.com> wrote:
+---------------
| thorsten kracht <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@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607