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
OCAMLLEX := ocamllex
OCAMLYACC := menhir --infer --explain --dump
OCAMLOPT_GETOPT := ocamlfind opt -linkpkg -package getopt
.PHONY: all clean
.PRECIOUS: $(addprefix .cmi,$(ALL_NAMES))
......@@ -28,8 +29,11 @@ all: $(RESULT)
%.cmx: %.ml
ocamlopt -c $(OCAMLCFLAGS) -o $@ $(<:.cmi=.ml)
main.cmx: main.ml
$(OCAMLOPT_GETOPT) -c $(OCAMLCFLAGS) -o $@ $(<:.cmi=.ml)
$(RESULT): $(addsuffix .cmx,$(ALL_NAMES))
ocamlopt -o $@ $(OCAMLLDFLAGS) $(OCAMLLDLIBS) $^
$(OCAMLOPT_GETOPT) -o $@ $(OCAMLLDFLAGS) $(OCAMLLDLIBS) $^
# module dependencies
lexer.cmi: lexer.ml
......
......@@ -96,12 +96,13 @@ Output of `mincss -h`:
Building mincss
===============
Dependencies are [OCaml](https://ocaml.org/docs/install.html) 4.0 and
[menhir](http://cristal.inria.fr/~fpottier/menhir/).
Dependencies are [OCaml](https://ocaml.org/docs/install.html) 4.02.0,
[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:
$ 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
$ cd mincss
$ make
......@@ -115,7 +116,7 @@ flexibility:
$ eval `opam config env`
$ opam switch 4.02.0
$ opam update
$ opam install menhir
$ opam install menhir getopt
TODO / bugs
......@@ -132,3 +133,4 @@ TODO / bugs
- `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`.
- 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 = {
simple : bool;
shorthands : bool;
duplicates : bool;
echo : bool;
sort : bool;
}
let parse_args () =
let usage =
"Usage: " ^ Sys.argv.(0) ^
" [<options>] [<file> ...]\n\
\n\
Generic options:\n \
-h, --help Show this help message\n \
-v, --verbose Verbose mode: show compression rate\n \
-o <file> Output file (defaults to stdout)\n \
<file> ... Input files (default is to read from stdin)\n\
\n\
Optimization flags (default is -w -c -s -d):\n \
-w, --whitespace Eliminate unnecessary whitespaces (has the greatest \
effect, omit for pretty-printing)\n \
-c, --simple Shorten colors, font weights and nth-child\n \
-s, --shorthands Generate shorthand properties\n \
-d, --duplicates Prune duplicate properties (WARNING: may affect \
cross-browser hacks)\n \
-p, --pretty Shorthand for -c -s -d\n \
\n\
Formatting options:\n \
-r, --sort Sort declarations in each ruleset (always on when \
--shorthands is enabled)\n \
-e, --echo Just parse and pretty-print, no optimizations\n\
"
in
let usage =
"Usage: " ^ Sys.argv.(0) ^
" [<options>] [<file> ...]\n\
\n\
Generic options:\n \
-h, --help Show this help message\n \
-v, --verbose Verbose mode: show compression rate\n \
-o <file>\n \
--output=<file> Output file (defaults to stdout)\n \
<file> ... Input files (defaults to stdin or \"-\")\n\
\n\
Optimization flags (default is -w -c -s -d):\n \
-w, --whitespace Eliminate unnecessary whitespaces (has the greatest \
effect, omit for pretty-printing)\n \
-c, --simple Shorten colors, font weights and nth-child\n \
-s, --shorthands Generate shorthand properties\n \
-d, --duplicates Prune duplicate properties (WARNING: may affect \
cross-browser hacks)\n \
-p, --pretty Shorthand for -c -s -d\n \
\n\
Formatting options:\n \
-r, --sort Sort declarations in each ruleset (always on when \
--shorthands is enabled)\n \
-e, --echo Just parse and pretty-print, no optimizations\n\
"
let default_args = {
infiles = [];
outfile = None;
verbose = false;
whitespace = false;
simple = false;
shorthands = false;
duplicates = false;
echo = false;
sort = false;
} in
let rec handle args = function
| ("-v" | "--verbose") :: tl ->
handle {args with verbose = true} tl
| ("-w" | "--whitespace") :: tl ->
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
let parse_args () =
let infiles = ref [] in
let outfile = ref None in
let verbose = ref false in
let whitespace = ref false in
let simple = ref false in
let shorthands = ref false in
let duplicates = ref false in
let sort = ref false in
let echo = ref false in
let show_usage () = prerr_string usage; raise Exit_success in
let set_pretty () = simple := true; shorthands := true; duplicates := true in
let add_infile = function
| "-" -> infiles := []
| filename -> infiles := filename :: !infiles
in
match handle default_args (List.tl (Array.to_list Sys.argv)) with
| { echo = true; _ } as args ->
let specs = [
('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
whitespace = false;
simple = false;
shorthands = false;
duplicates = false }
(* enable all optimizations by default *)
| { whitespace = false;
simple = false;
shorthands = false;
......@@ -181,6 +166,9 @@ let main () =
Util.prerr_loc_msg loc ("Error: " ^ msg);
| Box_error (box, msg) ->
prerr_endline ("Error: " ^ msg ^ ": " ^ Stringify.string_of_box box);
| Getopt.Error msg ->
prerr_endline ("Error: " ^ msg ^ "\n");
prerr_string usage;
| Failure msg ->
prerr_endline ("Error: " ^ msg);
| 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