From: Bigos on
On Nov 15, 1:41 pm, "Thomas F. Burdick" <tburd...(a)gmail.com> wrote:
> On Nov 14, 2:28 pm, r...(a)rpw3.org (Rob Warnock) wrote:
>
>
>
>
>
> > Here's a little function I hacked up in CMUCL some years ago when I
> > needed single character terminal input for an interactive program
> > [running on FreeBSD & Linux]:
>
> > (use-package :alien)
> > (use-package :unix)
>
> > #| What "less" does:
> > s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
> > s.c_oflag |=  (OPOST|ONLCR|TAB3);
> > s.c_oflag &= ~(OCRNL|ONOCR|ONLRET);
> > s.c_cc[VMIN] = 1;
> > s.c_cc[VTIME] = 0;
> > |#
>
> > (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)))))
>
> [snip]
>
> > As I said, this is CMUCL-specific, but almost any CL implementation
> > should provide you *some* way to make "ioctl()" calls...
>
> Indeed, and the translation to use the SB-POSIX package (sb-unix being
> internals) was dead simple. Where Rob's CMUCL version stack allocates
> the alien structures, this one heap allocates both them and their CLOS
> wrappers. If that were to ever be a performance issue, I bet you'd
> want to refactor this into a with-no-echo-cbreak macro and just call
> read-char directly without twiddling the terminal on every read.
>
> (require :sb-posix)
> (import '(sb-posix:termios sb-posix:termios-lflag sb-posix:termios-cc
>           sb-posix:tcgetattr sb-posix:tcsetattr
>           sb-posix:tcsadrain
>           sb-posix:icanon sb-posix:echo sb-posix:echoe sb-posix:echok
>           sb-posix:echonl sb-posix:vmin sb-posix:vtime))
>
> #| What "less" does:
> s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
> s.c_oflag |=  (OPOST|ONLCR|TAB3);
> s.c_oflag &= ~(OCRNL|ONOCR|ONLRET);
> s.c_cc[VMIN] = 1;
> s.c_cc[VTIME] = 0;
> |#
> (defun read-char-no-echo-cbreak (&optional (stream *query-io*))
>   (let ((old (tcgetattr 0))
>         (new (tcgetattr 0))
>         (bits (logior icanon echo echoe echok echonl)))
>     (unwind-protect
>          (progn
>            (setf (termios-lflag new) (logandc2 (termios-lflag old) bits)
>                  (aref (termios-cc new) vmin) 1
>                  (aref (termios-cc new) vtime) 0)
>            (tcsetattr 0 tcsadrain new)
>            (read-char stream))
>       (tcsetattr 0 tcsadrain old))))

It works !!! thank you!

