Module Wrapper (.ml)


module Wrapper: sig .. end
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 module Shell for building a significative set of ready-to-use wrappers corresponding to the most famous Unix tools (grep, dd, tar,..).

type command = string 
A command is a string.
type content = string 
A content is a string.
type arg = string 
An argument is a string.
type call = string 
A call is a directly executable command, as for instance, "ls" or "wc -l" or "cat | grep -v".
type script = string 
A script is a command containing some positional parameters $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.

Envelop


val envelop : ?name:string -> script -> call
Envelop a script into a function followed by a call of this function.

Example:

# print_endline (envelop "test -d $1");;
function auxfun418234 () {
test -d $1
}
auxfun418234
  : unit = ()


Wrapper



 
                                           ?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
General constructor for shell encapsulation:

If the flag ~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).


Text filters


val textfilter : ?at:('a -> string) option ->
?script:bool ->
command ->
?opt:string -> ?args:'a option -> StringExtra.String.line list -> string list
This constructor represent a specialization of the function Wrapper.make for building wrappers dealing with texts (string lists):

Treatments


module Treat: sig .. end
Common treatments for parameters, inputs and outputs.

Examples

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.

Quick and easy wrapper



(* 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 more sofisticated wrapper



(* 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"