Subject: [clisp-list] -repl problem in clisp 2.31 ?

From: Rick Taube <[email-masked]>
Date: Sat Dec 13 07:53:01 2003

Hi,  Im trying to make a script that beginning lisp users will use. 
this script will	
	1 start up clisp
	2 load a file
	3 eval an expression and then
	4 enter the standard clisp repl.

If I do:

clisp -i src/make.lisp -x "(make-cm :save-image nil)" -repl

it almost works, except that the poor user is left at the _read_ step 
of the repl without having received any repl prompt at all, which is 
confusing at best -- it looks to a user as if lisp is "hung":
      ...
	; Loading "/Lisp/cm-2.4.0/bin/clisp_2.31_darwin-powerpc/midishare.fas"
	; Compiling "/Lisp/cm-2.4.0/src/midishare/player.lisp"
	; Loading "/Lisp/cm-2.4.0/bin/clisp_2.31_darwin-powerpc/player.fas"
	; Compiling "/Lisp/cm-2.4.0/src/cmn.lisp"
	; Loading "/Lisp/cm-2.4.0/bin/clisp_2.31_darwin-powerpc/cmn.fas"
	; Garbage collecting...
	T

at this point you have to enter an expression,say 1, to get the prompt!
	T1
	CM[3]>

What I would like to have happen is for the normal clisp session to 
start, only that a file has been loaded and an expression has been 
evaluated before the user starts working.

Is there way to get this behavior in clisp 2.31 ??

I\ tried a workaround of creating a file called  "start.lisp" that 
contains
	(load "src/make.lisp")
	(make-cm :save-image nil)

and simply loading that:

	clisp -l start.lisp

but this wont work either, because my make-cm function wants to set 
*package* and *readtable* to values for Common Music, and the load 
function protects these globals during the load such that the user is 
stil in cl-user after make-cm does its job.

any advixce would be greatly appreciated!

Rick Taube
Associate Professor, Composition/Theory
School of Music
University of Illinois
Urbana, IL 61821 USA
net: [email-masked]
fax: 217 244 8319
vox: 217 244 2684

---

From: Pascal J.Bourguignon <[email-masked]>
Date: Sat Dec 13 08:44:01 2003

> any advixce would be greatly appreciated!

Why not just put 

 	(load "src/make.lisp")

in the user's ~/.clisprc.lisp ?

