a while ago people where talking about implementing a better
interactive command line to scsh. below is a very simple start at
one. the way it handles both single and multiple line inputs is kind
of interesting.
#!
cli - command line interface for scsh
Copyright (C) 1995 Scott Draves <spot@cs.cmu.edu>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!#
#!
todo:
better syntax for globbing, tilde
job control (& adds pid to list)
access to module system
interrupts
handle multiple return values
!#
#!
> ,config ,load cli.scm
cli.scm .
> ,open cli
Load structure cli (y/n)? y
> (cli)
cli> (+ 1 2)
3
cli> date
Wed Jun 26 02:13:43 EDT 1996
cli> (define file "/afs/cs/user/spot/.twmrc")
cli> wc ,file
225 591 5220 /afs/cs/user/spot/.twmrc
cli> grep color ,file
exit code 256
cli> sort /etc/protocols | tail -5 > /tmp/foo
cli> rm /tmp/foo
cli> cat /tmp/foo
UX:cat: ERROR: Cannot open /tmp/foo: No such file or directory
exit code 512
cli> ls -ld ,@(glob "p*")
drwxr-xr-x 6 spot sys 2048 Nov 14 1994 pgp
drwxr-xr-x 2 spot sys 2048 Feb 28 13:04 pub
cli> cd pgp
cli> ls
2.6-doc doc pgp.hlp readme.doc
config.txt local-pubring.bak pgp.pmax_mach src
contrib local-pubring.pgp pgp.sun4_mach
cli> (define (fact x)
(if (zero? x) 1 (* x (fact (- x 1)))))
cli> (fact 10)
3628800
cli>
!#
(define-structure cli
(export cli)
(open util pp handle scsh scheme)
(begin
(define (read-cmd prefix)
(let ((l (read-line)))
(if (eof-object? l) l
(let* ((l (string-append prefix l))
(p (make-string-input-port l)))
(call-with-current-continuation
(lambda (k)
(with-handler (lambda (c punt)
(if (eq? 'read-error (car c))
(k (read-cmd (string-append l "\n")))
(punt)))
(lambda ()
(port->sexp-list p)))))))))
(define (expand cmd)
(define (redirs cmd stack)
(if (null? cmd)
(list (reverse stack))
(case (car cmd)
((< > >> <<) (cons (reverse stack)
(let ((a (redirs (cdr cmd) '())))
(cons (cons (car cmd) (car a))
(cdr a)))))
(else (redirs (cdr cmd) (cons (car cmd) stack))))))
(define (next stack)
(cons 'epf (redirs (reverse stack) '())))
(define (pipes cmd stack)
(cond ((null? cmd) (list (next stack)))
((eq? (car cmd) '|) (cons (next stack) (pipes (cdr cmd) '())))
(else (pipes (cdr cmd) (cons (car cmd) stack)))))
(let ((r (reverse cmd)))
(if (eq? '& (car r))
`(& (| . ,(pipes (reverse (cdr r)) '())))
`(run (| . ,(pipes cmd '()))))))
(define (safe-eval e)
(call-with-current-continuation
(lambda (k)
(define (handle c punt)
(format #t "~S: ~A~%" (car c) (cadr c))
(p (cddr c))
(k (unspecific)))
(with-handler handle
(lambda ()
(eval e (interaction-environment)))))))
(define (one-cmd)
(format #t "cli> ")
(let ((cmd (read-cmd "")))
(cond ((eof-object? cmd) cmd)
((null? cmd) 'empty)
((and (null? (cdr cmd)) (pair? (car cmd)))
(let ((r (safe-eval (car cmd))))
(if (not (eq? r (unspecific)))
(p r))))
((eq? 'cd (car cmd)) (chdir (symbol->string (cadr cmd))))
(else (let ((status (eval (expand cmd)
(interaction-environment))))
(if (and (number? status) (not (zero? status)))
(format #t "exit code ~S~%" status)))))))
(define (cli)
(define (loop)
(if (not (eof-object? (one-cmd)))
(loop)))
(loop)
(format #t "~%cli done~%")
(unspecific))))
--
balance
equilibrium
death
http://www.cs.cmu.edu/~spot
spot@cs.cmu.edu
|