From: Roy Mash
Subject: Pause for keystroke
Date: 
Message-ID: <9pklps$5gn$1@suaar1ac.prod.compuserve.com>
I'd like my program to pause for the user to hit RETURN or enter, but
   (format t "Pausing ... Press ENTER to continue")
   (read)

doesn't work because READ waits until an expression is entered.

thanks,
roy

From: Sam Steingold
Subject: Re: Pause for keystroke
Date: 
Message-ID: <u1ykiavxf.fsf@xchange.com>
> * In message <············@suaar1ac.prod.compuserve.com>
> * On the subject of "Pause for keystroke"
> * Sent on Fri, 5 Oct 2001 10:06:16 -0700
> * Honorable "Roy Mash" <········@ci.sf.ca.us> writes:
>
> I'd like my program to pause for the user to hit RETURN or enter, but
>    (format t "Pausing ... Press ENTER to continue")
>    (read)
> 
> doesn't work because READ waits until an expression is entered.

use (read-line) instead of (read)

-- 
Sam Steingold (http://www.podval.org/~sds)
Support Israel's right to defend herself! <http://www.i-charity.com/go/israel>
Read what the Arab leaders say to their people on <http://www.memri.org/>
Lisp: Serious empowerment.
From: Andras Simon
Subject: Re: Pause for keystroke
Date: 
Message-ID: <vcditduvw56.fsf@russell.math.bme.hu>
Sam Steingold <···@gnu.org> writes:

> > * In message <············@suaar1ac.prod.compuserve.com>
> > * On the subject of "Pause for keystroke"
> > * Sent on Fri, 5 Oct 2001 10:06:16 -0700
> > * Honorable "Roy Mash" <········@ci.sf.ca.us> writes:
> >
> > I'd like my program to pause for the user to hit RETURN or enter, but
> >    (format t "Pausing ... Press ENTER to continue")
> >    (read)
> > 
> > doesn't work because READ waits until an expression is entered.
> 
> use (read-line) instead of (read)
> 

And what if you want to read (as opposed to read-line) something, but
newline is OK, too? I'm asking this because I'm slightly irritated by
having to type something to CMUCL's toplevel in order to get back the
prompt if the previous output wasn't terminated by a newline. 

Andras


> -- 
> Sam Steingold (http://www.podval.org/~sds)
> Support Israel's right to defend herself! <http://www.i-charity.com/go/israel>
> Read what the Arab leaders say to their people on <http://www.memri.org/>
> Lisp: Serious empowerment.
From: Coby Beck
Subject: Re: Pause for keystroke
Date: 
Message-ID: <X4nv7.294566$8c3.52960251@typhoon.tampabay.rr.com>
"Andras Simon" <······@math.bme.hu> wrote in message
····················@russell.math.bme.hu...
> Sam Steingold <···@gnu.org> writes:
> >
> > use (read-line) instead of (read)
> >
>
> And what if you want to read (as opposed to read-line) something, but
> newline is OK, too?

How about
(read-from-string (read-line) nil nil)

Coby
--
(remove #\space "coby . beck @ opentechgroup . com")
From: Andras Simon
Subject: Re: Pause for keystroke
Date: 
Message-ID: <vcdpu816pc2.fsf@russell.math.bme.hu>
"Coby Beck" <·····@mercury.bc.ca> writes:

> "Andras Simon" <······@math.bme.hu> wrote in message
> ····················@russell.math.bme.hu...
> > Sam Steingold <···@gnu.org> writes:
> > >
> > > use (read-line) instead of (read)
> > >
> >
> > And what if you want to read (as opposed to read-line) something, but
> > newline is OK, too?
> 
> How about
> (read-from-string (read-line) nil nil)

Thanks, but since this is for the toplevel repl, I'd like to ignore
newlines that are in the middle of a form being typed. I.e. when I
type

USER(23): (defun foo (bar)
              (declare (ignore bar)))

it should read the whole (defun foo (bar) (declare (ignore bar))).

With (read-from-string (read-line) nil nil) READ-LINE reads the first
line only (of course) and READ then complains about eof.

Andras


> 
> Coby
> --
> (remove #\space "coby . beck @ opentechgroup . com")
From: Erik Haugan
Subject: Re: Pause for keystroke
Date: 
Message-ID: <87bsjl6idc.fsf@kometknut.neitileu.no>
* "Coby Beck" <·····@mercury.bc.ca>
> (read-from-string (read-line) nil nil)

Yes, but that won't allow you to read more that one line.  I'd suggest:

(defun maybe-read (&rest args)
  (loop for char = (apply 'read-char args)
	until (char= char #\Newline)
	unless (whitespacep char)
	do (unread-char char (car args))
	   (apply 'read args)))

whitespacep should be defined to return true for whitespace characters in
the current readtable, but I can't find any way to do that.  Can it be done
without messing with implementation defined stuff?

Erik
From: Erik Naggum
Subject: Re: Pause for keystroke
Date: 
Message-ID: <3211363159251860@naggum.net>
* Andras Simon
| And what if you want to read (as opposed to read-line) something, but
| newline is OK, too? I'm asking this because I'm slightly irritated by
| having to type something to CMUCL's toplevel in order to get back the
| prompt if the previous output wasn't terminated by a newline.

  This is not a trivial problem, unfortunately.  The most appropriate way
  to read Common Lisp input from an untrusted source is to obey the rules
  of the source, and if that is lines instead of expressions, you need to
  work with prompts and various forms of input editing.  E.g., it would be
  nice if the prompt could contain an indication of unclosed delimiters, as
  well as some way to discard the unfinished form.  The only time it is
  appropriate to call the function read directly is when you "know" that
  the source will contain a Common Lisp expression, or, in other words,
  when you are prepared to deal with errors coming from violating that
  knowledge.  (This is why it is a very good idea to use Emacs interfaces
  to Common Lisp environments.)

  E.g., if you want to read interactive user input, I think the appropriate
  way to do this is to collect a syntactically valid form first, _then_
  process it.  Many input processors tend to be built around the assumption
  that it is easier to backtrack than to validate before processing.  Much
  of the parsing literature that exists unquestioningly _assumes_ that the
  _only_ way to get any match at all is to confuse the validation and
  parsing processes.  This is in part caused by the largely unfounded
  belief in context-free grammars, which has many strongly appealing
  theoretical aspects, but also a large number of negative human factors
  that detract from readability and processability.  (The influence of
  these bad theories on the retarded notion of "ambiguity" in SGML/XML/etc
  has caused a large increase in the cost of designing document types and
  applications, not the least that of educating/training/hurting developers
  and users alike so they stop wanting something completely reasonable.)

  Part of the problem of this mode of thinking is that most streams are
  very naively implemented one-pass structures.  E.g., if you want to
  collect a line of input, you copy characters from the stream (buffer) to
  some (other) buffer while looking for a line terminator character.  If
  you could instead push a "mark" on the stream (buffer), tell the stream
  to skip characters until a line terminator was seen, and return with it,
  you could extract the portion of the buffer from the mark until the
  current position, if you needed to: it should also be possible to refer
  to the characters in the stream buffer via a displaced array.  Naturally,
  the simple-minded single-buffer approach to buffering input and output is
  also at fault.  As long as you refill the same buffer with new data, you
  cannot work with buffer marks.  (Neither can you ask the operating system
  to kindly pre-fill the next buffer while you are doing something else, so
  you end up with a _guessing_ operating system and completely unnecessary
  delays at the buffer edges.)  Designing an SGML entity manager and parser
  around these ideas (in 1993-1994) caused a dramatic 5-fold speed increase
  over the naive C stream implementation.

  So much interesting work remains in the Common Lisp reader if one wants
  to support a better interactive environment, and that includes _much_
  better error recovery when reading Common Lisp files that have not been
  produced by a competent expression-oriented environment like Emacs with
  an intelligent user.  The common way of de-coupling the input processing
  from the "terminal" also leaves much to be desired.  Those who remember
  TOPS-20's command line processor will know what I mean and miss, but
  others may need to have several layers of blinders removed after only
  having been exposed to the ultra-primitive Microsoft command line and
  only somewhat better Unix command line, especially if they think that GNU
  readline is an improvement.  A typewriter remain a typewriter no matter
  how much chrome you add to it, and Unix even has an error message to tell
  you that you have violated its assumptions: "ENOTTY -- Not a typewriter".
  Unfortunately, nigh the whole world is now duped into thinking that silly
  fill-in forms on web pages is the way to do user interfaces.  It is not
  unlikely that this is a sort of improvement over the typewriter, but that
  is about all there is to it.

///
From: Geoff Summerhayes
Subject: Re: Pause for keystroke
Date: 
Message-ID: <trroger790st6e@corp.supernews.com>
"Roy Mash" <········@ci.sf.ca.us> wrote in message
·················@suaar1ac.prod.compuserve.com...
> I'd like my program to pause for the user to hit RETURN or enter, but
>    (format t "Pausing ... Press ENTER to continue")
>    (read)
>
> doesn't work because READ waits until an expression is entered.
>

(do ((x (read-char)))
    ((char-equal #\Newline x)))

-----------
Geoff
From: Roy Mash
Subject: Re: Pause for keystroke
Date: 
Message-ID: <9pkr83$8oh$1@suaar1ac.prod.compuserve.com>
Great, but now I have a further problem. I want the routine to work in at
least the two environments
I'm currently dealing with:  CLISP on unix, and Lispworks (Personal Edition)
running under windows.
In answer to a question I posted some time ago on this newsgroup I learned
to use this trick:
      (progn
         (format *query-io* "Prompt for user input goes here")
         (read *query-io*))
which made my programs nicely portable.

Now however, I find that if a replace (read *query-io*) with either
        (read-line *query-io*)
or
        (do ((x (read-char *query-io* )))
            ((char-equal #\Newline x)))
I get a nice dialog box in Lispworks with the OK button grayed out!
From: Roy Mash
Subject: Re: Pause for keystroke
Date: 
Message-ID: <9pksaq$nfo$1@suaar1aa.prod.compuserve.com>
Actually, let me add: the OK button becomes enabled
AFTER I enter something in the text field -- which is
just what I wanted to avoid in the first place.

roy
From: Geoff Summerhayes
Subject: Re: Pause for keystroke
Date: 
Message-ID: <trs0tpq3t9fnc6@corp.supernews.com>
"Roy Mash" <········@ci.sf.ca.us> wrote in message
·················@suaar1ac.prod.compuserve.com...
> Great, but now I have a further problem. I want the routine to work in
at
> least the two environments
> I'm currently dealing with:  CLISP on unix, and Lispworks (Personal
Edition)
> running under windows.
> In answer to a question I posted some time ago on this newsgroup I
learned
> to use this trick:
>       (progn
>          (format *query-io* "Prompt for user input goes here")
>          (read *query-io*))
> which made my programs nicely portable.
>
> Now however, I find that if a replace (read *query-io*) with either
>         (read-line *query-io*)
> or
>         (do ((x (read-char *query-io* )))
>             ((char-equal #\Newline x)))
> I get a nice dialog box in Lispworks with the OK button grayed out!
>

Why are you tying it to *query-io*?

--------

Geoff
From: Roy Mash
Subject: Re: Pause for keystroke
Date: 
Message-ID: <9pl2s5$csp$1@suaar1ac.prod.compuserve.com>
> Why are you tying it to *query-io*?

Because in Lispworks (read) by itself produces an error
if you're not in the Listener environment.
Lispworks does have various prompt-for idioms but these
wouldn't be portable to CLISP.
From: Christopher Stacy
Subject: Re: Pause for keystroke
Date: 
Message-ID: <uhetdm9hf.fsf@spacy.Boston.MA.US>
>>>>> On Fri, 5 Oct 2001 10:06:16 -0700, Roy Mash ("Roy") writes:
 Roy> I'd like my program to pause for the user to hit RETURN or enter, but
 Roy>    (format t "Pausing ... Press ENTER to continue")
 Roy>    (read)
 Roy> doesn't work because READ waits until an expression is entered.

>>>>> On Fri, 5 Oct 2001 13:49:21 -0700, Roy Mash ("Roy") writes:
 Roy> Now however, I find that if a replace (read *query-io*) with either
 Roy>         (read-line *query-io*)
 Roy> or
 Roy>         (do ((x (read-char *query-io* )))
 Roy>             ((char-equal #\Newline x)))
 Roy> I get a nice dialog box in Lispworks with the OK button grayed out!

 Geoff>> Why are you tying it to *query-io*?

 Roy> Because in Lispworks (read) by itself produces an error if
 Roy> you're not in the Listener environment.  Lispworks does have
 Roy> various prompt-for idioms but these wouldn't be portable to CLISP.

Good question!

Common Lisp doesn't really define how the IO streams are implemented;
there's nothing in the language that necessarily gets you a console
like the Listener that's available in most development environments.
Whether IO gets you some kind of keyboard terminal, a GUI, or a pipe
organ keyboard and pedals, is implementation dependants.

Lispworks for Windows can make a "console" application, which does IO
inside the console ("DOS box") that you run invoke it from.  You can
also ask for a CAPI application, which is the same except it pops up
the console window for you.  I didn't try to start CAPI explicitly,
but my experiments didn't get any CAPI query window like you describe.

In either of those two delivery environments, READ-CHAR on *TERMINAL-IO*
or *QUERY-IO* works in line-mode, so you have to press ENTER after the
input character.  Unfortunately, the #\Newline generated by pressing
the ENTER key is placed into the stream.  This makes every other
call to READ-CHAR immediately return a leftover #\Newline.

Did I see something going by about CLISP behaving the same way, with
the recommendation that the user flush the stream after each input?

This behaviour seems like a bug to me.  Either READ-CHAR should be
doing character-at-a-time (preferable), or else the ENTER key should
only perform the activation and not feed a #\Newline into the stream.
After all, even READ-LINE is defined not to return the #\Newline!

If you use CAPI then you can program the input model of window panes
(set up a callback for keyboard events), but of course that's not ANSI CL.

Is there a way in Lispworks to simply wait for and read one character?
How is this done in CMUCL, Franz, and CLISP?

I don't recall C stdio programs having this design bug for STDIN
(although maybe you have to do some OS-specific fcntl frobbing of 
the input descriptor to get the activation mode you want...  
I don't remember.  But at least there's a standard IO call to do it!)
From: Erik Naggum
Subject: Re: Pause for keystroke
Date: 
Message-ID: <3211351217140007@naggum.net>
* Christopher Stacy
| I don't recall C stdio programs having this design bug for STDIN
| (although maybe you have to do some OS-specific fcntl frobbing of the
| input descriptor to get the activation mode you want...   I don't
| remember.  But at least there's a standard IO call to do it!)

  For what it might be worth, this little page shows the kind of thing you
  have to do in the usual Unix system calls framework.

http://web.mit.edu/answers/c/c_getch.html

  I do not think this should comfort anyone.

  There are a number of useful things in the C streams model that are not
  available in Common Lisp streams, such as line buffering, which are
  neither pretty nor easy to request from Common Lisp and consequently
  cause the Common Lisp environments to lack these features.

///
From: ········@acm.org
Subject: Re: Pause for keystroke
Date: 
Message-ID: <MuFv7.24789$4l5.3876972@news20.bellglobal.com>
Erik Naggum <····@naggum.net> writes:
> * Christopher Stacy
> | I don't recall C stdio programs having this design bug for STDIN
> | (although maybe you have to do some OS-specific fcntl frobbing of the
> | input descriptor to get the activation mode you want...   I don't
> | remember.  But at least there's a standard IO call to do it!)
> 
>   For what it might be worth, this little page shows the kind of thing you
>   have to do in the usual Unix system calls framework.
> 
> http://web.mit.edu/answers/c/c_getch.html
> 
>   I do not think this should comfort anyone.

On the other hand, given a C FFI, it ought to be pretty easy to
construct something like:

 (with-cbreak (port stdin)
   (loop
     for i from 1 to 10
     do (format stdout "Type a character:")
     do (flush stdout)
     do (setf ch (read-byte stdin))
     do (format stdout "~C~%" ch)
     do (flush stdout)))
-- 
(concatenate 'string "cbbrowne" ·@cbbrowne.com")
http://www.ntlug.org/~cbbrowne/xwindows.html
"Is your pencil Y2K certified?  Do you know the possible effects if it
isn't?"