This is the mail archive of the kawa@sourceware.org mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Shell-style programming in Kawa


Hi Per,

On Jan 1, 2014, at 7:38 PM, Per Bothner <per@bothner.com> wrote:

> I checked in some semi-experimental code for Shell-style programming,
> and specifically running processes.  Please play with it and let me
> know how it works.  I have only tested it on Fedora Linux.

It seems to work fine on Mac OS X.

> It's an unusual design for a "process API", and I think it's neat.
> A write-up and "how-to" is in this (draft) blog article:
> 
> http://per.bothner.com/blog/2014/Kawa-shell-programming/
> 
> Please me know if that is unclear, incomplete, or has mistakes.

I did find a minor typo in the blog post:

#|kawa:11|# (define b1 ::bytevector p1)
#u8(87 101 100 32 74 97 110 ... 52 10)

doesn't show the command which caused b1 to get written out.  It should
be something like

#|kawa:11|# (define b1 ::bytevector p1)
#|kawa:12|# (write b1)
#u8(87 101 100 32 74 97 110 ... 52 10)



I like it overall, especially compared to the older functionality:
[(system "ls") => 0 is not very helpful, so the fact that run-process
displays the process's stdout stream is a big plus.]

However, the syntax can get awfully verbose, especially setting up
a pipeline with more than two stages.

$ a | b

becoming

&`[in: &`{a}]{b}

isn't too bad, but

$ a | b | c | d | e

becoming

&`[in: &`[in: &`[in: &`[in: &`{a}]{b}]{c}]{d}]{e}

is kind of unwieldy.  For comparison, the equivalent scsh would be
something like:

(run (| (a)
        (b)
        (c)
        (d)
        (e)))


I whipped up a macro [1] letting me do

(pipe ["ls" "/usr/include"]
      ["grep" "std"]
      ["tr" "[a-z]" "[A-Z]"]
      "grep -i lib")
=> STDLIB.H

but it'd be nice for something like that to be a built-in that doesn't
lose the niceties of the &`{} syntax.  For example, to allow for something
like

&pipe{ &`{ls /tmp}
       &`{grep &`{whoami}}}

The equivalent with my macro is
(pipe "ls /tmp"
      ["grep" (->string (pipe "whoami" ["tr" "-d" "\\n"]))])

because I have to manually strip off the trailing newline from `whoami`
and then coerce the result to a string (that stuff happens automatically
for &`{... &`{whoami} ...}).


Anyway, I look forward to trying to write a real non-toy script with
this, should be fun.

-J


[1] I'm not entirely sure of the guard for the first clause, but it works
for the tests I've tried so far.  

(define-syntax (pipe form)
  (syntax-case form ()
    ((pipe cmd) (or (String? (syntax cmd))
                    (vector? (syntax cmd))
                    (and (list? (syntax cmd))
                         (eq? '$bracket-list$ (car (syntax cmd)))))
     #`(run-process cmd))
    ((pipe proc)
     #`proc)
    ((pipe cmd1 cmd2)
     #`(run-process in: (pipe cmd1) cmd2))
    ((pipe cmd1 cmd2 cmd3 ...)
     #`(pipe (pipe cmd1 cmd2) cmd3 ...))))





--
Jamison Hope
The PTR Group
www.theptrgroup.com




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]