I must I need time to analyse this because at the moment I have only
vague idea why.
From: Bigos on
On Nov 15, 1:41 pm, "Thomas F. Burdick" <tburd...(a)gmail.com> wrote:
> On Nov 14, 2:28 pm, r...(a)rpw3.org (Rob Warnock) wrote:
>
>
>
>
>
> > Here's a little function I hacked up in CMUCL some years ago when I
> > needed single character terminal input for an interactive program
> > [running on FreeBSD & Linux]:
>
> > (use-package :alien)
> > (use-package :unix)
>
> > #| What "less" does:
> > s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
> > s.c_oflag |=  (OPOST|ONLCR|TAB3);
> > s.c_oflag &= ~(OCRNL|ONOCR|ONLRET);
> > s.c_cc[VMIN] = 1;
> > s.c_cc[VTIME] = 0;
> > |#
>
> > (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)))))
>
> [snip]
>
> > As I said, this is CMUCL-specific, but almost any CL implementation
> > should provide you *some* way to make "ioctl()" calls...
>
> Indeed, and the translation to use the SB-POSIX package (sb-unix being
> internals) was dead simple. Where Rob's CMUCL version stack allocates
> the alien structures, this one heap allocates both them and their CLOS
> wrappers. If that were to ever be a performance issue, I bet you'd
> want to refactor this into a with-no-echo-cbreak macro and just call
> read-char directly without twiddling the terminal on every read.
>
> (require :sb-posix)
> (import '(sb-posix:termios sb-posix:termios-lflag sb-posix:termios-cc
>           sb-posix:tcgetattr sb-posix:tcsetattr
>           sb-posix:tcsadrain
>           sb-posix:icanon sb-posix:echo sb-posix:echoe sb-posix:echok
>           sb-posix:echonl sb-posix:vmin sb-posix:vtime))
>
> #| What "less" does:
> s.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
> s.c_oflag |=  (OPOST|ONLCR|TAB3);
> s.c_oflag &= ~(OCRNL|ONOCR|ONLRET);
> s.c_cc[VMIN] = 1;
> s.c_cc[VTIME] = 0;
> |#
> (defun read-char-no-echo-cbreak (&optional (stream *query-io*))
>   (let ((old (tcgetattr 0))
>         (new (tcgetattr 0))
>         (bits (logior icanon echo echoe echok echonl)))
>     (unwind-protect
>          (progn
>            (setf (termios-lflag new) (logandc2 (termios-lflag old) bits)
>                  (aref (termios-cc new) vmin) 1
>                  (aref (termios-cc new) vtime) 0)
>            (tcsetattr 0 tcsadrain new)
>            (read-char stream))
>       (tcsetattr 0 tcsadrain old))))

All works expect one little problem, Why in the code below computer
prints both "press any key " and "~%you have pressed: >~s<~%" at the
same time?
I would expect the computer would ask me to press a key, wait for a
key press and then display what I have pressed. I will check it
tomorrow. It's time to get some rest now.

(format t "press any key 5 times~%")
(dotimes (i 5)
(format t "press any key ")
(format t "~%you have pressed: >~s<~%" (read-char-no-echo-
cbreak)))

(format t "~%")
From: Rob Warnock on
Bigos <ruby.object(a)googlemail.com> wrote:
+---------------
| All works expect one little problem, Why in the code below computer
| prints both "press any key " and "~%you have pressed: >~s<~%" at the
| same time?
+---------------

Hint: FORCE-OUTPUT


-Rob

-----
Rob Warnock <rpw3(a)rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

From: Bigos on
On Nov 16, 2:14 am, r...(a)rpw3.org (Rob Warnock) wrote:
> Bigos  <ruby.obj...(a)googlemail.com> wrote:
>
> +---------------
> | All works expect one little problem, Why in the code below computer
> | prints both "press any key  " and "~%you have pressed: >~s<~%" at the
> | same time?
> +---------------
>
> Hint: FORCE-OUTPUT
>
> -Rob
>
> -----
> Rob Warnock                     <r...(a)rpw3.org>
> 627 26th Avenue                 <URL:http://rpw3.org/>
> San Mateo, CA 94403             (650)572-2607

Yipieeee! it work. Than you very much everyone. It works the way I
wanted.

Now I will try to analyse the code in spare time and if I have any
more questions I will ask them in another thread.

(dotimes (i 5)
(format t "press any key ")
(force-output)
(format t "~%you have pressed: >~s<~%" (read-char-no-echo-cbreak)))
From: John Thingstad on
The Thu, 12 Nov 2009 15:48:08 -0800, Bigos wrote:

> Hi,
>
> I didn't give up yet. I was a bit busy with my day job so didn't have
> chance to post anything for a while.
>
> At the moment I am trying to write a Linux console application. I
> already have worked out how to do few things in Lisp, but I couldn't
> find answer to the following question:
>
> How do I grab key presses from a console application in Linux without
> having to press Enter?
>
> I mean something like read-char, without having to press Enter.
>
> Also I am willing to consider some alternatives, for example some simple
> GUI tool-kit.

I use nCurses.
There is a Lisp mode though I never got it to work. I mostly write this
sort of thin in Python.

--
John Thingstad