(* This file is part of our reusable OCaml BRICKS library
Copyright (C) 2007 Jean-Vincent Loddo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. *)
(** 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,..).
*) |
open Sugar;;
open UnixExtra;;
open StringExtra;;
(** A command is a string. *) |
type command = string;;
(** A content is a string. *) |
type content = string;;
(** An argument is a string. *) |
type arg = string ;;
(** A call is a directly executable command, as for instance, "ls" or "wc -l" or "cat | grep -v" . *) |
type call = 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. *) |
type script = string;;
(** Envelop*) |
(** Envelop a script into a function followed by a call of this function.
Example: *) |
let envelop ?(name:string=("auxfun"^(string_of_int (Random.int 819200)))) (script:script) : call =
("function "^name^" () {\n"^script^"\n}\n"^name)
;;
(** Wrapper*) |
(**
*) |
(** General constructor for shell encapsulation:
~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 |
let make
?(at:(('c->string) option)=None)
?(it:(('a->string) option)=None)
~(ot:(string->'b))
?(script=false)
(cmd:command)
?(opt="")
?(args:('c option)=None) ?(input:('a option)=None) () =
let cmd = if script then envelop cmd else cmd in
let perform_treat t x = match (t,x) with
| ((Some f), (Some x)) -> (f x)
| ( _ , None) -> ""
| ( None , (Some x)) -> failwith "Wrapper.make: argument provided without a treatment" in
let args = perform_treat at args in
let input = perform_treat it input in
(cmd^" "^opt^" "^args^"\n") => ((Unix.shell ~trace:false ~input) || ot )
;;
(** Text filters*) |
(** This constructor represent a specialization of the function make
for building wrappers dealing with texts (string lists):
|
let textfilter
?(at:(('c->string) option)=None)
?(script=false)
(cmd:command)
?(opt="")
?(args:('c option)=None) (x:string list)
= make
~at ~script
~it:(Some String.Text.to_string)
~ot:String.Text.of_string cmd
~opt ~args ~input:(Some x) ();;
(** Treatments*) |
(** Common treatments for parameters, inputs and outputs. All treatments are value
of the type ('a -> 'b) option . *) |
module Treat = struct
(* {b Input/Argument treatments} *)
(** Nothing to do (identity function). *) |
let identity = Some (fun x->x) ;;
(** Simple quote the argument. Sometimes, the argument of the filter must be envelopd
into simple quotes, as for awk and sed , in order to prevent problems with special chars. *) |
let quote = Some (fun x -> "'"^x^"'");;
(* {b Output treatments} *)
(** Make your boolean scripts with this output treatment *) |
let is_true = (String.chop || ((=) "true")) ;;
end;; (* module Treat *)
(** ExamplesBasically, 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 more sofisticated wrapper*) |
(** *) |