Add App.UnknownFlagHandler

This commit is contained in:
Ilia Choly 2022-08-02 15:12:31 -04:00 committed by Dan Buch
parent 321d49344b
commit 6331815fae
Signed by: meatballhat
GPG Key ID: A12F782281063434
4 changed files with 41 additions and 1 deletions

2
app.go
View File

@ -78,6 +78,8 @@ type App struct {
CommandNotFound CommandNotFoundFunc CommandNotFound CommandNotFoundFunc
// Execute this function if a usage error occurs // Execute this function if a usage error occurs
OnUsageError OnUsageErrorFunc OnUsageError OnUsageErrorFunc
// Execute this function when an unknown flag is accessed from the context
UnknownFlagHandler UnknownFlagFunc
// Compilation date // Compilation date
Compiled time.Time Compiled time.Time
// List of all authors who contributed // List of all authors who contributed

View File

@ -46,6 +46,9 @@ func (cCtx *Context) NumFlags() int {
// Set sets a context flag to a value. // Set sets a context flag to a value.
func (cCtx *Context) Set(name, value string) error { func (cCtx *Context) Set(name, value string) error {
if cCtx.flagSet.Lookup(name) == nil {
cCtx.onUnknownFlag(name)
}
return cCtx.flagSet.Set(name, value) return cCtx.flagSet.Set(name, value)
} }
@ -158,7 +161,7 @@ func (cCtx *Context) lookupFlagSet(name string) *flag.FlagSet {
return c.flagSet return c.flagSet
} }
} }
cCtx.onUnknownFlag(name)
return nil return nil
} }
@ -190,6 +193,12 @@ func (cCtx *Context) checkRequiredFlags(flags []Flag) requiredFlagsErr {
return nil return nil
} }
func (cCtx *Context) onUnknownFlag(name string) {
if cCtx.App != nil && cCtx.App.UnknownFlagHandler != nil {
cCtx.App.UnknownFlagHandler(cCtx, name)
}
}
func makeFlagNameVisitor(names *[]string) func(*flag.Flag) { func makeFlagNameVisitor(names *[]string) func(*flag.Flag) {
return func(f *flag.Flag) { return func(f *flag.Flag) {
nameParts := strings.Split(f.Name, ",") nameParts := strings.Split(f.Name, ",")

View File

@ -150,6 +150,19 @@ func TestContext_Value(t *testing.T) {
expect(t, c.Value("unknown-flag"), nil) expect(t, c.Value("unknown-flag"), nil)
} }
func TestContext_Value_UnknownFlagHandler(t *testing.T) {
set := flag.NewFlagSet("test", 0)
var flagName string
app := &App{
UnknownFlagHandler: func(_ *Context, name string) {
flagName = name
},
}
c := NewContext(app, set, nil)
c.Value("missing")
expect(t, flagName, "missing")
}
func TestContext_Args(t *testing.T) { func TestContext_Args(t *testing.T) {
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
set.Bool("myflag", false, "doc") set.Bool("myflag", false, "doc")
@ -258,6 +271,19 @@ func TestContext_Set(t *testing.T) {
expect(t, c.IsSet("int"), true) expect(t, c.IsSet("int"), true)
} }
func TestContext_Set_StrictLookup(t *testing.T) {
set := flag.NewFlagSet("test", 0)
var flagName string
app := &App{
UnknownFlagHandler: func(_ *Context, name string) {
flagName = name
},
}
c := NewContext(app, set, nil)
c.Set("missing", "")
expect(t, flagName, "missing")
}
func TestContext_LocalFlagNames(t *testing.T) { func TestContext_LocalFlagNames(t *testing.T) {
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
set.Bool("one-flag", false, "doc") set.Bool("one-flag", false, "doc")

View File

@ -23,6 +23,9 @@ type CommandNotFoundFunc func(*Context, string)
// is displayed and the execution is interrupted. // is displayed and the execution is interrupted.
type OnUsageErrorFunc func(cCtx *Context, err error, isSubcommand bool) error type OnUsageErrorFunc func(cCtx *Context, err error, isSubcommand bool) error
// UnknownFlagFunc is executed when an unknown flag is accessed from the context.
type UnknownFlagFunc func(*Context, string)
// ExitErrHandlerFunc is executed if provided in order to handle exitError values // ExitErrHandlerFunc is executed if provided in order to handle exitError values
// returned by Actions and Before/After functions. // returned by Actions and Before/After functions.
type ExitErrHandlerFunc func(cCtx *Context, err error) type ExitErrHandlerFunc func(cCtx *Context, err error)