|
4 | 4 |
|
5 | 5 | A declarative command-line parser for OCaml. |
6 | 6 |
|
7 | | -## Rationale |
| 7 | +The API is documented [here](https://ocaml.org/p/climate/latest). |
8 | 8 |
|
9 | | -Programs written in OCaml should conform to existing UX conventions so as to |
10 | | -match the expectations of users coming from other tools. For command-line |
11 | | -programs which wish to parse their arguments in a declarative style, existing |
12 | | -solutions all seem to deviate from the conventions established by common Unix |
13 | | -tools. The two popular libraries for declarative command-line argument parsing |
14 | | -in OCaml are`cmdliner` and `base`'s `Command` module. Both of these libraries |
15 | | -present unconventional behaviour in that non-ambiguous prefixes of arguments are |
16 | | -treated as the full argument names. Additionally, `cmdliner` lacks support for |
17 | | -generating shell autocompletion scripts, and `base` only supports arguments |
18 | | -beginning with a single `-`. |
| 9 | +## About |
19 | 10 |
|
20 | | -This library aims to be an alternative to `cmdliner` and `Base.Command` with |
21 | | -support for generating autocompletion scripts and which behaves as |
22 | | -conventionally as possible. |
| 11 | +A library for parsing command-line arguments in a declarative style, where |
| 12 | +specifying the parser spec and assigning parsed arguments to variables in your |
| 13 | +program is done with the same code. Climate supports CLIs with nested |
| 14 | +subcommands, and can automatically generate help messages, manpages, and shell |
| 15 | +completion scripts. |
23 | 16 |
|
24 | | -## Example |
| 17 | +Here's a tiny example: |
| 18 | +```ocaml |
| 19 | +let open Arg_parser in |
| 20 | +let+ flag_foo = flag [ "foo" ] ~doc:"some flag" |
| 21 | +and+ value_bar = named_opt [ "bar" ] string ~doc:"some string value" |
| 22 | +in |
| 23 | +(* ...do something with the parsed values... *) |
| 24 | +``` |
| 25 | + |
| 26 | +## Full Example |
25 | 27 |
|
26 | 28 | Here's a complete example program with built-in support for generating its own |
27 | 29 | completion script. |
@@ -70,46 +72,63 @@ let main ~bold ~underline ~color words = |
70 | 72 |
|
71 | 73 | let () = |
72 | 74 | let command = |
73 | | - Command.singleton ~desc:"Echo with style!" |
| 75 | + Command.singleton ~doc:"Echo with style!" |
74 | 76 | @@ |
75 | 77 | let open Arg_parser in |
76 | | - (* Describe and parse the command line arguments:*) |
77 | | - let+ bold = flag [ "bold" ] ~desc:"Make the text bold" |
78 | | - and+ underline = flag [ "underline" ] ~desc:"Underline the text" |
79 | | - and+ color = named_opt [ "color" ] Color.conv ~desc:"Set the text color" |
| 78 | + (* Describe and parse the command line arguments: *) |
| 79 | + let+ bold = flag [ "bold" ] ~doc:"Make the text bold" |
| 80 | + and+ underline = flag [ "underline" ] ~doc:"Underline the text" |
| 81 | + and+ color = named_opt [ "color" ] Color.conv ~doc:"Set the text color" |
80 | 82 | and+ words = pos_all string |
81 | 83 | and+ completion = |
82 | | - flag [ "completion" ] ~desc:"Print this program's completion script and exit" |
| 84 | + flag [ "completion" ] ~doc:"Print this program's completion script and exit" |
83 | 85 | in |
84 | 86 | if completion |
85 | 87 | then `Completion |
86 | 88 | else `Main (fun () -> main ~bold ~underline ~color words) |
87 | 89 | in |
88 | 90 | (* Run the parser yielding either a main function to call or an indication |
89 | 91 | that we should print the completion script. *) |
90 | | - match Command.run command with |
| 92 | + let help_style = |
| 93 | + let open Help_style in |
| 94 | + { program_doc = { ansi_style_plain with color = Some `Green } |
| 95 | + ; usage = { ansi_style_plain with color = Some `Yellow } |
| 96 | + ; section_heading = { ansi_style_plain with color = Some `Red } |
| 97 | + ; arg_name = { ansi_style_plain with color = Some `Blue } |
| 98 | + ; arg_doc = { ansi_style_plain with color = Some `Cyan } |
| 99 | + ; error = { ansi_style_plain with color = Some `Red } |
| 100 | + } |
| 101 | + in |
| 102 | + match |
| 103 | + Command.run ~program_name:(Literal "echo-ansi") ~version:"0.0.1" ~help_style command |
| 104 | + with |
91 | 105 | | `Completion -> print_endline (Command.completion_script_bash command) |
92 | 106 | | `Main main -> main () |
93 | | -; |
| 107 | +;; |
94 | 108 | ``` |
95 | 109 |
|
96 | 110 | This program lives in `examples/echo_ansi.ml`. Run it with `dune exec |
97 | 111 | examples/echo_ansi.exe -- <ARGS>`. E.g. |
98 | 112 |
|
99 | 113 | ``` |
100 | 114 | $ dune exec examples/echo_ansi.exe -- --help |
101 | | -Usage: _build/default/examples/echo_ansi.exe [OPTIONS] [STRING]... |
102 | | -
|
103 | 115 | Echo with style! |
104 | 116 |
|
| 117 | +Usage: echo-ansi [OPTION]… [STRING]… |
| 118 | +
|
| 119 | +Arguments: |
| 120 | + [STRING]... |
| 121 | +
|
105 | 122 | Options: |
106 | | - --bold Make the text bold |
107 | | - --underline Underline the text |
108 | | - --color <COLOR> Set the text color |
109 | | - --completion Print this program's completion script and exit |
110 | | - --help, -h Print help |
| 123 | + --bold Make the text bold |
| 124 | + --underline Underline the text |
| 125 | + --color <COLOR> Set the text color |
| 126 | + --completion Print this program's completion script and exit |
| 127 | + -h, --help Show this help message. |
111 | 128 | ``` |
112 | 129 |
|
| 130 | +## Shell Completion |
| 131 | + |
113 | 132 | The easiest way to setup the completion script is to first put the executable |
114 | 133 | in a directory in your PATH. E.g. |
115 | 134 | ``` |
@@ -147,52 +166,7 @@ compinit |
147 | 166 | bashcompinit |
148 | 167 | ``` |
149 | 168 |
|
150 | | -## Manual |
151 | | - |
152 | | -### Terminology |
153 | | - |
154 | | -__Term__ will refer to each space-delimited string on the command line after the |
155 | | -program name. The command `ls -l --color=always /etc/` has 3 terms. The program |
156 | | -name is `ls` (not a term), and the terms are `-l`, `--color=always`, and |
157 | | -`/etc/`. |
158 | | - |
159 | | -__Argument__ will refer to each distinct piece of information passed to the |
160 | | -program on the command line. The command `make -td --jobs 4 all` has 4 |
161 | | -arguments. The `-td` term is made up of two arguments combined into a single |
162 | | -term: `-t` and `-d` (more on this later). `--jobs 4` is a single argument |
163 | | -comprising two terms, where `4` is a parameter to the argument `--jobs`. The |
164 | | -final term `all` is also an argument. |
165 | | - |
166 | | -Arguments may be __positional__ or __named__. Positional arguments are |
167 | | -identified by their position in the argument list rather than by name. Named |
168 | | -arguments may have two forms: __short__ and __long__. Short named arguments |
169 | | -begin with a single `-` followed by a single non `-` character, such as `-l`. |
170 | | -Long named arguments begin with `--` followed by one or more non `-` characters, |
171 | | -such as `--jobs`. A collection of short named arguments may be combined together |
172 | | -with a single leading `-` followed by each short argument name. For example in |
173 | | -`ls -la`, the `-la` is an alternative way of writing `-l -a`. |
174 | | - |
175 | | -A named argument may take a __parameter__. A parameter is a single value which |
176 | | -follows the argument on the command line. Using `make`'s `--jobs` argument as an |
177 | | -example, here are the different ways of passing a parameter to a named argument |
178 | | -on the command line: |
179 | | - |
180 | | -``` |
181 | | -make --jobs=4 # long name with equals sign |
182 | | -make --jobs 4 # long name space delimited |
183 | | -make -j 4 # short name space delimited |
184 | | -make -j4 # short name without space |
185 | | -``` |
186 | | - |
187 | | -If multiple short arguments are combined into a single term then only one of |
188 | | -those arguments may take a parameter. If the parameterized argument appears as |
189 | | -the final argument in the sequence then the following term will be treated as |
190 | | -its parameter, such as in `make -dj 4`, which is equivalent to `make -d -j 4`. |
191 | | -If the parameterized argument appears in a non-final position within the |
192 | | -sequence then the remainder of the sequence is treated as its parameter, such as |
193 | | -in `make -dj4` which is also equivalent to `make -d -j 4`. |
194 | | - |
195 | | -### Manpages |
| 169 | +## Manpages |
196 | 170 |
|
197 | 171 | To generate a manpage for a command, run the command with the hidden flag |
198 | 172 | `--manpage`. This command will print the manpage in the troff format to stdout. |
|
0 commit comments