feat: add support for Provide*() (<type>, error) methods on commands
This commit is contained in:
@@ -5,43 +5,40 @@
|
||||
|
||||
[](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)
|
||||
|
||||
<!-- 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)
|
||||
- [Flags](#flags)
|
||||
- [Commands and sub-commands](#commands-and-sub-commands)
|
||||
- [Branching positional arguments](#branching-positional-arguments)
|
||||
- [Positional arguments](#positional-arguments)
|
||||
- [Slices](#slices)
|
||||
- [Maps](#maps)
|
||||
- [Pointers](#pointers)
|
||||
- [Nested data structure](#nested-data-structure)
|
||||
- [Custom named decoders](#custom-named-decoders)
|
||||
- [Supported field types](#supported-field-types)
|
||||
- [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)
|
||||
- [Other options](#other-options)
|
||||
|
||||
<!-- /TOC -->
|
||||
- [Kong is a command-line parser for Go](#kong-is-a-command-line-parser-for-go)
|
||||
- [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)
|
||||
- [Flags](#flags)
|
||||
- [Commands and sub-commands](#commands-and-sub-commands)
|
||||
- [Branching positional arguments](#branching-positional-arguments)
|
||||
- [Positional arguments](#positional-arguments)
|
||||
- [Slices](#slices)
|
||||
- [Maps](#maps)
|
||||
- [Pointers](#pointers)
|
||||
- [Nested data structure](#nested-data-structure)
|
||||
- [Custom named decoders](#custom-named-decoders)
|
||||
- [Supported field types](#supported-field-types)
|
||||
- [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)
|
||||
- [`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)
|
||||
- [`Bind(...)` - bind values for callback hooks and Run() methods](#bind---bind-values-for-callback-hooks-and-run-methods)
|
||||
- [Other options](#other-options)
|
||||
|
||||
## Version 1.0.0 Release
|
||||
|
||||
@@ -755,9 +752,14 @@ The default help output is usually sufficient, but if not there are two solution
|
||||
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-beforereset-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
|
||||
|
||||
|
||||
+13
@@ -782,6 +782,19 @@ func (c *Context) RunNode(node *Node, binds ...interface{}) (err error) {
|
||||
methodBinds = methodBinds.clone()
|
||||
for p := node; p != nil; p = p.Parent {
|
||||
methodBinds = methodBinds.add(p.Target.Addr().Interface())
|
||||
// Try value and pointer to value.
|
||||
for _, p := range []reflect.Value{p.Target, p.Target.Addr()} {
|
||||
t := p.Type()
|
||||
for i := 0; i < p.NumMethod(); i++ {
|
||||
methodt := t.Method(i)
|
||||
if strings.HasPrefix(methodt.Name, "Provide") {
|
||||
method := p.Method(i)
|
||||
if err := methodBinds.addProvider(method.Interface()); err != nil {
|
||||
return fmt.Errorf("%s.%s: %w", t.Name(), methodt.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if method.IsValid() {
|
||||
methods = append(methods, targetMethod{node, method, methodBinds})
|
||||
|
||||
@@ -2381,3 +2381,28 @@ func TestAfterRun(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, afterRunCLI{runCalled: true, afterRunCalled: true}, cli)
|
||||
}
|
||||
|
||||
type ProvidedString string
|
||||
|
||||
type providerCLI struct {
|
||||
Sub providerSubCommand `cmd:""`
|
||||
}
|
||||
|
||||
type providerSubCommand struct{}
|
||||
|
||||
func (p *providerCLI) ProvideFoo() (ProvidedString, error) {
|
||||
return ProvidedString("foo"), nil
|
||||
}
|
||||
|
||||
func (p *providerSubCommand) Run(t *testing.T, ps ProvidedString) error {
|
||||
assert.Equal(t, ProvidedString("foo"), ps)
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestProviderMethods(t *testing.T) {
|
||||
k := mustNew(t, &providerCLI{})
|
||||
kctx, err := k.Parse([]string{"sub"})
|
||||
assert.NoError(t, err)
|
||||
err = kctx.Run(t)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user