Skip to content

Commit f37cc9e

Browse files
committed
Cookbook recipe to parse command-line arguments with Cmdliner
1 parent da6f727 commit f37cc9e

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
packages:
3+
- name: cmdliner
4+
tested_version: "1.3.0"
5+
used_libraries:
6+
- cmdliner
7+
---
8+
(* In this example, we define a parser for a command-line like this:
9+
10+
```
11+
mycmd --verbose input_file -o output_file
12+
```
13+
14+
`--verbose` and `-o` are optional, and the command should accept multiple
15+
input files.
16+
17+
We can find more examples on
18+
[this page](https://erratique.ch/software/cmdliner/doc/examples.html).
19+
*)
20+
let cmdliner_parser () =
21+
(* `Cmdliner` is a library that allows the declarative definition of
22+
command-line interfaces
23+
([documentation page](https://erratique.ch/software/cmdliner/doc/index.html)).
24+
*)
25+
let open Cmdliner in
26+
(* First we declare the expected arguments of our command-line, and how
27+
`Cmdliner` should parse them. *)
28+
let verbose =
29+
let doc = "Output debug information" in
30+
(* `&` is a right associative composition operator
31+
([documentation](https://erratique.ch/software/cmdliner/doc/Cmdliner/Arg/index.html#val-(&))).
32+
*)
33+
Arg.(value & flag & info ["v" ; "verbose"] ~doc)
34+
and input_files =
35+
let doc = "Input file(s)" in
36+
Arg.(non_empty & pos_all file []
37+
& info [] ~docv:"INPUT" ~doc)
38+
and output_file =
39+
let doc = "Output file"
40+
and docv = "OUTPUT" in
41+
Arg.(value & opt (some string) None
42+
& info ["o"] ~docv ~doc)
43+
(* `mycmd` is the function that the program will apply to the parsed
44+
arguments. *)
45+
and mycmd verbose input_files output_file =
46+
Printf.printf "verbose: %b\n" verbose;
47+
Printf.printf "input files: %s\n"
48+
(input_files |> String.concat ", ");
49+
Printf.printf "output file: %s\n"
50+
(Option.value ~default:"" output_file)
51+
in
52+
(* Declaration of the complete command, including its man-like
53+
documentation. *)
54+
let cmd =
55+
let doc = "An example command"
56+
and man = [
57+
`S Manpage.s_description;
58+
`P "A command that can take multiple files
59+
and outputs a file (optional)."
60+
]
61+
in
62+
Cmd.v (Cmd.info "mycmd" ~doc ~man)
63+
Term.(const mycmd $ verbose $ input_files $ output_file)
64+
in
65+
Cmd.eval cmd
66+
67+
68+
(* Given a command-line like
69+
`mycmd --verbose -o somefile ./dune-project ./cmd_cookbook.opam`, we should
70+
expect the following output:
71+
72+
```
73+
verbose: true
74+
input files: ./dune-project, ./cmd_cookbook.opam
75+
output file: somefile
76+
``` *)
77+
let () =
78+
exit @@ cmdliner_parser ()

0 commit comments

Comments
 (0)