Commit 83d43b96 authored by Taddeüs Kroes's avatar Taddeüs Kroes

Switch to Getopt for parsing cli args

parent f3c25e73
...@@ -10,6 +10,7 @@ OCAMLLDLIBS := str.cmxa ...@@ -10,6 +10,7 @@ OCAMLLDLIBS := str.cmxa
OCAMLLEX := ocamllex OCAMLLEX := ocamllex
OCAMLYACC := menhir --infer --explain --dump OCAMLYACC := menhir --infer --explain --dump
OCAMLOPT_GETOPT := ocamlfind opt -linkpkg -package getopt
.PHONY: all clean .PHONY: all clean
.PRECIOUS: $(addprefix .cmi,$(ALL_NAMES)) .PRECIOUS: $(addprefix .cmi,$(ALL_NAMES))
...@@ -28,8 +29,11 @@ all: $(RESULT) ...@@ -28,8 +29,11 @@ all: $(RESULT)
%.cmx: %.ml %.cmx: %.ml
ocamlopt -c $(OCAMLCFLAGS) -o $@ $(<:.cmi=.ml) ocamlopt -c $(OCAMLCFLAGS) -o $@ $(<:.cmi=.ml)
main.cmx: main.ml
$(OCAMLOPT_GETOPT) -c $(OCAMLCFLAGS) -o $@ $(<:.cmi=.ml)
$(RESULT): $(addsuffix .cmx,$(ALL_NAMES)) $(RESULT): $(addsuffix .cmx,$(ALL_NAMES))
ocamlopt -o $@ $(OCAMLLDFLAGS) $(OCAMLLDLIBS) $^ $(OCAMLOPT_GETOPT) -o $@ $(OCAMLLDFLAGS) $(OCAMLLDLIBS) $^
# module dependencies # module dependencies
lexer.cmi: lexer.ml lexer.cmi: lexer.ml
......
...@@ -96,12 +96,13 @@ Output of `mincss -h`: ...@@ -96,12 +96,13 @@ Output of `mincss -h`:
Building mincss Building mincss
=============== ===============
Dependencies are [OCaml](https://ocaml.org/docs/install.html) 4.0 and Dependencies are [OCaml](https://ocaml.org/docs/install.html) 4.02.0,
[menhir](http://cristal.inria.fr/~fpottier/menhir/). [menhir](http://cristal.inria.fr/~fpottier/menhir/) and
[Getopt](https://forge.ocamlcore.org/projects/ocaml-getopt/).
Bootstrapping on a Debian system can be done as follows: Bootstrapping on a Debian system can be done as follows:
$ sudo apt-get install ocaml menhir git $ sudo apt-get install ocaml menhir libgetopt-ocaml-dev git
$ git clone git@github.com:taddeus/mincss.git $ git clone git@github.com:taddeus/mincss.git
$ cd mincss $ cd mincss
$ make $ make
...@@ -115,7 +116,7 @@ flexibility: ...@@ -115,7 +116,7 @@ flexibility:
$ eval `opam config env` $ eval `opam config env`
$ opam switch 4.02.0 $ opam switch 4.02.0
$ opam update $ opam update
$ opam install menhir $ opam install menhir getopt
TODO / bugs TODO / bugs
...@@ -132,3 +133,4 @@ TODO / bugs ...@@ -132,3 +133,4 @@ TODO / bugs
- `border:none` could be `border:0`, or in general any shorthand that has both - `border:none` could be `border:0`, or in general any shorthand that has both
a `style` and `width` property should be transformed from `none` into `0`. a `style` and `width` property should be transformed from `none` into `0`.
- Automated test suite: auto-diff css files and expected minified versions. - Automated test suite: auto-diff css files and expected minified versions.
- `mincss -s test/duplicates.css` gets stuck in an infinite loop.
...@@ -9,103 +9,88 @@ type args = { ...@@ -9,103 +9,88 @@ type args = {
simple : bool; simple : bool;
shorthands : bool; shorthands : bool;
duplicates : bool; duplicates : bool;
echo : bool;
sort : bool; sort : bool;
} }
let parse_args () = let usage =
let usage = "Usage: " ^ Sys.argv.(0) ^
"Usage: " ^ Sys.argv.(0) ^ " [<options>] [<file> ...]\n\
" [<options>] [<file> ...]\n\ \n\
\n\ Generic options:\n \
Generic options:\n \ -h, --help Show this help message\n \
-h, --help Show this help message\n \ -v, --verbose Verbose mode: show compression rate\n \
-v, --verbose Verbose mode: show compression rate\n \ -o <file>\n \
-o <file> Output file (defaults to stdout)\n \ --output=<file> Output file (defaults to stdout)\n \
<file> ... Input files (default is to read from stdin)\n\ <file> ... Input files (defaults to stdin or \"-\")\n\
\n\ \n\
Optimization flags (default is -w -c -s -d):\n \ Optimization flags (default is -w -c -s -d):\n \
-w, --whitespace Eliminate unnecessary whitespaces (has the greatest \ -w, --whitespace Eliminate unnecessary whitespaces (has the greatest \
effect, omit for pretty-printing)\n \ effect, omit for pretty-printing)\n \
-c, --simple Shorten colors, font weights and nth-child\n \ -c, --simple Shorten colors, font weights and nth-child\n \
-s, --shorthands Generate shorthand properties\n \ -s, --shorthands Generate shorthand properties\n \
-d, --duplicates Prune duplicate properties (WARNING: may affect \ -d, --duplicates Prune duplicate properties (WARNING: may affect \
cross-browser hacks)\n \ cross-browser hacks)\n \
-p, --pretty Shorthand for -c -s -d\n \ -p, --pretty Shorthand for -c -s -d\n \
\n\ \n\
Formatting options:\n \ Formatting options:\n \
-r, --sort Sort declarations in each ruleset (always on when \ -r, --sort Sort declarations in each ruleset (always on when \
--shorthands is enabled)\n \ --shorthands is enabled)\n \
-e, --echo Just parse and pretty-print, no optimizations\n\ -e, --echo Just parse and pretty-print, no optimizations\n\
" "
in
let default_args = { let parse_args () =
infiles = []; let infiles = ref [] in
outfile = None; let outfile = ref None in
verbose = false; let verbose = ref false in
whitespace = false; let whitespace = ref false in
simple = false; let simple = ref false in
shorthands = false; let shorthands = ref false in
duplicates = false; let duplicates = ref false in
echo = false; let sort = ref false in
sort = false; let echo = ref false in
} in
let show_usage () = prerr_string usage; raise Exit_success in
let rec handle args = function let set_pretty () = simple := true; shorthands := true; duplicates := true in
| ("-v" | "--verbose") :: tl -> let add_infile = function
handle {args with verbose = true} tl | "-" -> infiles := []
| ("-w" | "--whitespace") :: tl -> | filename -> infiles := filename :: !infiles
handle {args with whitespace = true} tl
| ("-c" | "--simple") :: tl ->
handle {args with simple = true} tl
| ("-s" | "--shorthands") :: tl ->
handle {args with shorthands = true} tl
| ("-d" | "-duplicates") :: tl ->
handle {args with duplicates = true} tl
| ("-p" | "--pretty") :: tl ->
handle {args with simple = true; shorthands = true; duplicates = true} tl
| ("-e" | "--echo") :: tl ->
handle {args with echo = true} tl
| ("-r" | "--sort") :: tl ->
handle {args with sort = true} tl
| ("-h" | "--help") :: tl ->
prerr_string usage;
raise Exit_success
| ["-o"] ->
raise (Failure ("missing output file name"))
| "-o" :: next :: tl when next.[0] = '-' ->
raise (Failure ("missing output file name"))
| "-o" :: filename :: tl ->
handle {args with outfile = Some filename} tl
| arg :: tl when String.length arg > 2 && arg.[0] = '-' && arg.[1] <> '-' ->
let rec handle_opts args = function
| i when i = String.length arg -> args
| i -> handle_opts (handle args ["-" ^ String.make 1 arg.[i]]) (i + 1)
in
handle (handle_opts args 1) tl
| arg :: tl when arg.[0] = '-' ->
prerr_endline usage;
raise (Failure ("unknown option " ^ arg))
| filename :: tl ->
handle {args with infiles = args.infiles @ [filename]} tl
| [] -> args
in in
match handle default_args (List.tl (Array.to_list Sys.argv)) with let specs = [
| { echo = true; _ } as args -> ('h', "help", Some show_usage, None);
('v', "verbose", Getopt.set verbose true, None);
('o', "output", None, Some (fun file -> outfile := Some file));
('w', "whitespace", Getopt.set whitespace true, None);
('c', "simple", Getopt.set simple true, None);
('s', "shorthands", Getopt.set shorthands true, None);
('d', "duplicates", Getopt.set duplicates true, None);
('p', "pretty", Some set_pretty, None);
('r', "sort", Getopt.set sort true, None);
('e', "echo", Getopt.set echo true, None);
] in
Getopt.parse_cmdline specs add_infile;
match {
infiles = List.rev !infiles;
outfile = !outfile;
verbose = !verbose;
whitespace = !whitespace;
simple = !simple;
shorthands = !shorthands;
duplicates = !duplicates;
sort = !sort;
} with
(* disable optimizations when --echo is specified *)
| args when !echo = true ->
{ args with { args with
whitespace = false; whitespace = false;
simple = false; simple = false;
shorthands = false; shorthands = false;
duplicates = false } duplicates = false }
(* enable all optimizations by default *)
| { whitespace = false; | { whitespace = false;
simple = false; simple = false;
shorthands = false; shorthands = false;
...@@ -181,6 +166,9 @@ let main () = ...@@ -181,6 +166,9 @@ let main () =
Util.prerr_loc_msg loc ("Error: " ^ msg); Util.prerr_loc_msg loc ("Error: " ^ msg);
| Box_error (box, msg) -> | Box_error (box, msg) ->
prerr_endline ("Error: " ^ msg ^ ": " ^ Stringify.string_of_box box); prerr_endline ("Error: " ^ msg ^ ": " ^ Stringify.string_of_box box);
| Getopt.Error msg ->
prerr_endline ("Error: " ^ msg ^ "\n");
prerr_string usage;
| Failure msg -> | Failure msg ->
prerr_endline ("Error: " ^ msg); prerr_endline ("Error: " ^ msg);
| Exit_success -> | Exit_success ->
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment