[comp.lang.lisp] Lisp shells for Unix

yukngo@obelix.gaul.csd.uwo.ca (Cheung Yukngo) (08/30/90)

Last year, I implemented a Lisp-based shell using the ELI lisp that
comes with the Andrew toolkit from CMU. I got to the stage that pipes,
redirections, job control, etc can be done. I did the implementation
to learn how shells do the things they do. I did not debug it to the
stage that it could replace /bin/csh or /bin/sh, not to mention bash
or tcsh. I did not read the papers discussing Lisp shells (I did not
know of their existance). I'd appreciate it if somebosy could give the
references. I did encounter quite a few interesting problems with my
implementation.

I don't think I should bore you with all the problems I encountered.
Here is a few more interesting ones (in my opinion):

1. How should pipes be specified? 

   (pipe (cat prog.c) (egrep "here") (> "matches")) ?

   Think how the lisp interpreter should execute this thing. After you
   evaluate the arguments, then you do the pipe? Don't evaluate the
   arguments, and let each builtin function worries about the
   evaluation of the arguments (like is done in ELI)? How to mix
   outputs from, say 'car' and output from 'cat'?

2. What exactly are the programs in your search PATH? Are they in the
   same class as 'car' and 'cdr'? Should we have:

   (cat "a.c")
      or
   (! 'cat "a.c") ?

   Should the PATH variable be continued?

3. What status should be given to the output of a program? Is it a
   return value? Part of a return value? Side effects and nothing
   else?

4. With the use of lisp, the traditional one line command buffer for
   executing commands can be discarded (since most lisp program is not
   going to be one line or should be typed on the same line). What
   should replace it? A screen for issuing commands and one screen for
   executing them? One window for the commands and one window for the
   output, in a window system? Think about doing terminal handling and
   command editing as in tcsh or bash. Seems like we need a full
   editor.

There are a lot of good things to say about a shell based in Lisp. I
like the idea. The problems are interesting and challenging.
Unfortunately, I have not met a single graduate student here that was
interested enough to actually tried the shell. Pretty tough to tell
them that parentheses are good for them :-)

Khun Yee

ken@dali.gatech.edu (Ken Seefried iii) (08/31/90)

--

This thread on extensible languages, etc. got me to thinking about the
several papers that I have read over time about people working on Lisp
or Lisp-like command interpreter shells for Unix.  Have any of these
projects borne fruit?  At one time, Henry Strickland (formally of
GaTech, currently with Object Sciences, Corp), was playing with XLisp
as a base for a Lisp shell, but never finished it (got the C++ bug, I
guess...;')

--

	ken seefried iii		ken@dali.gatech.edu

	"Vee haf veyz off making you talk...release da veasles..."

stephen@estragon.uchicago.edu (Stephen P Spackman) (09/04/90)

Disclaimer: I'm approaching this as a DESIGN question, not an
implementation question. You'll probably find my comments impractical
if you're working with an extant system.

In article <YUKNGO.90Aug30165843@obelix.gaul.csd.uwo.ca> yukngo@obelix.gaul.csd.uwo.ca (Cheung Yukngo) writes:
   I don't think I should bore you with all the problems I encountered.
   Here is a few more interesting ones (in my opinion):

   1. How should pipes be specified? 

      (pipe (cat prog.c) (egrep "here") (> "matches")) ?

      Think how the lisp interpreter should execute this thing. After you
      evaluate the arguments, then you do the pipe? Don't evaluate the
      arguments, and let each builtin function worries about the
      evaluation of the arguments (like is done in ELI)? How to mix
      outputs from, say 'car' and output from 'cat'?

What about: pipe is a lazy string.
    (persistent-setq matches ((egrep "here") (cat prog.c)))
[or, to use my fave abbrev.tchnq:]
    (pq matches/(egrep "here")/cat prog.c)

   2. What exactly are the programs in your search PATH? Are they in the
      same class as 'car' and 'cdr'? Should we have:

      (cat "a.c")
	 or
      (! 'cat "a.c") ?

      Should the PATH variable be continued?

What about: we integrate this with the packages concept. A directory
is a sort of package thing.

   3. What status should be given to the output of a program? Is it a
      return value? Part of a return value? Side effects and nothing
      else?

Sounds like we need to generalise multiple return values so that we
can pick them out by name, maybe; or so that the function class gets
to specify what happens if you don't catch all of them (like stdout
and stderr get merged and status gets discarded) and what happens if
you do (exit code is arg0, stdout is arg1, stderr is arg2, ...)
separately.

   4. With the use of lisp, the traditional one line command buffer for
      executing commands can be discarded (since most lisp program is not
      going to be one line or should be typed on the same line). What
      should replace it? A screen for issuing commands and one screen for
      executing them? One window for the commands and one window for the
      output, in a window system? Think about doing terminal handling and
      command editing as in tcsh or bash. Seems like we need a full
      editor.

It should be PART OF an editor. System commands can be editor commands
(like Gnu emacs, but with lisp, the shell, and the editor all merged).
I want an output window at the top, an input window (where the cursor
goes while completing long commands) at the bottom, and two PANES in
the bottom window, one for past and one for future. (-: But then why
am I describing undo-support features for Unix? :-).

   There are a lot of good things to say about a shell based in Lisp. I
   like the idea. The problems are interesting and challenging.
   Unfortunately, I have not met a single graduate student here that was
   interested enough to actually tried the shell. Pretty tough to tell
   them that parentheses are good for them :-)

