open Sugar;;
open UnixExtra;;
open StringExtra;;
open Wrapper;;
type filename = string;;
type filexpr = string;;
type foldername = string;;
let awk ?(opt="") prog text = textfilter ~at:Treat.quote "awk" ~opt ~args:(Some(prog)) text ;;
let cut args text = textfilter ~at:Treat.identity "cut" ~args:(Some(args)) text ;;
let head ?(opt="") text = textfilter "head" ~opt text ;;
let grep ?(opt="") regexp text = textfilter ~at:Treat.quote "grep" ~opt ~args:(Some(regexp)) text ;;
let nl ?(opt="") text = textfilter "nl" ~opt text ;;
let sed ?(opt="-e") prog text = textfilter ~at:Treat.quote "sed" ~opt ~args:(Some(prog)) text ;;
let sort ?(opt="") text = textfilter "sort" ~opt text ;;
let tac ?(opt="") text = textfilter "tac" ~opt text ;;
let tail ?(opt="") text = textfilter "tail" ~opt text ;;
let tee ?(opt="") (files:filename list) text =
let args = List.map String.quote files in
let args = String.big (String.merge " ") args in
textfilter ~at:Treat.identity "tee" ~opt ~args:(Some args) text ;;
let tr ?(opt="") c1 c2 text =
let s1 = String.quote (Char.escaped c1) in
let s2 = String.quote (Char.escaped c2) in
let args = String.merge " " s1 s2 in
textfilter ~at:Treat.identity "tr" ~opt ~args:(Some args) text ;;
let uniq ?(opt="") text = textfilter "uniq" ~opt text ;;
let wc text : int =
make ~it:(Some String.Text.to_string)
~ot:(String.chop || int_of_string)
"wc -w"
~input:(Some text) () ;;
let cc ?(strict=false) text : int =
let it = Some(if strict then (String.big (^)) else (String.Text.to_string)) in
make ~it
~ot:(String.chop || int_of_string)
"wc -c"
~input:(Some text) () ;;
module Files = struct
let glob ?(null=false) (args:filexpr) =
let shopt = ("shopt "^(if null then "-s" else "-u")^" nullglob\n") in
let cmd = shopt^"for i in \"$@\"; do echo $i; done" in
make ~at:Treat.identity ~ot:String.Text.of_string cmd ~script:true ~args:(Some args) ();;
let cat ?(opt="") (arg:filexpr) =
make ~at:Treat.identity ~ot:String.Text.of_string "cat" ~opt ~args:(Some arg) ();;
let cut ?(opt="") (arg:filexpr) =
make ~at:Treat.identity ~ot:String.Text.of_string "cut" ~opt ~args:(Some arg) ();;
let head ?(opt="") (arg:filexpr) =
make ~at:Treat.identity ~ot:String.Text.of_string "head" ~opt ~args:(Some arg) ();;
let nl ?(opt="") (arg:filexpr) =
make ~at:Treat.identity ~ot:String.Text.of_string "nl" ~opt ~args:(Some arg) ();;
let sort ?(opt="") (arg:filexpr) =
make ~at:Treat.identity ~ot:String.Text.of_string "sort" ~opt ~args:(Some arg) ();;
let tac ?(opt="") (arg:filexpr) =
make ~at:Treat.identity ~ot:String.Text.of_string "tac" ~opt ~args:(Some arg) ();;
let tail ?(opt="") (arg:filexpr) =
make ~at:Treat.identity ~ot:String.Text.of_string "tail" ~opt ~args:(Some arg) ();;
let uniq ?(opt="") (arg:filexpr) =
make ~at:Treat.identity ~ot:String.Text.of_string "uniq" ~opt ~args:(Some arg) ();;
end;;
let date ?(opt="") ?(arg="") () =
make ~at:Treat.identity ~ot:String.chop "date" ~opt ~args:(Some arg) ();;
let id ?(opt="") ?(arg="") () =
make ~at:Treat.identity ~ot:String.chop "id" ~opt ~args:(Some arg) ();;
let uname ?(opt="") () = make ~ot:String.chop "uname" ~opt ();;
let whoami () = make ~ot:String.chop "whoami" ();;
let find (arg:arg) =
make ~at:Treat.identity ~ot:String.Text.of_string "find" ~args:(Some arg) ();;
let dd ?(ibs=None) ?(obs=None) ?(bs=None) ?(cbs=None) ?(skip=None) ?(seek=None) ?(count=None) ?(conv=None)
(x:filename) (y:filename) =
let iF = " if="^(String.quote x) in
let oF = " of="^(String.quote y) in
let ibs = match ibs with (Some n) -> " ibs=" ^ (string_of_int n) | _ -> "" in
let obs = match obs with (Some n) -> " obs=" ^ (string_of_int n) | _ -> "" in
let bs = match bs with (Some n) -> " bs=" ^ (string_of_int n) | _ -> "" in
let cbs = match cbs with (Some n) -> " cbs=" ^ (string_of_int n) | _ -> "" in
let skip = match skip with (Some n) -> " skip=" ^ (string_of_int n) | _ -> "" in
let seek = match seek with (Some n) -> " seek=" ^ (string_of_int n) | _ -> "" in
let count= match count with (Some n) -> " count="^ (string_of_int n) | _ -> "" in
let conv = match conv with (Some n) -> " conv=" ^ (string_of_int n) | _ -> "" in
let arg = (iF^oF^ibs^obs^bs^cbs^skip^seek^count^conv) in
make ~at:Treat.identity ~ot:ignore "dd" ~args:(Some arg) ()
;;
let tgz_create ?(opt="") (fname:filename) (files:filexpr) =
let at (t,e) = ((String.quote t)^" "^e) in
make ~at:(Some at) ~ot:ignore ("tar "^opt^" -czf $@") ~script:true ~args:(Some (fname,files)) ()
;;
let tgz_extract ?(opt="") (fname:filename) (rep:foldername) =
let at (t,r) = ((String.quote t)^" "^(String.quote r)) in
make ~at:(Some at) ~ot:ignore ("tar "^opt^" -C $2 -xzf $1") ~script:true ~args:(Some (fname,rep)) ()
;;
module Check = struct
let check cmd cmdname ?(nullglob=false) (patt:filexpr) =
let wrapper x = make ~at:Treat.quote ~ot:Treat.is_true cmd ~script:true ~args:(Some x) () in
match (Files.glob ~null:nullglob patt) with
| [] -> failwith (cmdname^": argument '"^patt^"' globs to nothing")
| l -> List.for_all wrapper l
;;
end;;
let dir_writable ?(nullglob=false) (dirpatt:filexpr) =
let cmd = "test -d $1 -a -r $1 -a -w $1 && echo true" in
Check.check cmd "dir_writable" ~nullglob dirpatt
;;
let dir_comfortable ?(nullglob=false) (dirpatt:filexpr) =
let cmd = "test -d $1 -a -r $1 -a -w $1 -a -x $1 && echo true" in
Check.check cmd "dir_comfortable" ~nullglob dirpatt
;;
let regfile_readable ?(nullglob=false) (dirpatt:filexpr) =
let cmd = "test -f $1 -a -r $1 && echo true" in
Check.check cmd "regfile_readable" ~nullglob dirpatt
;;
let regfile_modifiable ?(nullglob=false) (dirpatt:filexpr) =
let cmd = "test -f $1 -a -r $1 -a -w $1 && echo true" in
Check.check cmd "regfile_modifiable" ~nullglob dirpatt
;;
let freshname_possible x =
let d = (Filename.dirname x) in
(dir_writable d)
;;