-- 
__Pascal_Bourguignon__                              .  *   * . * .* .
http://www.informatimago.com/                        .   *   .   .*
There is no worse tyranny than to force             * .  . /\  ()  . *
a man to pay for what he does not                    . .  / .\   . * .
want merely because you think it                    .*.  / *  \  . .
would be good for him. -- Robert Heinlein             . /*   o \     .
http://www.theadvocates.org/                        *   '''||'''   .
SCO Spam-magnet: [email-masked]                 ******************

---

From: "Rick Taube" <[email-masked]>
Date: Sat Dec 13 10:41:02 2003

> in the user's ~/.clisprc.lisp ?

thanks for the suggestion but i want to start the software from a script
wihout any installation steps whatsoever and i was hoping there was some way
around my -repl problem. I cant tell if the behavior of -repl that I
reported is a bug or not, but given clisp 2.31's command args it seems it
should be possible for a .sh script to do what I want. I could save an image
on the cd as well, but i would prefer not to.

---

From: Sam Steingold <[email-masked]>
Date: Sat Dec 13 23:35:01 2003

> * Rick Taube <[email-masked]> [2003-12-13 09:52:40 -0600]:
>
> 	1 start up clisp
> 	2 load a file
> it almost works, except that the poor user is left at the _read_ step of
> the repl without having received any repl prompt at all, which is

-x -repl works like this: all -x arguments are concatenated into a
string, terminated with a newline and turned into a
string-input-stream, which is concatenated with terminal into a
concatenated stream, which is fed to the REPL.
REPL prints the prompt only when the *standard-input* is interactive.
so "(make-cm :save-image nil)" is read and executed and REPL is now
reading from a concatenated stream of a string stream which contains
just the separating newline and the terminal.  this stream is not
interactive (interactivity is decided based on the first stream in the
concatenated stream), so no prompt.

why newline?  suppose you have "-x *standard-input* -repl": then -
without the newline - CLISP will wait for your input before trying to
evaluate *standard-input*.

now, for your specific case, the workaround is obvious: try

clisp -i src/make.lisp -x "(make-cm :save-image nil) t" -repl

or

clisp -i src/make.lisp -x "(make-cm :save-image nil)" -x 1 -repl

this will print an extra 1 (or t) but reading the non-list will consume
the separator newline and the REPL will print the prompt because the
string input stream is now empty.

now how can this be fixed?

remove the newline separator?
but then you will need to do
clisp -x '*standard-input* ' -repl
(note space after the variable name).

create a separate REPL for "-x" and the interactive session?
hmm...

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.honestreporting.com>
Those who can't write, write manuals.

---

From: "Rick Taube" <[email-masked]>
Date: Sun Dec 14 10:39:04 2003

Hi, yes appending "t" to my -x expr gets me to the prompt, albeit with t
appearing in the terminal. Thanks for your help!

> create a separate REPL for "-x" and the interactive session?

From this user's perspective, it would be nice if some combo of "-i ... -x
... -repl" could place the user at clisp's standard input prompt without "t"
appearing and with the repl's interaction number still set to 1 in the
prompt . and some flavor of -i that could load silently would be nice too. I
realize I can add an -x  "(load \"src/make.lisp\" :verbose nil)" to do my
loading instead of -i but some simple command arg for silent loading might
be a generally useful feature. anyway thanks for your help.

---

From: Sam Steingold <[email-masked]>
Date: Sun Dec 14 13:21:00 2003

> * Rick Taube <[email-masked]> [2003-12-14 12:43:01 -0600]:
>
> Hi, yes appending "t" to my -x expr gets me to the prompt, albeit with
> t appearing in the terminal. Thanks for your help!
you're welcome!

>> create a separate REPL for "-x" and the interactive session?

trouble is, a REPL ends with an EXIT, so launching two REPL's is tricky.
maybe DRIVER should optionally return (when, say, *DRIVER-FINAL-P* is NIL)?

> From this user's perspective, it would be nice if some combo of "-i
> ... -x ... -repl" could place the user at clisp's standard input
> prompt without "t" appearing and with the repl's interaction number
> still set to 1 in the prompt .

prompt "[1]> " would, indeed, require a second REPL - is not
technically, then, at least, ideologically.

> and some flavor of -i that could load silently would be nice too. I
> realize I can add an -x "(load \"src/make.lisp\" :verbose nil)" to do
> my loading instead of -i but some simple command arg for silent
> loading might be a generally useful feature.

maybe adding "-s/--silent" that will set *LOAD-VERBOSE* and
*COMPILE-VERBOSE* to NIL would be a good idea?

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.honestreporting.com>
Lisp: Serious empowerment.

---

From: Sam Steingold <[email-masked]>
Date: Thu Dec 18 12:32:01 2003

> Hi,  Im trying to make a script that beginning lisp users will use. this
> script will	
> 	1 start up clisp
> 	2 load a file

please try the appended patch.

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.honestreporting.com>
Save your burned out bulbs for me, I'm building my own dark room.

Index: src/spvw.d
===================================================================
RCS file: /cvsroot/clisp/clisp/src/spvw.d,v
retrieving revision 1.243
diff -u -w -b -r1.243 spvw.d
--- src/spvw.d	4 Nov 2003 21:47:31 -0000	1.243
+++ src/spvw.d	18 Dec 2003 20:21:43 -0000
@@ -1635,6 +1635,15 @@
   skipSTACK(1);
 }
 
+/* can trigger GC */
+local object appease_form (bool interactive_debug, object form)
+{ /* return `(BATCHMODE-ERRORS ,form) */
+  if (interactive_debug) pushSTACK(S(appease_cerrors));
+  else pushSTACK(S(batchmode_errors));
+  pushSTACK(form);
+  return listof(2);
+}
+
 # main program stores the name 'main'.
 #ifdef NEXTAPP
   # main() already exists in Lisp_main.m
@@ -2875,12 +2884,7 @@
           });
         }
         var object form = listof(1+argcount); # `(COMPILE-FILE ',...)
