Name: genspio
Owner: Hammer Lab
Description: Generate Shell Phrases In OCaml
Created: 2016-09-09 18:55:45.0
Updated: 2017-11-20 23:44:13.0
Pushed: 2017-12-14 19:29:48.0
Homepage: https://smondet.gitlab.io/genspio-doc/
Size: 326
Language: OCaml
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
Genspio is a typed EDSL to generate shell scripts and commands from OCaml.
The idea is to build values of type 'a EDSL.t
with the
combinators in the Genspio.EDSL
module, and compile them to POSIX
shell scripts (or one-liners) with functions from Genspio.Compile
.
Genspio is still in alpha status. For now the EDSL is based on a big GADT and compiles to POSIX one-liners or multi-line scripts.
The tests run the output of the compiler against a few shells that it tries to
find on the host (e.g. dash
, bash
, busybox
, mksh
, zsh
? cf. the
example test results summary below).
If you have any questions, do not hesitate to submit an issue.
You can install the library though opam
:
opam install genspio
Or get the development version with opam pin
:
opam pin add genspio https://github.com/hammerlab/genspio.git
You can also build locally:
You need OCaml ? 4.03.0 together with
nonstd
,
sosa
, and
jbuilder
:
jbuilder build @install
Here is a quick example:
> open Genspio.EDSL;;
>
c =
t username_one_way : c_string t =
(* We lift the string "USER" to EDSL-land and use function `getenv`: *)
getenv (string "USER") in
t username_the_other_way : c_string t =
(* The usual pipe operator is `||>` *)
(exec ["whoami"] ||> exec ["tr"; "-d"; "\\n"])
(* `get_stdout` takes `stdout` from a `unit t` as a `byte_array t` *)
|> get_stdout
(* `to_c_string` checks that a `byte_array t` can be casted to a `c_string` *)
|> to_c_string
t my_printf : string -> c_string t list -> unit t = fun fmt args ->
(* The function `call` is like `exec` but operates on `c_string t` values
instead of just OCaml strings: *)
call (string "printf" :: string fmt :: args) in
The operator `=$=` is `string t` equality, it returns a `bool t` that
we can use with `if_seq`: *)
_seq (username_one_way =$= username_the_other_way)
~t:[
my_printf "Username matches: `%s`\\n" [username_one_way];
]
~e:[
my_printf "Usernames do not match: `%s` Vs `%s`\\n"
[username_one_way; username_the_other_way];
]
c : unit t
> Sys.command (Genspio.Compile.to_one_liner c);;
name matches: `smondet`
int = 0
More examples:
src/examples/small.ml
which generates a useful list of usage examples.src/examples/downloader.ml
contains a (much) bigger example.hammerlab/secotrec
is a real-world,
larger-scale use of Genspio (for now using version 0.0.1).To run the tests you also need make
and there is an additional dependency on
the uri
library, see:
genspio_test=_build/default/src/test/main.exe
jbuilder build $genspio_test
$genspio_test --help
Try this:
$genspio_test --important-shells bash,dash /tmp/gtests/
cd /tmp/gtests/
make run-all # Attempts to run all the tests on all the shells
make check # Checks that all the tests for the important ones succeeded
You can generate a markdown report:
Some failures are expected with not-really-POSIX or buggy shells like
KSH93, or on some corner cases
cf. #35
.
You can check failures in the <shell-test>/failures.md
files, see for instance
ksh/failures.md
:
test-T-no_name_77-A0-R77-71757b23d6
script/test-T-no_name_77-A0-R77-71757b23d6-script.sh
script/test-T-no_name_77-A0-R77-71757b23d6-run-test.sh
_log/test-T-no_name_77-A0-R77-71757b23d6/stdout.txt
_log/test-T-no_name_77-A0-R77-71757b23d6/stderr.txt
test-T-redirect_fails-A0-R2-5f3e8da336
script/test-T-redirect_fails-A0-R2-5f3e8da336-script.sh
script/test-T-redirect_fails-A0-R2-5f3e8da336-run-test.sh
_log/test-T-redirect_fails-A0-R2-5f3e8da336/stdout.txt
_log/test-T-redirect_fails-A0-R2-5f3e8da336/stderr.txt
(similarly there are <shell-test>/successes.md
files).
From here, one can explore:
It's Apache 2.0.