open Lexing open Types type args = { mutable infiles : string list; mutable outfile : string option; mutable verbose : int; mutable echo : bool; } (* Parse command-line arguments *) let parse_args () = let args = { infiles = []; outfile = None; verbose = 1; echo = false; } in let args_spec = [ ("<file> ...", Arg.Rest (fun _ -> ()), " Optional input files (default is to read from stdin)"); ("-o", Arg.String (fun s -> args.outfile <- Some s), "<file> Output file (defaults to stdout)"); ("-v", Arg.Int (fun i -> args.verbose <- i), "<num> Set verbosity (0: nothing, 1: errors (default), \ 2: compression rate, 3: debug)"); ("--echo", Arg.Unit (fun _ -> args.echo <- true), " Don't minify, just pretty-print the parsed CSS"); ] in let usage = "Usage: " ^ Sys.argv.(0) ^ " [-o <file>] [-v <verbosity>] [<file> ...]" in Arg.parse args_spec (fun f -> args.infiles <- args.infiles @ [f]) usage; args let parse_files = function | [] -> let input = Util.input_buffered stdin 512 in (input, Parse.parse_input "<stdin>" input) | files -> let rec loop = function | [] -> [] | filename :: tl -> let input = Util.input_all (open_in filename) in let stylesheet = Parse.parse_input filename input in (input, stylesheet) :: loop tl in let inputs, stylesheets = List.split (loop files) in (String.concat "" inputs, List.concat stylesheets) let handle_args args = let input, stylesheet = parse_files args.infiles in let write_output = match args.outfile with | None -> print_endline | Some name -> fun css -> let f = open_out name in output_string f css; close_out f in match args with | {echo = true} -> write_output (Stringify.string_of_stylesheet stylesheet) | _ -> let stylesheet = Color.compress stylesheet in let output = Stringify.minify_stylesheet stylesheet in write_output output; if args.verbose >= 2 then begin let il = String.length input in let ol = String.length output in Printf.fprintf stderr "compression: %d -> %d bytes (%d%% of original)\n" il ol (int_of_float (float_of_int ol /. float_of_int il *. 100.)) end (* Main function, returns exit status *) let main () = let args = parse_args () in begin try handle_args args; exit 0 with | Loc_error (loc, msg) -> Util.prerr_loc_msg (args.verbose >= 1) loc ("Error: " ^ msg); | Failure err -> prerr_endline ("Error: " ^ err); end; exit 1 let _ = main ()