This is the mail archive of the
kawa@sourceware.org
mailing list for the Kawa project.
Re: Shell-style programming in Kawa
- From: Jamison Hope <jrh at theptrgroup dot com>
- To: Per Bothner <per at bothner dot com>
- Cc: "kawa at sourceware dot org list" <kawa at sourceware dot org>
- Date: Wed, 22 Jan 2014 19:01:44 -0500
- Subject: Re: Shell-style programming in Kawa
- Authentication-results: sourceware.org; auth=none
- References: <52C4B518 dot 5080000 at bothner dot com>
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