Convert Hook to an Option.
This commit is contained in:
committed by
Gerald Kaszuba
parent
cf89213e1e
commit
afbb431641
@@ -18,7 +18,7 @@ usage: {{.Name}}
|
||||
var defaultHelpTemplate = template.Must(template.New("help").Parse(defaultHelp))
|
||||
|
||||
// Help returns a Hook that will display help and exit.
|
||||
func Help(tmpl *template.Template, tmplctx map[string]interface{}) Hook {
|
||||
func Help(tmpl *template.Template, tmplctx map[string]interface{}) HookFunction {
|
||||
return func(app *Kong, ctx *Context, trace *Trace) error {
|
||||
merged := map[string]interface{}{
|
||||
"Application": app.Model,
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type Hook func(app *Kong, ctx *Context, trace *Trace) error
|
||||
type HookFunction func(app *Kong, ctx *Context, trace *Trace) error
|
||||
|
||||
// Error reported by Kong.
|
||||
type Error struct{ msg string }
|
||||
@@ -37,10 +37,11 @@ type Kong struct {
|
||||
Stdout io.Writer
|
||||
Stderr io.Writer
|
||||
|
||||
help *template.Template
|
||||
helpContext map[string]interface{}
|
||||
helpFuncs template.FuncMap
|
||||
hooks map[reflect.Value]Hook
|
||||
help *template.Template
|
||||
helpContext map[string]interface{}
|
||||
helpFuncs template.FuncMap
|
||||
hooks map[reflect.Value]HookFunction
|
||||
noDefaultHelp bool
|
||||
}
|
||||
|
||||
// New creates a new Kong parser into ast.
|
||||
@@ -52,7 +53,7 @@ func New(ast interface{}, options ...Option) (*Kong, error) {
|
||||
help: defaultHelpTemplate,
|
||||
helpContext: map[string]interface{}{},
|
||||
helpFuncs: template.FuncMap{},
|
||||
hooks: map[reflect.Value]Hook{},
|
||||
hooks: map[reflect.Value]HookFunction{},
|
||||
}
|
||||
|
||||
model, err := build(ast)
|
||||
@@ -66,9 +67,28 @@ func New(ast interface{}, options ...Option) (*Kong, error) {
|
||||
option(k)
|
||||
}
|
||||
|
||||
if !k.noDefaultHelp {
|
||||
k.integrateHelp()
|
||||
}
|
||||
|
||||
return k, nil
|
||||
}
|
||||
|
||||
func (k *Kong) integrateHelp() {
|
||||
helpValue := false
|
||||
help := &Flag{
|
||||
Value: Value{
|
||||
Name: "help",
|
||||
Help: "Show context-sensitive help.",
|
||||
Flag: true,
|
||||
Value: reflect.ValueOf(&helpValue).Elem(),
|
||||
Decoder: kindDecoders[reflect.Bool],
|
||||
},
|
||||
}
|
||||
k.Model.Flags = append([]*Flag{help}, k.Model.Flags...)
|
||||
Hook(&helpValue, Help(defaultHelpTemplate, nil))(k)
|
||||
}
|
||||
|
||||
// Trace parses the command-line, validating and collecting matching grammar nodes.
|
||||
func (k *Kong) Trace(args []string) (*Context, error) {
|
||||
p := &Context{
|
||||
@@ -89,12 +109,6 @@ func (k *Kong) Trace(args []string) (*Context, error) {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// Hook to execute when a command is encountered.
|
||||
func (k *Kong) Hook(ptr interface{}, hook Hook) *Kong {
|
||||
k.hooks[reflect.ValueOf(ptr)] = hook
|
||||
return k
|
||||
}
|
||||
|
||||
// Parse arguments into target.
|
||||
//
|
||||
// The returned "command" is a space separated path to the final selected command, if any. Commands appear as
|
||||
|
||||
+10
-15
@@ -7,11 +7,12 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func mustNew(t *testing.T, cli interface{}) *Kong {
|
||||
func mustNew(t *testing.T, cli interface{}, options ...Option) *Kong {
|
||||
t.Helper()
|
||||
parser, err := New(cli, ExitFunction(func(int) {
|
||||
options = append(options, ExitFunction(func(int) {
|
||||
t.Fatalf("unexpected exit()")
|
||||
}))
|
||||
parser, err := New(cli, options...)
|
||||
require.NoError(t, err)
|
||||
return parser
|
||||
}
|
||||
@@ -381,19 +382,13 @@ func TestHooks(t *testing.T) {
|
||||
{"Flag", "one --three=three", values{true, "", "three"}},
|
||||
{"ArgAndFlag", "one two --three=three", values{true, "two", "three"}},
|
||||
}
|
||||
p := mustNew(t, &cli).
|
||||
Hook(&cli.One, func(app *Kong, ctx *Context, trace *Trace) error {
|
||||
hooked.one = true
|
||||
return nil
|
||||
}).
|
||||
Hook(&cli.One.Two, func(app *Kong, ctx *Context, trace *Trace) error {
|
||||
hooked.two = trace.Value.String()
|
||||
return nil
|
||||
}).
|
||||
Hook(&cli.One.Three, func(app *Kong, ctx *Context, trace *Trace) error {
|
||||
hooked.three = trace.Value.String()
|
||||
return nil
|
||||
})
|
||||
setOne := func(app *Kong, ctx *Context, trace *Trace) error { hooked.one = true; return nil }
|
||||
setTwo := func(app *Kong, ctx *Context, trace *Trace) error { hooked.two = trace.Value.String(); return nil }
|
||||
setThree := func(app *Kong, ctx *Context, trace *Trace) error { hooked.three = trace.Value.String(); return nil }
|
||||
p := mustNew(t, &cli,
|
||||
Hook(&cli.One, setOne),
|
||||
Hook(&cli.One.Two, setTwo),
|
||||
Hook(&cli.One.Three, setThree))
|
||||
|
||||
for _, test := range tests {
|
||||
hooked = values{}
|
||||
|
||||
+19
@@ -2,6 +2,7 @@ package kong
|
||||
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
@@ -12,6 +13,13 @@ func ExitFunction(exit func(int)) Option {
|
||||
return func(k *Kong) { k.Exit = exit }
|
||||
}
|
||||
|
||||
// NoDefaultHelp disables the default help flags.
|
||||
func NoDefaultHelp() Option {
|
||||
return func(k *Kong) {
|
||||
k.noDefaultHelp = true
|
||||
}
|
||||
}
|
||||
|
||||
// Name overrides the application name.
|
||||
func Name(name string) Option {
|
||||
return func(k *Kong) { k.Model.Name = name }
|
||||
@@ -41,3 +49,14 @@ func Writers(stdout, stderr io.Writer) Option {
|
||||
k.Stderr = stderr
|
||||
}
|
||||
}
|
||||
|
||||
// Hook to execute when a command, flag or positional argument is encountered.
|
||||
func Hook(ptr interface{}, hook HookFunction) Option {
|
||||
key := reflect.ValueOf(ptr)
|
||||
if key.Kind() != reflect.Ptr {
|
||||
panic("expected a pointer")
|
||||
}
|
||||
return func(k *Kong) {
|
||||
k.hooks[key] = hook
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user