I’m happy to announce Feather 0.3.0! Feather is a minimal library for bash-like scripting and process execution. (github/tutorial, documentation) This release adds two major features:
1. A new interface for collecting the exit status, stdout, and stderr of a Feather command.
For example, you can easily print a process’s stderr if it exits non-zero:
open Feather;;
let stderr, status =
process "ls" [ "/tmp/does-not-exist" ] |> collect stderr_and_status
in
if status <> 0 then failwith ("ls failed with stderr:\n" ^ stderr)
where the types are
val process : string -> string list -> cmd
type 'a what_to_collect
val stderr_and_status : (string * int) what_to_collect
val collect :
?cwd:string ->
?env:(string * string) ->
'a what_to_collect ->
cmd ->
'a
as you can imagine, we expose several of these what_to_collect
's. Here’s the full set:
val stdout : string what_to_collect
val stderr : string what_to_collect
val status : int what_to_collect
val stdout_and_stderr : (string * string) what_to_collect
val stdout_and_status : (string * int) what_to_collect
val stderr_and_status : (string * int) what_to_collect
type everything = { stdout : string; stderr : string; status : int }
val everything : everything what_to_collect
We considered different design approaches here. I think what we landed on keeps the call site readable and the types of the interface simple.
It should be noted: the simplest way to run a command without collecting anything is to use Feather.run.
2. The ability to wait on background processes and collect their output.
Starting with Feather 0.1.0, you were able to start processes in the background, but the only way to wait for them to complete was to use Feather’s async wrapper. For those wanting an async-less, direct-style interface, we now expose new methods to do this properly:
type 'a background_process
val run_in_background :
?cwd:string ->
?env:(string * string) Base.list ->
cmd ->
unit background_process
val collect_in_background :
?cwd:string ->
?env:(string * string) list ->
'a what_to_collect ->
cmd ->
'a background_process
val wait : 'a background_process -> 'a
val wait_all : unit -> unit
where an example use might be
let server_process =
process "my-server.exe" [] |> collect_in_background stdout_and_status
in
... do other things ...
match Feather.wait server_process with
| (stdout, 0) -> ...
| (_, 1) -> ...
Thanks again to @Firobe and @tmarti2 for their contributions to this release! I think we’ve made a lot of progress here and I’m excited to see where things go