From: Joseph O'Rourke
Subject: Read char, then immediate action ?
Date: 
Message-ID: <3821de93.0@news.smith.edu>
My apologies in advance for the elementary nature of this question...

How can I read in a single character from the user, and then act
upon it without awaiting an end-of-line input by the user?
I don't know how to let read-char see the character in the buffer
before the user hits the return key.  So this code

	(defun test ()
	  (setf c1 (read-char))
	  (format t "c1=~C~%" c1) ;or some other action
	  (setf c2 (read-char))
	  (format t "c2=~C~%" c2) ;or some other action
	)

does nothing until two characters and a newline have been entered.
	I am running CLISP under SGI Unix, if that matters.  Thanks!

From: Barry Margolin
Subject: Re: Read char, then immediate action ?
Date: 
Message-ID: <cylU3.53$v3.3077@burlma1-snr2>
In article <··········@news.smith.edu>,
Joseph O'Rourke <·······@grendel.csc.smith.edu> wrote:
>My apologies in advance for the elementary nature of this question...
>
>How can I read in a single character from the user, and then act
>upon it without awaiting an end-of-line input by the user?
>I don't know how to let read-char see the character in the buffer
>before the user hits the return key.  So this code

You have to use some OS-specific mechanism to put the terminal in raw
mode.  For instance, a foreign function call to ioctl() or fcntl().

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Christopher C Stacy
Subject: Re: Read char, then immediate action ?
Date: 
Message-ID: <x8l1za6os1s.fsf@world.std.com>
In Harlequin Lispworks for Windows, your program does what you expect
it to be doing.  It reads characters without waiting for a Newline.
I have never seen an implementation of READ-CHAR that worked differently,
but I don't know if ANSI CL specifies that behaviour, or if it's just on
possible (and obviously desirable_ interpretation of it.
From: Barry Margolin
Subject: Re: Read char, then immediate action ?
Date: 
Message-ID: <j5nU3.62$v3.3426@burlma1-snr2>
In article <···············@world.std.com>,
Christopher C Stacy  <······@world.std.com> wrote:
>In Harlequin Lispworks for Windows, your program does what you expect
>it to be doing.  It reads characters without waiting for a Newline.
>I have never seen an implementation of READ-CHAR that worked differently,
>but I don't know if ANSI CL specifies that behaviour, or if it's just on
>possible (and obviously desirable_ interpretation of it.

ANSI CL doesn't specify anything about it.  If *STANDARD-INPUT* is
connected to the terminal, it's the operating system's terminal driver that
controls whether a program can read input before a newline is typed.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Christopher R. Barry
Subject: Re: Read char, then immediate action ?
Date: 
Message-ID: <87ln8dlveh.fsf@2xtreme.net>
·······@grendel.csc.smith.edu (Joseph O'Rourke) writes:

> My apologies in advance for the elementary nature of this question...

This is one of the better questions posted here.


> How can I read in a single character from the user, and then act
> upon it without awaiting an end-of-line input by the user?
> I don't know how to let read-char see the character in the buffer
> before the user hits the return key.  So this code
> 
> 	(defun test ()
> 	  (setf c1 (read-char))
> 	  (format t "c1=~C~%" c1) ;or some other action
> 	  (setf c2 (read-char))
> 	  (format t "c2=~C~%" c2) ;or some other action
> 	)

I was just doing this over the last week while playing with some
Lisp-machine-style rubout-handling code. The way you do this is going
to dependant on your Lisp implementation and interface. For Allegro
CL's Emacs Lisp Interface, set fi:raw-mode to t. Make sure that
fi:raw-mode-echo is also t unless you want to echo characters yourself
(or not echo them).

For ilisp, which works with CMU CL and CLISP (and others) the
equivalent of fi:raw-mode and fi:raw-mode-echo is AFAICT (function)
raw-keys-ilisp and ilisp-raw-echo, respectively. I got a
wrong-type-argument error when I tried to use these though. (And I
wasn't in the mood to debug it, so I only tested my code with Allegro
CL.)

While playing with raw input mode, you might find the following of
interest:
  http://world.std.com/~pitman/PS/Ambitious.html

Christopher
From: Eric Marsden
Subject: Re: Read char, then immediate action ?
Date: 
Message-ID: <wzieme52p33.fsf@mail.dotcom.fr>
>>>>> "jor" == Joseph O'Rourke <·······@grendel.csc.smith.edu> writes:

  jor> How can I read in a single character from the user, and then
  jor> act upon it without awaiting an end-of-line input by the user?

This is implementation-dependent, as others have pointed out. Since
you are using CLISP, there is a `with-keyboard' form which is defined
when running on a terminal, and which sets the terminal in raw mode.

   (defun test-raw-keyboard ()
     (with-keyboard
      (loop for raw = (read-char *keyboard-input*)
            for cooked = (system::input-character-char raw)
            until (eq #\Escape cooked)
            do (format t "~c" (or cooked #\space)))))  

-- 
Warning: This article may be fatal if swallowed.
From: Aaron Sloman See text for reply address
Subject: Re: Read char, then immediate action ?
Date: 
Message-ID: <803ss2$8bu$1@soapbox.cs.bham.ac.uk>
[To reply replace "Aaron.Sloman.XX" with "A.Sloman"]

·······@grendel.csc.smith.edu (Joseph O'Rourke) writes:

> Date: 4 Nov 99 19:29:23 GMT
> Organization: Smith College, Northampton Mass, USA
>
> ....
>
> How can I read in a single character from the user, and then act
> upon it without awaiting an end-of-line input by the user?

This sort of thing is needed to implement an interactive editor.

There will be different mechanisms in different lisp systems,
different operating systems...

In Poplog Common lisp there is a facility

    *raw-terminal-io*
        An input/output stream that provides raw access to the terminal.

mentioned in this file:

    http://www.cs.bham.ac.uk/research/poplog/doc/lispref/poplog_only

Aaron
===
-- 
Aaron Sloman, ( http://www.cs.bham.ac.uk/~axs/ )
School of Computer Science, The University of Birmingham, B15 2TT, UK
EMAIL A.Sloman AT cs.bham.ac.uk   (NB: Anti Spam address)
PAPERS: http://www.cs.bham.ac.uk/research/cogaff/
From: Alex Henderson
Subject: Re: Read char, then immediate action ?
Date: 
Message-ID: <382635D3.4CAFF499@cam.ac.uk>
> How can I read in a single character from the user, and then act
> upon it without awaiting an end-of-line input by the user?
> I don't know how to let read-char see the character in the buffer
> before the user hits the return key.  So this code
> 
>         (defun test ()
>           (setf c1 (read-char))
>           (format t "c1=~C~%" c1) ;or some other action
>           (setf c2 (read-char))
>           (format t "c2=~C~%" c2) ;or some other action
>         )
> 
> does nothing until two characters and a newline have been entered.
>         I am running CLISP under SGI Unix, if that matters.  Thanks!

Having tried the above under MCL, it performs as expected.

What I suspect is that the terminal you are running CLISP in is using
Line-emulation mode (not passing any input until an end of line is
reached): OK for some simple command-lines, but not appropriate in this
case. Check your terminal settings.

Failing that I'm not sure. Certainly the spec for read-char indicates it
should do as you want. Try experimenting with things like
read-char-no-hang and peek-char etc, but I suspect it's the terminal
that's at fault.

A

-- 
K(-B-E-A)K8,1:C//cc/DE/F24,'GfGAB^/b'b(EG)b(FA)b(EG)=b(DF)c(E^)/^(^)