main.ml 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. open Lexing
  2. open Types
  3. type args = {
  4. mutable infiles : string list;
  5. mutable outfile : string option;
  6. mutable verbose : int;
  7. mutable echo : bool;
  8. }
  9. (* Parse command-line arguments *)
  10. let parse_args () =
  11. let args = {
  12. infiles = [];
  13. outfile = None;
  14. verbose = 1;
  15. echo = false;
  16. } in
  17. let args_spec = [
  18. ("<file> ...", Arg.Rest (fun _ -> ()),
  19. " Optional input files (default is to read from stdin)");
  20. ("-o", Arg.String (fun s -> args.outfile <- Some s),
  21. "<file> Output file (defaults to stdout)");
  22. ("-v", Arg.Int (fun i -> args.verbose <- i),
  23. "<num> Set verbosity (0: nothing, 1: errors (default), \
  24. 2: compression rate, 3: debug)");
  25. ("--echo", Arg.Unit (fun _ -> args.echo <- true),
  26. " Don't minify, just pretty-print the parsed CSS");
  27. ] in
  28. let usage =
  29. "Usage: " ^ Sys.argv.(0) ^ " [-o <file>] [-v <verbosity>] [<file> ...]"
  30. in
  31. Arg.parse args_spec (fun f -> args.infiles <- args.infiles @ [f]) usage;
  32. args
  33. let parse_files = function
  34. | [] ->
  35. let input = Util.input_buffered stdin 512 in
  36. (input, Parse.parse_input "<stdin>" input)
  37. | files ->
  38. let rec loop = function
  39. | [] -> []
  40. | filename :: tl ->
  41. let input = Util.input_all (open_in filename) in
  42. let stylesheet = Parse.parse_input filename input in
  43. (input, stylesheet) :: loop tl
  44. in
  45. let inputs, stylesheets = List.split (loop files) in
  46. (String.concat "" inputs, List.concat stylesheets)
  47. let handle_args args =
  48. let input, stylesheet = parse_files args.infiles in
  49. let write_output =
  50. match args.outfile with
  51. | None -> print_endline
  52. | Some name ->
  53. fun css -> let f = open_out name in output_string f css; close_out f
  54. in
  55. match args with
  56. | {echo = true} ->
  57. write_output (Stringify.string_of_stylesheet stylesheet)
  58. | _ ->
  59. let stylesheet = Color.compress stylesheet in
  60. let output = Stringify.minify_stylesheet stylesheet in
  61. write_output output;
  62. if args.verbose >= 2 then begin
  63. let il = String.length input in
  64. let ol = String.length output in
  65. Printf.fprintf stderr "compression: %d -> %d bytes (%d%% of original)\n"
  66. il ol (int_of_float (float_of_int ol /. float_of_int il *. 100.))
  67. end
  68. (* Main function, returns exit status *)
  69. let main () =
  70. let args = parse_args () in
  71. begin
  72. try
  73. handle_args args;
  74. exit 0
  75. with
  76. | Loc_error (loc, msg) ->
  77. Util.prerr_loc_msg (args.verbose >= 1) loc ("Error: " ^ msg);
  78. | Failure err ->
  79. prerr_endline ("Error: " ^ err);
  80. end;
  81. exit 1
  82. let _ = main ()