Merge remote-tracking branch 'upstream/master'

This commit is contained in:
S.Solodyagin
2025-07-02 20:54:46 +03:00
44 changed files with 1927 additions and 574 deletions
+110 -80
View File
@@ -5,16 +5,16 @@
[![](https://godoc.org/github.com/alecthomas/kong?status.svg)](http://godoc.org/github.com/alecthomas/kong) [![CircleCI](https://img.shields.io/circleci/project/github/alecthomas/kong.svg)](https://circleci.com/gh/alecthomas/kong) [![Go Report Card](https://goreportcard.com/badge/github.com/alecthomas/kong)](https://goreportcard.com/report/github.com/alecthomas/kong) [![Slack chat](https://img.shields.io/static/v1?logo=slack&style=flat&label=slack&color=green&message=gophers)](https://gophers.slack.com/messages/CN9DS8YF3)
<!-- TOC depthfrom:2 depthto:3 -->
- [Version 1.0.0 Release](#version-100-release)
- [Introduction](#introduction)
- [Help](#help)
- [Help as a user of a Kong application](#help-as-a-user-of-a-kong-application)
- [Defining help in Kong](#defining-help-in-kong)
- [Command handling](#command-handling)
- [Switch on the command string](#switch-on-the-command-string)
- [Attach a Run... error method to each command](#attach-a-run-error-method-to-each-command)
- [Hooks: BeforeReset, BeforeResolve, BeforeApply, AfterApply and the Bind option](#hooks-beforereset-beforeresolve-beforeapply-afterapply-and-the-bind-option)
- [Attach a `Run(...) error` method to each command](#attach-a-run-error-method-to-each-command)
- [Hooks: BeforeReset(), BeforeResolve(), BeforeApply(), AfterApply()](#hooks-beforereset-beforeresolve-beforeapply-afterapply)
- [The Bind() option](#the-bind-option)
- [Flags](#flags)
- [Commands and sub-commands](#commands-and-sub-commands)
- [Branching positional arguments](#branching-positional-arguments)
@@ -25,22 +25,26 @@
- [Nested data structure](#nested-data-structure)
- [Custom named decoders](#custom-named-decoders)
- [Supported field types](#supported-field-types)
- [Custom decoders mappers](#custom-decoders-mappers)
- [Custom decoders (mappers)](#custom-decoders-mappers)
- [Supported tags](#supported-tags)
- [Plugins](#plugins)
- [Dynamic Commands](#dynamic-commands)
- [Variable interpolation](#variable-interpolation)
- [Validation](#validation)
- [Modifying Kong's behaviour](#modifying-kongs-behaviour)
- [Namehelp and Descriptionhelp - set the application name description](#namehelp-and-descriptionhelp---set-the-application-name-description)
- [Configurationloader, paths... - load defaults from configuration files](#configurationloader-paths---load-defaults-from-configuration-files)
- [Resolver... - support for default values from external sources](#resolver---support-for-default-values-from-external-sources)
- [\*Mapper... - customising how the command-line is mapped to Go values](#mapper---customising-how-the-command-line-is-mapped-to-go-values)
- [ConfigureHelpHelpOptions and HelpHelpFunc - customising help](#configurehelphelpoptions-and-helphelpfunc---customising-help)
- [Bind... - bind values for callback hooks and Run methods](#bind---bind-values-for-callback-hooks-and-run-methods)
- [`Name(help)` and `Description(help)` - set the application name description](#namehelp-and-descriptionhelp---set-the-application-name-description)
- [`Configuration(loader, paths...)` - load defaults from configuration files](#configurationloader-paths---load-defaults-from-configuration-files)
- [`Resolver(...)` - support for default values from external sources](#resolver---support-for-default-values-from-external-sources)
- [`*Mapper(...)` - customising how the command-line is mapped to Go values](#mapper---customising-how-the-command-line-is-mapped-to-go-values)
- [`ConfigureHelp(HelpOptions)` and `Help(HelpFunc)` - customising help](#configurehelphelpoptions-and-helphelpfunc---customising-help)
- [Injecting values into `Run()` methods](#injecting-values-into-run-methods)
- [Other options](#other-options)
<!-- /TOC -->
## Version 1.0.0 Release
Kong has been stable for a long time, so it seemed appropriate to cut a 1.0 release.
There is one breaking change, [#436](https://github.com/alecthomas/kong/pull/436), which should effect relatively few users.
## Introduction
@@ -177,7 +181,7 @@ Flags:
#### Showing an _argument_'s detailed help
Custom help will only be shown for _positional arguments with named fields_ ([see the README section on positional arguments for more details on what that means](../../../README.md#branching-positional-arguments))
Custom help will only be shown for _positional arguments with named fields_ ([see the README section on positional arguments for more details on what that means](#branching-positional-arguments))
**Contextual argument help**
@@ -302,17 +306,21 @@ func main() {
```
## Hooks: BeforeReset(), BeforeResolve(), BeforeApply(), AfterApply() and the Bind() option
## Hooks: BeforeReset(), BeforeResolve(), BeforeApply(), AfterApply()
If a node in the grammar has a `BeforeReset(...)`, `BeforeResolve
(...)`, `BeforeApply(...) error` and/or `AfterApply(...) error` method, those
methods will be called before values are reset, before validation/assignment,
and after validation/assignment, respectively.
If a node in the CLI, or any of its embedded fields, implements a `BeforeReset(...) error`, `BeforeResolve
(...) error`, `BeforeApply(...) error` and/or `AfterApply(...) error` method, those will be called as Kong
resets, resolves, validates, and assigns values to the node.
| Hook | Description |
| --------------- | ----------------------------------------------------------------------------------------------- |
| `BeforeReset` | Invoked before values are reset to their defaults (as defined by the grammar) or to zero values |
| `BeforeResolve` | Invoked before resolvers are applied to a node |
| `BeforeApply` | Invoked before the traced command line arguments are applied to the grammar |
| `AfterApply` | Invoked after command line arguments are applied to the grammar **and validated**` |
The `--help` flag is implemented with a `BeforeReset` hook.
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.
```go
@@ -338,38 +346,42 @@ func main() {
}
```
Another example of using hooks is load the env-file:
It's also possible to register these hooks with the functional options
`kong.WithBeforeReset`, `kong.WithBeforeResolve`, `kong.WithBeforeApply`, and
`kong.WithAfterApply`.
## The Bind() option
Arguments to hooks are provided via the `Run(...)` method or `Bind(...)` option. `*Kong`, `*Context`, `*Path` and parent commands are also bound and finally, hooks can also contribute bindings via `kong.Context.Bind()` and `kong.Context.BindTo()`.
eg:
```go
package main
type CLI struct {
Debug bool `help:"Enable debug mode."`
import (
"fmt"
"git.company.lan/gopkg/kong"
"github.com/joho/godotenv"
)
Rm RmCmd `cmd:"" help:"Remove files."`
Ls LsCmd `cmd:"" help:"List paths."`
}
type EnvFlag string
type AuthorName string
// BeforeResolve loads env file.
func (c EnvFlag) BeforeReset(ctx *kong.Context, trace *kong.Path) error {
path := string(ctx.FlagValue(trace.Flag).(EnvFlag)) // nolint
path = kong.ExpandPath(path)
if err := godotenv.Load(path); err != nil {
return err
}
// ...
func (l *LsCmd) Run(cli *CLI) error {
// use cli.Debug here !!
return nil
}
var CLI struct {
EnvFile EnvFlag
Flag `env:"FLAG"`
func (r *RmCmD) Run(author AuthorName) error{
// use binded author here
return nil
}
func main() {
_ = kong.Parse(&CLI)
fmt.Println(CLI.Flag)
}
var cli CLI
ctx := kong.Parse(&cli, Bind(AuthorName("penguin")))
err := ctx.Run()
```
## Flags
@@ -553,36 +565,44 @@ Tags can be in two forms:
Both can coexist with standard Tag parsing.
| Tag | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `cmd:""` | If present, struct is a command. |
| `arg:""` | If present, field is an argument. Required by default. |
| `env:"X,Y,..."` | Specify envars to use for default value. The envs are resolved in the declared order. The first value found is used. |
| `name:"X"` | Long name, for overriding field name. |
| `help:"X"` | Help text. |
| `type:"X"` | Specify [named types](#custom-named-decoders) to use. |
| `placeholder:"X"` | Placeholder text. |
| `default:"X"` | Default value. |
| `default:"1"` | On a command, make it the default. |
| `default:"withargs"` | On a command, make it the default and allow args/flags from that command |
| `short:"X"` | Short name, if flag. |
| `aliases:"X,Y"` | One or more aliases (for cmd or flag). |
| `required:""` | If present, flag/arg is required. |
| `optional:""` | If present, flag/arg is optional. |
| `hidden:""` | If present, command or flag is hidden. |
| `negatable:""` | If present on a `bool` field, supports prefixing a flag with `--no-` to invert the default value |
| `format:"X"` | Format for parsing input, if supported. |
| `sep:"X"` | Separator for sequences (defaults to ","). May be `none` to disable splitting. |
| `mapsep:"X"` | Separator for maps (defaults to ";"). May be `none` to disable splitting. |
| `enum:"X,Y,..."` | Set of valid values allowed for this flag. An enum field must be `required` or have a valid `default`. |
| `group:"X"` | Logical group for a flag or command. |
| `xor:"X,Y,..."` | Exclusive OR groups for flags. Only one flag in the group can be used which is restricted within the same command. When combined with `required`, at least one of the `xor` group will be required. |
| `prefix:"X"` | Prefix for all sub-flags. |
| `envprefix:"X"` | Envar prefix for all sub-flags. |
| `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. |
| `passthrough:""` | If present on a positional argument, it stops flag parsing when encountered, as if `--` was processed before. Useful for external command wrappers, like `exec`. On a command it requires that the command contains only one argument of type `[]string` which is then filled with everything following the command, unparsed. |
| `-` | Ignore the field. Useful for adding non-CLI fields to a configuration struct. e.g `` `kong:"-"` `` |
| Tag | Description |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `cmd:""` | If present, struct is a command. |
| `arg:""` | If present, field is an argument. Required by default. |
| `env:"X,Y,..."` | Specify envars to use for default value. The envs are resolved in the declared order. The first value found is used. |
| `name:"X"` | Long name, for overriding field name. |
| `help:"X"` | Help text. |
| `type:"X"` | Specify [named types](#custom-named-decoders) to use. |
| `placeholder:"X"` | Placeholder input, if flag. e.g. `` `placeholder:"<the-placeholder>"` `` will show `--flag-name=<the-placeholder>` when displaying help. |
| `default:"X"` | Default value. |
| `default:"1"` | On a command, make it the default. |
| `default:"withargs"` | On a command, make it the default and allow args/flags from that command |
| `short:"X"` | Short name, if flag. |
| `aliases:"X,Y"` | One or more aliases (for cmd or flag). |
| `required:""` | If present, flag/arg is required. |
| `optional:""` | If present, flag/arg is optional. |
| `hidden:""` | If present, command or flag is hidden. |
| `negatable:""` | If present on a `bool` field, supports prefixing a flag with `--no-` to invert the default value |
| `negatable:"X"` | If present on a `bool` field, supports `--X` to invert the default value |
| `format:"X"` | Format for parsing input, if supported. |
| `sep:"X"` | Separator for sequences (defaults to ","). May be `none` to disable splitting. |
| `mapsep:"X"` | Separator for maps (defaults to ";"). May be `none` to disable splitting. |
| `enum:"X,Y,..."` | Set of valid values allowed for this flag. An enum field must be `required` or have a valid `default`. |
| `group:"X"` | Logical group for a flag or command. |
| `xor:"X,Y,..."` | Exclusive OR groups for flags. Only one flag in the group can be used which is restricted within the same command. When combined with `required`, at least one of the `xor` group will be required. |
| `and:"X,Y,..."` | AND groups for flags. All flags in the group must be used in the same command. When combined with `required`, all flags in the group will be required. |
| `prefix:"X"` | Prefix for all sub-flags. |
| `envprefix:"X"` | Envar prefix for all sub-flags. |
| `xorprefix:"X"` | Prefix for all sub-flags in XOR/AND groups. |
| `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. |
| `passthrough:"<mode>"`[^1] | If present on a positional argument, it stops flag parsing when encountered, as if `--` was processed before. Useful for external command wrappers, like `exec`. On a command it requires that the command contains only one argument of type `[]string` which is then filled with everything following the command, unparsed. |
| `-` | Ignore the field. Useful for adding non-CLI fields to a configuration struct. e.g `` `kong:"-"` `` |
[^1]:
`<mode>` can be `partial` or `all` (the default). `all` will pass through all arguments including flags, including
flags. `partial` will validate flags until the first positional argument is encountered, then pass through all remaining
positional arguments.
## Plugins
@@ -611,8 +631,8 @@ also supports dynamically adding commands via `kong.DynamicCommand()`.
## Variable interpolation
Kong supports limited variable interpolation into help strings, enum lists and
default values.
Kong supports limited variable interpolation into help strings, placeholder strings,
enum lists and default values.
Variables are in the form:
@@ -654,8 +674,7 @@ func main() {
## Validation
Kong does validation on the structure of a command-line, but also supports
extensible validation. Any node in the tree may implement the following
interface:
extensible validation. Any node in the tree may implement either of the following interfaces:
```go
type Validatable interface {
@@ -663,12 +682,18 @@ type Validatable interface {
}
```
```go
type Validatable interface {
Validate(kctx *kong.Context) error
}
```
If one of these nodes is in the active command-line it will be called during
normal validation.
## Modifying Kong's behaviour
Each Kong parser can be configured via functional options passed to `New(cli interface{}, options...Option)`.
Each Kong parser can be configured via functional options passed to `New(cli any, options...Option)`.
The full set of options can be found [here](https://godoc.org/github.com/alecthomas/kong#Option).
@@ -726,20 +751,25 @@ All builtin Go types (as well as a bunch of useful stdlib types like `time.Time`
1. `NamedMapper(string, Mapper)` and using the tag key `type:"<name>"`.
2. `KindMapper(reflect.Kind, Mapper)`.
3. `TypeMapper(reflect.Type, Mapper)`.
4. `ValueMapper(interface{}, Mapper)`, passing in a pointer to a field of the grammar.
4. `ValueMapper(any, 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.
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.
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 `DefaultHelpPrinter` for an example.
3. Use `ValueFormatter(HelpValueFormatter)` if you want to just customize the help text that is accompanied by flags and arguments.
4. Use `Groups([]Group)` if you want to customize group titles or add a header.
### `Bind(...)` - bind values for callback hooks and Run() methods
### Injecting values into `Run()` methods
See the [section on hooks](#hooks-beforeresolve-beforeapply-afterapply-and-the-bind-option) for details.
There are several ways to inject values into `Run()` methods:
1. Use `Bind()` to bind values directly.
2. Use `BindTo()` to bind values to an interface type.
3. Use `BindToProvider()` to bind values to a function that provides the value.
4. Implement `Provide<Type>() error` methods on the command structure.
### Other options