-        if (!argv_repl) {
-          if (argv_interactive_debug) pushSTACK(S(appease_cerrors));
-          else pushSTACK(S(batchmode_errors));
-          pushSTACK(form);
-          form = listof(2); # `(SYS::BATCHMODE-ERRORS (COMPILE-FILE ',...))
-        }
+        if (!argv_repl) form = appease_form(argv_interactive_debug,form);
         eval_noenv(form); # execute
         fileptr++;
       });
@@ -2934,33 +2938,25 @@
     pushSTACK(NIL);
    #endif
     form = listof(4);
-    if (!argv_repl) {
-      if (argv_interactive_debug) pushSTACK(S(appease_cerrors));
-      else pushSTACK(S(batchmode_errors));
-      pushSTACK(form);
-      form = listof(2); # `(SYS::BATCHMODE-ERRORS (LOAD "..."))
-    }
+    if (!argv_repl) form = appease_form(argv_interactive_debug,form);
     eval_noenv(form); # execute
     if (!argv_repl) quit();
   }
   if (argv_expr_count) {
     # set *STANDARD-INPUT* to a stream, that produces argv_exprs:
-    var uintL count = argv_expr_count;
     var char** exprs = &argv_selection_array[argc-1];
+    if (argv_expr_count > 1) {
+      var uintL count = argv_expr_count;
     do { pushSTACK(asciz_to_string(*exprs--,O(misc_encoding))); }
     while (--count);
-    pushSTACK(O(newline_string)); /* separate -x from REPL */
-    var object total = string_concat(argv_expr_count+1);
+      var object total = string_concat(argv_expr_count);
     pushSTACK(total);
+    } else pushSTACK(asciz_to_string(*exprs--,O(misc_encoding)));
     funcall(L(make_string_input_stream),1);
-    if (argv_repl) {
-      pushSTACK(value1); pushSTACK(Symbol_value(S(standard_input)));
-      funcall(L(make_concatenated_stream),2);
-    }
-    Symbol_value(S(standard_input)) = value1;
     # During bootstrapping, *DRIVER* has no value and SYS::BATCHMODE-ERRORS
     # is undefined. Do not set an error handler in that case.
-    if (!nullpSv(driverstern) && !argv_repl) {
+    if (!nullpSv(driverstern)) {
+      dynamic_bind(S(standard_input),value1);
       # (PROGN
       #   (EXIT-ON-ERROR (APPEASE-CERRORS (FUNCALL *DRIVER*)))
       #   ; Normally this will exit by itself once the string has reached EOF,
@@ -2968,12 +2964,12 @@
       #   (UNLESS argv_repl (EXIT)))
       var object form;
       pushSTACK(S(funcall)); pushSTACK(S(driverstern)); form = listof(2);
-      if (argv_interactive_debug) pushSTACK(S(appease_cerrors));
-      else pushSTACK(S(batchmode_errors));
-      pushSTACK(form); form = listof(2);
+      if (!argv_repl) form = appease_form(argv_interactive_debug,form);
       eval_noenv(form);
       if (!argv_repl) quit();
-    }
+      else dynamic_unbind(S(standard_input));
+    } else /* no *DRIVER* => bootstrap, no -repl */
+      Symbol_value(S(standard_input)) = value1;
   }
   # call read-eval-print-loop:
   driver();
Index: src/reploop.lisp
===================================================================
RCS file: /cvsroot/clisp/clisp/src/reploop.lisp,v
retrieving revision 1.26
diff -u -w -b -r1.26 reploop.lisp
--- src/reploop.lisp	12 Dec 2003 17:46:33 -0000	1.26
+++ src/reploop.lisp	18 Dec 2003 20:21:43 -0000
@@ -403,7 +403,10 @@
            ;; T -> #<EOF>
            ;; NIL -> form is already evaluated
            ;;        result has been printed
-           (exit))))))
+           (if (interactive-stream-p *standard-input*)
+             (exit)           ; user typed EOF
+             (progn (setq *command-index* 0) ; reset *command-index*
+                    (return-from main-loop)))))))) ; and proceed
 
 (setq *driver* #'main-loop)