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))
|
var defaultHelpTemplate = template.Must(template.New("help").Parse(defaultHelp))
|
||||||
|
|
||||||
// Help returns a Hook that will display help and exit.
|
// 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 {
|
return func(app *Kong, ctx *Context, trace *Trace) error {
|
||||||
merged := map[string]interface{}{
|
merged := map[string]interface{}{
|
||||||
"Application": app.Model,
|
"Application": app.Model,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"text/template"
|
"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.
|
// Error reported by Kong.
|
||||||
type Error struct{ msg string }
|
type Error struct{ msg string }
|
||||||
@@ -37,10 +37,11 @@ type Kong struct {
|
|||||||
Stdout io.Writer
|
Stdout io.Writer
|
||||||
Stderr io.Writer
|
Stderr io.Writer
|
||||||
|
|
||||||
help *template.Template
|
help *template.Template
|
||||||
helpContext map[string]interface{}
|
helpContext map[string]interface{}
|
||||||
helpFuncs template.FuncMap
|
helpFuncs template.FuncMap
|
||||||
hooks map[reflect.Value]Hook
|
hooks map[reflect.Value]HookFunction
|
||||||
|
noDefaultHelp bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Kong parser into ast.
|
// New creates a new Kong parser into ast.
|
||||||
@@ -52,7 +53,7 @@ func New(ast interface{}, options ...Option) (*Kong, error) {
|
|||||||
help: defaultHelpTemplate,
|
help: defaultHelpTemplate,
|
||||||
helpContext: map[string]interface{}{},
|
helpContext: map[string]interface{}{},
|
||||||
helpFuncs: template.FuncMap{},
|
helpFuncs: template.FuncMap{},
|
||||||
hooks: map[reflect.Value]Hook{},
|
hooks: map[reflect.Value]HookFunction{},
|
||||||
}
|
}
|
||||||
|
|
||||||
model, err := build(ast)
|
model, err := build(ast)
|
||||||
@@ -66,9 +67,28 @@ func New(ast interface{}, options ...Option) (*Kong, error) {
|
|||||||
option(k)
|
option(k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !k.noDefaultHelp {
|
||||||
|
k.integrateHelp()
|
||||||
|
}
|
||||||
|
|
||||||
return k, nil
|
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.
|
// Trace parses the command-line, validating and collecting matching grammar nodes.
|
||||||
func (k *Kong) Trace(args []string) (*Context, error) {
|
func (k *Kong) Trace(args []string) (*Context, error) {
|
||||||
p := &Context{
|
p := &Context{
|
||||||
@@ -89,12 +109,6 @@ func (k *Kong) Trace(args []string) (*Context, error) {
|
|||||||
return p, nil
|
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.
|
// Parse arguments into target.
|
||||||
//
|
//
|
||||||
// The returned "command" is a space separated path to the final selected command, if any. Commands appear as
|
// 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"
|
"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()
|
t.Helper()
|
||||||
parser, err := New(cli, ExitFunction(func(int) {
|
options = append(options, ExitFunction(func(int) {
|
||||||
t.Fatalf("unexpected exit()")
|
t.Fatalf("unexpected exit()")
|
||||||
}))
|
}))
|
||||||
|
parser, err := New(cli, options...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return parser
|
return parser
|
||||||
}
|
}
|
||||||
@@ -381,19 +382,13 @@ func TestHooks(t *testing.T) {
|
|||||||
{"Flag", "one --three=three", values{true, "", "three"}},
|
{"Flag", "one --three=three", values{true, "", "three"}},
|
||||||
{"ArgAndFlag", "one two --three=three", values{true, "two", "three"}},
|
{"ArgAndFlag", "one two --three=three", values{true, "two", "three"}},
|
||||||
}
|
}
|
||||||
p := mustNew(t, &cli).
|
setOne := func(app *Kong, ctx *Context, trace *Trace) error { hooked.one = true; return nil }
|
||||||
Hook(&cli.One, func(app *Kong, ctx *Context, trace *Trace) error {
|
setTwo := func(app *Kong, ctx *Context, trace *Trace) error { hooked.two = trace.Value.String(); return nil }
|
||||||
hooked.one = true
|
setThree := func(app *Kong, ctx *Context, trace *Trace) error { hooked.three = trace.Value.String(); return nil }
|
||||||
return nil
|
p := mustNew(t, &cli,
|
||||||
}).
|
Hook(&cli.One, setOne),
|
||||||
Hook(&cli.One.Two, func(app *Kong, ctx *Context, trace *Trace) error {
|
Hook(&cli.One.Two, setTwo),
|
||||||
hooked.two = trace.Value.String()
|
Hook(&cli.One.Three, setThree))
|
||||||
return nil
|
|
||||||
}).
|
|
||||||
Hook(&cli.One.Three, func(app *Kong, ctx *Context, trace *Trace) error {
|
|
||||||
hooked.three = trace.Value.String()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
hooked = values{}
|
hooked = values{}
|
||||||
|
|||||||
+19
@@ -2,6 +2,7 @@ package kong
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"reflect"
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -12,6 +13,13 @@ func ExitFunction(exit func(int)) Option {
|
|||||||
return func(k *Kong) { k.Exit = exit }
|
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.
|
// Name overrides the application name.
|
||||||
func Name(name string) Option {
|
func Name(name string) Option {
|
||||||
return func(k *Kong) { k.Model.Name = name }
|
return func(k *Kong) { k.Model.Name = name }
|
||||||
@@ -41,3 +49,14 @@ func Writers(stdout, stderr io.Writer) Option {
|
|||||||
k.Stderr = stderr
|
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