diff --git a/.golangci.yml b/.golangci.yml
index 48925a8..bffbfc7 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -13,6 +13,7 @@ linters:
- wsl
- funlen
- gocognit
+ - gomnd
linters-settings:
govet:
diff --git a/README.md b/README.md
index a969f61..9439acb 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,15 @@

-# Kong is a command-line parser for Go [](http://godoc.org/github.com/alecthomas/kong) [](https://circleci.com/gh/alecthomas/kong)
+# Kong is a command-line parser for Go [](http://godoc.org/github.com/alecthomas/kong) [](https://circleci.com/gh/alecthomas/kong) [](https://goreportcard.com/report/github.com/alecthomas/kong) [](https://gophers.slack.com/messages/CN9DS8YF3)
1. [Introduction](#introduction)
2. [Help](#help)
3. [Command handling](#command-handling)
- 1. [Switch on the command string](#switch-on-the-command-string)
- 2. [Attach a `Run(...) error` method to each command](#attach-a-run-error-method-to-each-command)
+ 1. [1. Switch on the command string](#1-switch-on-the-command-string)
+ 2. [2. Attach a `Run(...) error` method to each command](#2-attach-a-run-error-method-to-each-command)
4. [Hooks: BeforeResolve(), BeforeApply(), AfterApply() and the Bind() option](#hooks-beforeresolve-beforeapply-afterapply-and-the-bind-option)
5. [Flags](#flags)
6. [Commands and sub-commands](#commands-and-sub-commands)
@@ -32,6 +32,7 @@
+
## Introduction
Kong aims to support arbitrarily complex command-line structures with as little developer effort as possible.
@@ -74,6 +75,7 @@ func main() {
}
```
+
## Help
Help is automatically generated. With no other arguments provided, help will display a full summary of all available commands.
@@ -114,11 +116,13 @@ eg.
-f, --force Force removal.
-r, --recursive Recursively remove files.
+
## Command handling
There are two ways to handle commands in Kong.
-### Switch on the command string
+
+### 1. Switch on the command string
When you call `kong.Parse()` it will return a unique string representation of the command. Each command branch in the hierarchy will be a bare word and each branching argument or required positional argument will be the name surrounded by angle brackets. Here's an example:
@@ -157,7 +161,8 @@ func main() {
This has the advantage that it is convenient, but the downside that if you modify your CLI structure, the strings may change. This can be fragile.
-### Attach a `Run(...) error` method to each command
+
+### 2. Attach a `Run(...) error` method to each command
A more robust approach is to break each command out into their own structs:
@@ -181,6 +186,10 @@ There's a full example emulating part of the Docker CLI [here](https://github.co
eg.
```go
+type Context struct {
+ Debug bool
+}
+
type RmCmd struct {
Force bool `help:"Force removal."`
Recursive bool `help:"Recursively remove files."`
@@ -188,7 +197,7 @@ type RmCmd struct {
Paths []string `arg name:"path" help:"Paths to remove." type:"path"`
}
-func (r *RmCmd) Run(debug bool) error {
+func (r *RmCmd) Run(ctx *Context) error {
fmt.Println("rm", r.Paths)
return nil
}
@@ -197,7 +206,7 @@ type LsCmd struct {
Paths []string `arg optional name:"path" help:"Paths to list." type:"path"`
}
-func (l *LsCmd) Run(debug bool) error {
+func (l *LsCmd) Run(ctx *Context) error {
fmt.Println("ls", l.Paths)
return nil
}
@@ -212,19 +221,20 @@ var cli struct {
func main() {
ctx := kong.Parse(&cli)
// Call the Run() method of the selected parsed command.
- err = ctx.Run(cli.Debug)
+ err = ctx.Run(&Context{Debug: cli.Debug})
ctx.FatalIfErrorf(err)
}
```
+
## Hooks: BeforeResolve(), BeforeApply(), AfterApply() and the Bind() option
If a node in the grammar has a `BeforeResolve(...)`, `BeforeApply(...) error` and/or `AfterApply(...) error` method, those methods will be called before validation/assignment and after validation/assignment, respectively.
The `--help` flag is implemented with a `BeforeApply` hook.
-Arguments to hooks are provided via the `Bind(...)` option. `*Kong`, `*Context` and `*Path` are also bound and finally, hooks can also contribute bindings via `kong.Context.Bind()` and `kong.Context.BindTo()`.
+Arguments to hooks are provided via the `Run(...)` method or `Bind(...)` option. `*Kong`, `*Context` and `*Path` are also bound and finally, hooks can also contribute bindings via `kong.Context.Bind()` and `kong.Context.BindTo()`.
eg.
@@ -251,6 +261,7 @@ func main() {
}
```
+
## Flags
Any [mapped](#mapper---customising-how-the-command-line-is-mapped-to-go-values) field in the command structure *not* tagged with `cmd` or `arg` will be a flag. Flags are optional by default.
@@ -263,6 +274,7 @@ type CLI struct {
}
```
+
## Commands and sub-commands
Sub-commands are specified by tagging a struct field with `cmd`. Kong supports arbitrarily nested commands.
@@ -280,6 +292,7 @@ type CLI struct {
}
```
+
## Branching positional arguments
In addition to sub-commands, structs can also be configured as branching positional arguments.
@@ -307,12 +320,14 @@ var CLI struct {
This looks a little verbose in this contrived example, but typically this will not be the case.
+
## Terminating positional arguments
If a [mapped type](#mapper---customising-how-the-command-line-is-mapped-to-go-values) is tagged with `arg` it will be treated as the final positional values to be parsed on the command line.
If a positional argument is a slice, all remaining arguments will be appended to that slice.
+
## Slices
Slice values are treated specially. First the input is split on the `sep:""` tag (defaults to `,`), then each element is parsed by the slice element type and appended to the slice. If the same value is encountered multiple times, elements continue to be appended.
@@ -331,6 +346,7 @@ var CLI struct {
}
```
+
## Maps
Maps are similar to slices except that only one key/value pair can be assigned per value, and the `sep` tag denotes the assignment character and defaults to `=`.
@@ -353,6 +369,7 @@ var CLI struct {
For flags, multiple key+value pairs should be separated by `;` eg. `--set="key1=value1;key2=value2"`.
+
## Custom named decoders
Kong includes a number of builtin custom type mappers. These can be used by
@@ -371,11 +388,13 @@ specifies the element type. For maps, the tag has the format
`tag:"[]:[]"` where either may be omitted.
+
## Custom decoders (mappers)
If a field implements the [MapperValue](https://godoc.org/github.com/alecthomas/kong#MapperValue)
interface it will be used to decode arguments into the field.
+
## Supported tags
Tags can be in two forms:
@@ -408,6 +427,7 @@ Tag | Description
`set:"K=V"` | Set a variable for expansion by child elements. Multiples can occur.
`embed` | If present, this field's children will be embedded in the parent. Useful for composition.
+
## Variable interpolation
Kong supports limited variable interpolation into help strings, enum lists and
@@ -419,7 +439,7 @@ Variables are in the form:
${=}
Variables are set with the `Vars{"key": "value", ...}` option. Undefined
-variable references in the grammar without a default will result in an error at
+variable references in the grammar without a default will result in an error at
construction time.
Variables can also be set via the `set:"K=V"` tag. In this case, those variables will be available for that
@@ -446,12 +466,14 @@ func main() {
}
```
+
## Modifying Kong's behaviour
Each Kong parser can be configured via functional options passed to `New(cli interface{}, options...Option)`.
The full set of options can be found [here](https://godoc.org/github.com/alecthomas/kong#Option).
+
### `Name(help)` and `Description(help)` - set the application name description
Set the application name and/or description.
@@ -460,6 +482,7 @@ The name of the application will default to the binary name, but can be overridd
As with all help in Kong, text will be wrapped to the terminal.
+
### `Configuration(loader, paths...)` - load defaults from configuration files
This option provides Kong with support for loading defaults from a set of configuration files. Each file is opened, if possible, and the loader called to create a resolver for that file.
@@ -472,12 +495,14 @@ kong.Parse(&cli, kong.Configuration(kong.JSON, "/etc/myapp.json", "~/.myapp.json
[See the tests](https://github.com/alecthomas/kong/blob/master/resolver_test.go#L103) for an example of how the JSON file is structured.
+
### `Resolver(...)` - support for default values from external sources
Resolvers are Kong's extension point for providing default values from external sources. As an example, support for environment variables via the `env` tag is provided by a resolver. There's also a builtin resolver for JSON configuration files.
Example resolvers can be found in [resolver.go](https://github.com/alecthomas/kong/blob/master/resolver.go).
+
### `*Mapper(...)` - customising how the command-line is mapped to Go values
Command-line arguments are mapped to Go values via the Mapper interface:
@@ -500,6 +525,7 @@ All builtin Go types (as well as a bunch of useful stdlib types like `time.Time`
3. `TypeMapper(reflect.Type, Mapper)`.
4. `ValueMapper(interface{}, Mapper)`, passing in a pointer to a field of the grammar.
+
### `ConfigureHelp(HelpOptions)` and `Help(HelpFunc)` - customising help
The default help output is usually sufficient, but if not there are two solutions.
@@ -507,10 +533,12 @@ The default help output is usually sufficient, but if not there are two solution
1. Use `ConfigureHelp(HelpOptions)` to configure how help is formatted (see [HelpOptions](https://godoc.org/github.com/alecthomas/kong#HelpOptions) for details).
2. Custom help can be wired into Kong via the `Help(HelpFunc)` option. The `HelpFunc` is passed a `Context`, which contains the parsed context for the current command-line. See the implementation of `PrintHelp` for an example.
+
### `Bind(...)` - bind values for callback hooks and Run() methods
See the [section on hooks](#BeforeApply-AfterApply-and-the-bind-option) for details.
+
### Other options
The full set of options can be found [here](https://godoc.org/github.com/alecthomas/kong#Option).