Skip to content

Commit 3016283

Browse files
committed
Improve README.md
- add option docs - add note about null defaults - add info about help formatting - add build config section - move delegate modification section later
1 parent 40202f1 commit 3016283

File tree

1 file changed

+177
-71
lines changed

1 file changed

+177
-71
lines changed

README.md

Lines changed: 177 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -52,91 +52,96 @@ class MyArgs(parser: ArgParser) {
5252

5353
Various types of options can be parsed from the command line arguments:
5454

55-
- Boolean flags are created by asking the parser for a `flagging` delegate. One
56-
or more option names, either short or long style, must be provided:
55+
### Boolean Flags
5756

58-
```kotlin
59-
val verbose by parser.flagging("-v", "--verbose",
60-
help = "enable verbose mode")
61-
```
57+
Boolean flags are created by asking the parser for a `flagging` delegate. One
58+
or more option names, either short or long style, must be provided:
6259

63-
Here the presence of either `-v` or `--verbose` options in the
64-
arguments will cause the `Boolean` property `verbose` to be `true`, otherwise
65-
it will be `false`.
60+
```kotlin
61+
val verbose by parser.flagging("-v", "--verbose",
62+
help = "enable verbose mode")
63+
```
6664

67-
- Single argument options are created by asking the parser for a
68-
`storing` delegate.
65+
Here the presence of either `-v` or `--verbose` options in the
66+
arguments will cause the `Boolean` property `verbose` to be `true`, otherwise
67+
it will be `false`.
6968

70-
```kotlin
71-
val name by parser.storing("-N", "--name",
72-
help = "name of the widget")
73-
```
69+
### Storing a Single Argument
7470

75-
Here either `-N` or `--name` with an argument will cause `name` to have that
76-
argument as its value.
71+
Single argument options are created by asking the parser for a
72+
`storing` delegate.
7773

78-
A function can also be supplied to transform the argument into the desired
79-
type. Here the `size` property will be an `Int` rather than a `String`:
74+
```kotlin
75+
val name by parser.storing("-N", "--name",
76+
help = "name of the widget")
77+
```
8078

81-
```kotlin
82-
val size by parser.storing("-s", "--size",
83-
help = "size of the plumbus") { toInt() }
84-
```
79+
Here either `-N` or `--name` with an argument will cause `name` to have that
80+
argument as its value.
8581

86-
- Options that add to a `Collection` each time they
87-
appear in the arguments are created with using the `adding` delegate. Just like `storing`
88-
delegates, a transform function may optionally be supplied:
82+
A function can also be supplied to transform the argument into the desired
83+
type. Here the `size` property will be an `Int` rather than a `String`:
8984

90-
```kotlin
91-
val includeDirs by parser.adding(
92-
"-I", help = "directory to search for header files") { File(this) }
93-
```
85+
```kotlin
86+
val size by parser.storing("-s", "--size",
87+
help = "size of the plumbus") { toInt() }
88+
```
9489

95-
Now each time the `-I` option appears, its argument is appended to
96-
`includeDirs`.
90+
### Adding to a Collection
9791

98-
- For choosing between a fixed set of values (typically, but not necessarily,
99-
from an enum), a `mapping` delegate can be used:
92+
Options that add to a `Collection` each time they
93+
appear in the arguments are created with using the `adding` delegate. Just like `storing`
94+
delegates, a transform function may optionally be supplied:
10095

101-
```kotlin
102-
val mode by parser.mapping(
103-
"--fast" to Mode.FAST,
104-
"--small" to Mode.SMALL,
105-
"--quiet" to Mode.QUIET,
106-
help = "mode of operation")
107-
```
96+
```kotlin
97+
val includeDirs by parser.adding(
98+
"-I", help = "directory to search for header files") { File(this) }
99+
```
108100

109-
Here the `mode` property will be set to the corresponding `Mode` value depending
110-
on which of `--fast`, `--small`, and `--quiet` appears (last) in the arguments.
101+
Now each time the `-I` option appears, its argument is appended to
102+
`includeDirs`.
111103

112-
`mapping` is one of the few cases where it is not possible to infer the option
113-
name from the property name.
104+
### Mapping from an option to a fixed value
114105

115-
## Modifying Delegates
106+
For choosing between a fixed set of values (typically, but not necessarily,
107+
from an enum), a `mapping` delegate can be used:
116108

117-
The delegates returned by any of these methods also have a few methods for setting
118-
optional attributes:
109+
```kotlin
110+
val mode by parser.mapping(
111+
"--fast" to Mode.FAST,
112+
"--small" to Mode.SMALL,
113+
"--quiet" to Mode.QUIET,
114+
help = "mode of operation")
115+
```
119116

120-
- Some types of options (notably `storing` and `mapping`) have no
121-
default value, and hence will be required options unless a default
122-
value is provided. This is done with the `default` method:
117+
Here the `mode` property will be set to the corresponding `Mode` value depending
118+
on which of `--fast`, `--small`, and `--quiet` appears (last) in the arguments.
123119

124-
```kotlin
125-
val name by parser.storing("-N", "--name", help="...")
126-
.default("John Doe")
127-
```
120+
`mapping` is one of the few cases where it is not possible to infer the option
121+
name from the property name.
128122

129-
- Sometimes it's easier to validate an option at the end pf parsing, in which
130-
case the `addValidator` method can be used.
123+
### More advanced options
131124

132-
```kotlin
133-
val percentages by parser.adding("--percentages", help="...") { toInt() }
134-
.addValidator {
135-
if (sum() != 100)
136-
throw InvalidArgumentException(
137-
"Percentages must add up to 100%")
125+
For all other types of options, the `option` method should be used. The
126+
methods mentioned above are, in fact, convenience methods built on top of the
127+
`option` method.
128+
129+
For example, it is possible to create an option that has multiple arguments:
130+
131+
fun ArgParser.putting(vararg names: String, help: String) =
132+
option<MutableMap<String, String>>(*names,
133+
argNames = listOf("KEY", "VALUE"),
134+
help = help) {
135+
value.orElse { mutableMapOf<String, String>() }.apply {
136+
put(arguments.first(), arguments.last()) }
138137
}
139-
```
138+
139+
Note that the `option` method does not have an auto-naming overload. If you
140+
need this capability, create a `DelegateProvider` that creates your `Delegate`:
141+
142+
fun ArgParser.putting(help: String) =
143+
ArgParser.DelegateProvider { identifier ->
144+
putting(identifierToOptionName(identifier), help = help) }
140145

141146

142147
## Positional Arguments
@@ -176,6 +181,40 @@ val sources by parser.positionalList("SOURCE", 1..Int.MAX_VALUE,
176181
```
177182

178183

184+
## Modifying Delegates
185+
186+
The delegates returned by any of these methods also have a few methods for setting
187+
optional attributes:
188+
189+
- Some types of delegates (notably `storing`, `mapping`, and `positional`) have no
190+
default value, and hence will be required options unless a default
191+
value is provided. This is done with the `default` method:
192+
193+
```kotlin
194+
val name by parser.storing("-N", "--name", help="...").default("John Doe")
195+
```
196+
197+
Note that it *is* possible to use `null` for the default:
198+
199+
```kotlin
200+
val name by parser.storing("-N", "--name", help="...").default(null)
201+
```
202+
203+
The resulting value will be nullable (a `String?` in this case).
204+
205+
- Sometimes it's easier to validate an option at the end pf parsing, in which
206+
case the `addValidator` method can be used.
207+
208+
```kotlin
209+
val percentages by parser.adding("--percentages", help="...") { toInt() }
210+
.addValidator {
211+
if (sum() != 100)
212+
throw InvalidArgumentException(
213+
"Percentages must add up to 100%")
214+
}
215+
```
216+
217+
179218
## Error Handling
180219

181220
Exceptions caused by user error will all derive from `SystemExitException`, and
@@ -265,9 +304,9 @@ my_program --foo ARGUMENT
265304

266305
### Multi-argument Options
267306

268-
Multi-argument options are supported, though not by any of the convenience
269-
methods. Option-arguments after the first must be separate command-line
270-
arguments, for both an long and short forms of an option.
307+
Multi-argument options are supported, though currently not by any of the
308+
convenience methods. Option-arguments after the first must be separate
309+
command-line arguments, for both an long and short forms of an option.
271310

272311
### Positional Arguments
273312

@@ -313,11 +352,56 @@ And equally easy to create a program that behaves like `cp`:
313352
```
314353

315354

316-
<!--
317355
## Help Formatting
318356

319-
TODO: write an explanation of help formatting
320-
-->
357+
By default, `ArgParser` will add a `--help` option (short name `-h`) for
358+
displaying usage information. If this option is present the program will halt
359+
and print a help message like the one below, based on the `ArgParser`
360+
configuration:
361+
362+
usage: program_name [-h] [-n] [-I INCLUDE]... -o OUTPUT
363+
[-v]... SOURCE... DEST
364+
365+
366+
This is the prologue. Lorem ipsum dolor sit amet, consectetur
367+
adipiscing elit. Aliquam malesuada maximus eros. Fusce
368+
luctus risus eget quam consectetur, eu auctor est
369+
ullamcorper. Maecenas eget suscipit dui, sed sodales erat.
370+
Phasellus.
371+
372+
373+
required arguments:
374+
-o OUTPUT, directory in which all output should
375+
--output OUTPUT be generated
376+
377+
378+
optional arguments:
379+
-h, --help show this help message and exit
380+
381+
-n, --dry-run don't do anything
382+
383+
-I INCLUDE, search in this directory for header
384+
--include INCLUDE files
385+
386+
-v, --verbose increase verbosity
387+
388+
389+
positional arguments:
390+
SOURCE source file
391+
392+
DEST destination file
393+
394+
395+
This is the epilogue. Lorem ipsum dolor sit amet,
396+
consectetur adipiscing elit. Donec vel tortor nunc. Sed eu
397+
massa sed turpis auctor faucibus. Donec vel pellentesque
398+
tortor. Ut ultrices tempus lectus fermentum vestibulum.
399+
Phasellus.
400+
401+
The creation of the `--help` option can be disabled by passing `null` as the
402+
`helpFormatter` when constructing the `ArgParser`, or configured by manually
403+
constructing a `HelpFormatter` instance. In the above example a
404+
`DefaultHelpFormatter` was created with the prologue and epilogue.
321405

322406

323407
## Caveats
@@ -331,11 +415,33 @@ TODO: write an explanation of help formatting
331415
parsed. This means it's important that you don't attempt to create delegates
332416
on an `ArgParser` after any of its existing delegated properties have been
333417
read. Attempting to do so will cause an `IllegalStateException`. It would be
334-
nice if Kotlin has facilities for doing some of the work of `ArgParser` at
418+
nice if Kotlin had facilities for doing some of the work of `ArgParser` at
335419
compile time rather than run time, but so far the run time errors seem to be
336420
reasonably easy to avoid.
337421

338422

423+
## Configuring your Build
424+
425+
Kotlin-argparser binaries are hosted on Bintray's center. In Gradle, use
426+
something like this in your `build.gradle`:
427+
428+
buildscript {
429+
repositories {
430+
jcenter()
431+
}
432+
}
433+
434+
dependencies {
435+
compile "com.xenomachina:kotlin-argparser:$kotlin_argparser_version"
436+
}
437+
438+
More information on setting up your Gradle, Maven, or Ivy
439+
dependencies can be found under the "Maven build settings" heading on
440+
[Kotlin-argparser's Bintray
441+
page](https://bintray.com/xenomachina/maven/kotlin-argparser/_latestVersion),
442+
as well as the version of the latest release.
443+
444+
339445
## Credits
340446

341447
This library was created by [Laurence Gonsalves](http://laurence.gonsalv.es).

0 commit comments

Comments
 (0)