Gauche Devlog

< Code is soft, interface is hard | Exact sqrt >


More control on redirection in run-process

Whew, these days I can only work on Gauche in smaller chunks of time spans, and there are lots of small changes that are not documented. Today I finally managed to document the new interface of run-process in gauche.process module. Now you can specify I/O redirections of the child process as flexible as you can in unix shells.

For example, you can consolidate subprocess's stdout and stderr:

(let1 p (run-process '(command arg ...) 
                     :redirects '((> 1 out) (>& 2 1))
  (begin0 (process->string (process-output p 'out))
          (process-wait p)))

Here (> 1 out) specifies process's file descriptor 1 is fed to a pipe identified by a symbol 'out. Another end of the pipe is retrieved by process-output. (>& 2 1) makes process's file descriptor 2 refer to the same sink as its file descriptor 1.

If you do (> 1 "out"), then the output is sent to a file named "out". You can also use (>> 1 "out") to append, just like the shell.

Using (<< fd "data") or (<< fd #u8(data ...)) allows you to feed the immediate data to the child process. A slight variation (<<< fd obj) uses written representation of obj as the process's input.

It is a upper-compatible extension to the existing mechanism. The current :input, :output and :error redirection arguments are interpreted like the following redirection specification:

:input x   = :redirects '((< 0 x))
:output x  = :redirects '((> 1 x))
:error x   = :redirects '((> 2 x))

The current :input :pipe etc are interpreted as follows:

:input :pipe   = :redirects '((< 0 stdin))
:output :pipe  = :redirects '((> 1 stdout))
:error :pipe   = :redirects '((> 2 stderr))

That is, they'll create pipes identified by symbols stdin, stdout and stderr, respectively. If you call (process-input process) or (process-output process), omitting the pipe name, then stdin and stdout are assumed respectively. So the existing code keeps working.

See the updated manual entry in svn repo for the full spec.

The next step will be to handle multiple processes and piping among them. Something like scsh's process forms. Originally I planned to port scsh's process operations, but now I'm thinking a bit different, more functional (combinatorial) approach than using macros and effectively introducing mini-DSL like scsh. That is, the base function creates a process runner closure, which can be combined and wired together by combinators, then you kick the whole thing to run. This idea is still vague and I'm not sure it can be in to the 0.9.1. But the I/O extension described here will be.

Tags: gauche.process, run-process, scsh

Post a comment