Have you tried telling them that parentheses are BAD for them, that
they aren't intellignet enough to be allowed to use the system, that
they'll probably break something and that the work is classified?
:-) :-) :-):-) :-) :-):-) :-) :-):-) :-) :-):-) :-) :-):-) :-) :-):-)

stephen p spackman  stephen@estragon.uchicago.edu  312.702.3982

mayer@hplabsz.HPL.HP.COM (Niels Mayer) (09/04/90)

In article <YUKNGO.90Aug30165843@obelix.gaul.csd.uwo.ca> yukngo@obelix.gaul.csd.uwo.ca (Cheung Yukngo) writes:
>1. How should pipes be specified? 
>   (pipe (cat prog.c) (egrep "here") (> "matches")) ?

What's the point of doing that?? I'd rather just say
	(system "cat prog.c | egrep "here" > matches")
and then use the return value of the system(3s) call in my lisp prog.

I think the | > sytax of current shells capture the flow of data quite
nicely. THe lisp syntax above captures the notion of doing functional
programming with return values, not streams of data. We want a syntax that
captures the notion of dataflow (see also the comments about computing w/
"streams" from Abelson & Sussman's SICP Ch. 3.??)... I think that if you're
expecting to do interesting things with streams, you want to settle on a
different kind of syntax + semantics than the above.

IMHO, the interesting thing to do with Lisp, is to use it as a shell
scripting language, rather than a shell command language. Use lisp to parse
and capture the output of text-stream oriented unix commands.  In
particular, I think it's neat to be able to run unix programs, parse their
output, and do intereting lispy things with the output. Not only is it
neat, but it can give you a nice flexible lispy interface that talks to the
rest of the unix world. Interfacing things like popen(3s), scanf(3s), help
in this respect.

I use such programming alot in my WINTERP environment (a Motif UI +
Application prototyping and extension lang based on XLISP -- anon ftp from
expo.lcs.mit.edu:contrib/winterp/winterp-<latestversion>.tar.Z).

Here's a example of translating unix piped data into the lisp world. It is
used to collect data for a search browser built atop the grep(1) command
(see winterp/examples/grep-br.lsp for details):

;; define a class of "grep items"
(SETQ Grep-Item-Class
      (SEND Class :new
            '(file-name line-num match-line)
            ))

;; define a method to read grep items from a pipe.
(SEND Grep-Item-Class :ANSWER :read-grep-info '(pipe)
      '(
        (if (AND
             (SETQ file-name  (FSCANF-STRING pipe "%[^:]:"))
             (SETQ line-num   (FSCANF-FIXNUM pipe "%d:"))
             (SETQ match-line (FSCANF-STRING pipe "%[^\n]\n"))
             )
          SELF                          ;return SELF if succesful
          NIL                           ;return NIL if hit EOF
          )
        ))

;; a function returning a list of "grep-item" objects corresponding to
;; output
(DEFUN grep (grep-arg-string)
  (DO* 
   (;; loop variables, initializers, and increments.
    (fp (POPEN (STRCAT "grep -n " grep-arg-string " /dev/null")
               :DIRECTION :INPUT))
    (line (SEND (SEND Grep-Item-Class :NEW) :read-grep-info fp)
          (SEND (SEND Grep-Item-Class :NEW) :read-grep-info fp))
    (result '())                        ;init to an empty list
    )
   ;; loop test and return
   ((NULL line)                         ;:read-grep-info returns NIL on EOF
    (PCLOSE fp)                         ;close the pipe opened above
    (REVERSE result)                    ;return list of grep objects.
    )
   ;; loop body
   (SETQ result (CONS line result))     ;prepend grep-obj to list
   ))


PS: I will be out of town for a month, so don't expect followups or quich
e-mail response...
-------------------------------------------------------------------------------
	    Niels Mayer -- hplabs!mayer -- mayer@hplabs.hp.com
		  Human-Computer Interaction Department
		       Hewlett-Packard Laboratories
			      Palo Alto, CA.
				   *

lgm@cbnewsc.att.com (lawrence.g.mayka) (09/04/90)

In article <5881@hplabsz.HPL.HP.COM>, mayer@hplabsz.HPL.HP.COM (Niels Mayer) writes:
> I think the | > sytax of current shells capture the flow of data quite
> nicely. THe lisp syntax above captures the notion of doing functional
> programming with return values, not streams of data. We want a syntax that
> captures the notion of dataflow (see also the comments about computing w/
> "streams" from Abelson & Sussman's SICP Ch. 3.??)... I think that if you're
> expecting to do interesting things with streams, you want to settle on a
> different kind of syntax + semantics than the above.

The Series/Generators package described in Appendices A and B of
"Common Lisp the Language - Second Edition" supports this model.


	Lawrence G. Mayka
	AT&T Bell Laboratories
	lgm@iexist.att.com

Standard disclaimer.