I'm implementing "||", "&&" and "|" shell syntax in scheme. Maybe it could become part of gauche.process. Before I waste your time with my code. I'd like to check what would be a good design for this. What I have in mind is this. A bit higher level than run-process, but still not the same as scsh. But hopefully we can make scsh wrapper more easily with these.
Process Form
A process is represented by
-
A single string
-
A single symbol
-
A list of strings or symbols (could be intermixed)
-
A list, where the first item is in either three above forms, followed by a list of run-process-like redirects, e.g.
((ls) (> 1 "out") (< 0 "in"))
Process execution
The procedure "run-pf&" takes one process form (pf), executes it and return the process object immediately. This is simply a wrapper around run-process that can handle process forms.
The procedure "run-pf" is like run-pf& except that it waits for the process to terminate and returns the exit code. If the process is signaled, the exit code is in 128+ range like how unix shell does it. Anything that can't be converted to exit code (e.g. process-wait fails) results in an exception.
run-pf can take more than argument too. In that case it executes processes sequentially like scheme "begin" form and returns exit code of the last process.
The procedure "run-and" takes 1+ arguments as process form and executes them in sequence so long as their exit codes are zero, i.e. "&&" syntax. It returns exit code of the last executed process. "run-or" is similar, for "||" syntax.
Redirection is generally ok for run-pf, run-and and run-or, except redirection to ports, for obvious reasons.
Piping
The procedure run-pipe+& has the following form
(define (run-pipe+& first-redir last-redir connect-list . pf/rest))
first-redir and last-redir are two lists of extra redirections for the first and the last process. They are in the same form that of :redirects keyword from run-process. This allows us to setup stdin of the first process, or stdout of the last process.
connect-list specifies how to connect two consecutive processes together. It's the exact same form from scsh's fork/pipe+. For example "((1 2 0) (3 3))" says redirect both stdout and stderr of the first process to stdin of the second one, and redirect fd 3 of the first to 3 of the second.
run-pipe+& immediately returns a list of process objects. For example, we could offload complex processing to some oustide command with
(run-pipe+& '((< 0 input)) '((> 1 output)) '((1 0)) '(cmd1) '(cmd2) '(cmd3))
Then retrieve the two input/output ports from the relevant process objects and start piping.
From that we have a few convenient wrappers:
- run-pipe+ waits for all processes to finish before return, and returns exit code of the last process in pipe. It does not take first-redir/last-redir either
- run-pipe is run-pipe+ with default connection-list ((1 0))