diff --git a/app.go b/app.go index d03ec5d..16b0b19 100644 --- a/app.go +++ b/app.go @@ -223,7 +223,7 @@ func (a *App) Run(arguments []string) (err error) { return err } - err = parseIter(set, a, arguments[1:]) + err = parseIter(set, a, arguments[1:], shellComplete) nerr := normalizeFlags(a.Flags, set) context := NewContext(a, set, nil) if nerr != nil { @@ -349,7 +349,7 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { return err } - err = parseIter(set, a, ctx.Args().Tail()) + err = parseIter(set, a, ctx.Args().Tail(), ctx.shellComplete) nerr := normalizeFlags(a.Flags, set) context := NewContext(a, set, ctx) diff --git a/command.go b/command.go index a99da0a..db6c802 100644 --- a/command.go +++ b/command.go @@ -184,9 +184,8 @@ func (c *Command) parseFlags(args Args, shellComplete bool) (*flag.FlagSet, erro return set, set.Parse(append([]string{"--"}, args.Tail()...)) } - err = parseIter(set, c, args.Tail()) - // Continue parsing flags on failure during shell completion - if err != nil && !shellComplete { + err = parseIter(set, c, args.Tail(), shellComplete) + if err != nil { return nil, err } diff --git a/parse.go b/parse.go index 660f538..e77568d 100644 --- a/parse.go +++ b/parse.go @@ -11,19 +11,24 @@ type iterativeParser interface { } // To enable short-option handling (e.g., "-it" vs "-i -t") we have to -// iteratively catch parsing errors. This way we achieve LR parsing without +// iteratively catch parsing errors. This way we achieve LR parsing without // transforming any arguments. Otherwise, there is no way we can discriminate // combined short options from common arguments that should be left untouched. -func parseIter(set *flag.FlagSet, ip iterativeParser, args []string) error { +// Pass `ignoreErrors` to continue parsing options on failure, for example +// during shell completion when the user-supplied options may be incomplete. +func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, ignoreErrors bool) error { for { err := set.Parse(args) if !ip.useShortOptionHandling() || err == nil { + if ignoreErrors { + return nil + } return err } errStr := err.Error() trimmed := strings.TrimPrefix(errStr, "flag provided but not defined: -") - if errStr == trimmed { + if !ignoreErrors && errStr == trimmed { return err }