module Wrapper:Handling shell scripts in OCaml. A general technique for wrapping shell commands or scripts is proposed in this module. The technique is applied in the modulesig
..end
Shell
for building a significative set
of ready-to-use wrappers corresponding to the most famous Unix tools
(grep, dd, tar,..).typecommand =
string
typecontent =
string
typearg =
string
typecall =
string
"ls"
or "wc -l"
or "cat | grep -v"
.typescript =
string
$1
, $2
,...
as for instance "test -d $1 && echo true"
.
A script is not directly executable but can be easily enveloped in a shell function
in order to become executable by the shell interpreter.val envelop : ?name:string -> script -> call
Example:
# print_endline (envelop "test -d $1");;
function auxfun418234 () {
test -d $1
}
auxfun418234
: unit = ()
?args:'a
|
+-----+-----+
| ?at | argument(s)
?opt +-----+-----+ treatment
| |
+----------+--+
+-----------+ | Unix.shell | +-----------+
?input:'b -->+ ?it +-------->+ +-------->+ ~ot +-->'c
+-----------+ | command | +-----------+
input treatment +-------------+ output treatment
val make : ?at:('a -> string) option ->
?it:('b -> UnixExtra.Unix.content) option ->
ot:(string -> 'c) ->
?script:bool ->
command ->
?opt:string -> ?args:'a option -> ?input:'b option -> unit -> 'c
~it
(the input treatment, by default None
) represent the action
to execute before the command
, in order to transform a value of a
type 'b
into a string
; the result
will be used as standard input for the command
;~ot
(the output treatment) represent the action
to execute after the command
in order to transform its standard output (a string
)
in a value of an arbitrary type 'c
;~at
(the argument treatment, by default None
) permits a similar
re-arrangement of the signature,
but for the argument(s) of the command, which could be of any type 'a
(then
also a tuple). This function converts the argument(s) in a string,
which is the suitable type for the command
; ~opt=""
) are appended as-is at right side of the
command and before the string representation of arguments. ~script
is set the command
is enveloped in order to allow the
use of positionnal parameters $1
, $2
,... By default ~script=false
.
The function raises a failure if an argument or an input is provided
(in the form Some v
)
while the corresponding treatment is undefined (equals to None
).
val textfilter : ?at:('a -> string) option ->
?script:bool ->
command ->
?opt:string -> ?args:'a option -> StringExtra.String.line list -> string list
Wrapper.make
for building wrappers dealing with texts (string lists):~it
is set to Some String.Text.to_string
~ot
is set to String.Text.of_string
module Treat:sig
..end
Basically, the wrapper constructor may be used in a "quick and easy" way using strings
as parameters of the resulting wrapper. Instead, the more sofisticated way constists
in defining a real abstract syntax for parameters and/or inputs, in order to avoid
bad calls of the wrapper at compile-time.
(* A wrapper for the command date *)
let date ?(opt="") ?(arg="") () =
make ~at:Treat.identity ~ot:String.chop "date" ~args:(Some arg) ~opt () ;;
(* Examples of usage: *)
# date () ;;
: string = "lun avr 16 14:28:57 CEST 2007"
# date ~opt:"-r" ~arg:"shell.ml" () ;;
: string = "sam avr 14 16:58:22 CEST 2007"
# date ~arg:"-r shell.ml" () ;;
: string = "sam avr 14 16:58:22 CEST 2007"
(* A wrapper for the command date with an abstract syntax for parameters. *)
module Date = struct
(* (1) Define your abstract syntax (for parameters and/or input and/or output).
In this case for parameters: *)
type options = Option_f of string | Option_r of string | Option_R ;;
type synopsis = options list ;;
(* (2) Define your conversion(s) *)
let string_of_options = function
| Option_f x -> "-f "^x
| Option_r x -> "-r "^x
| Option_R -> "-R "
;;
let string_of_synopsis = String.merge_map string_of_options;;
(* (3) Apply the wrapper constructor *)
let date (args:synopsis) =
make ~at:(Some string_of_synopsis) ~ot:String.chop "date" ~args:(Some args) ()
;;
end;;
(* Example of usage *)
# date [Option_r "shell.ml"];;
: string = "sam avr 14 16:58:22 CEST 2007"