From 981bfaa04e123a81e0ee0e391c40c6e4f25a589d Mon Sep 17 00:00:00 2001 From: Evan Fiordeliso Date: Sat, 11 Nov 2023 21:29:56 -0500 Subject: [PATCH] Add error for unknown option --- command.go | 6 ++--- opts/parser.go | 66 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/command.go b/command.go index 6075a43..77bf364 100644 --- a/command.go +++ b/command.go @@ -68,12 +68,12 @@ func (c *Command) Execute(args []string) { args = args[1:] } - parser := opts.NewParser(args, c.opts) + parser := opts.NewParser(args, c.opts, false) restArgs, err := parser.Parse() if err != nil { - fmt.Printf("Option error: %s\n", err.Error()) + fmt.Println(err.Error()) c.ShowHelp() - return + os.Exit(1) } if len(restArgs) > 0 { diff --git a/opts/parser.go b/opts/parser.go index 6d61292..59a8d2b 100644 --- a/opts/parser.go +++ b/opts/parser.go @@ -2,10 +2,12 @@ package opts import ( "errors" + "fmt" "strings" ) var ( + ErrUnknownOption = errors.New("unknown option") ErrInvalidShortOption = errors.New("invalid short option") ErrCannotChainOption = errors.New("cannot chain option as it takes an argument") ) @@ -14,13 +16,17 @@ type Parser struct { opts Set args []string curr int + + ignoreUnknown bool } -func NewParser(args []string, opts []Option) *Parser { +func NewParser(args []string, opts []Option, ignoreUnknown bool) *Parser { return &Parser{ opts: append(opts, globalOpts...), args: args, curr: -1, + + ignoreUnknown: ignoreUnknown, } } @@ -93,10 +99,16 @@ func (p *Parser) parseLongOption(longName string) error { } opt, ok := p.opts.GetByLongName(longName) - if ok { - if err := opt.Parse(value); err != nil { - return err + if !ok { + if !p.ignoreUnknown { + return fmt.Errorf("%w: %s", ErrUnknownOption, "--"+longName) } + + return nil // Ignore unknown option. Continue parsing. + } + + if err := opt.Parse(value); err != nil { + return err } return nil @@ -109,10 +121,16 @@ func (p *Parser) parseShortOption(shortNames string) error { value := p.value() opt, ok := p.opts.GetByShortName(shortNames) - if ok { - if err := opt.Parse(value); err != nil { - return err + if !ok { + if !p.ignoreUnknown { + return fmt.Errorf("%w: %s", ErrUnknownOption, "-"+shortNames) } + + return nil // Ignore unknown option. Continue parsing. + } + + if err := opt.Parse(value); err != nil { + return err } } else { for j := 0; j < len(shortNames); j++ { @@ -120,23 +138,29 @@ func (p *Parser) parseShortOption(shortNames string) error { value := "" opt, ok := p.opts.GetByShortName(string(shortName)) - if ok { - if opt.TakesArg() { - if j > 0 { - return ErrCannotChainOption - } - - value = shortNames[1:] - value = strings.TrimPrefix(value, "=") - if len(value) == 0 { - value = p.value() - } - j = len(shortNames) + if !ok { + if !p.ignoreUnknown { + return fmt.Errorf("%w: %s", ErrUnknownOption, "-"+string(shortName)) } - if err := opt.Parse(value); err != nil { - return err + continue // Ignore unknown option. Continue parsing. + } + + if opt.TakesArg() { + if j > 0 { + return ErrCannotChainOption } + + value = shortNames[1:] + value = strings.TrimPrefix(value, "=") + if len(value) == 0 { + value = p.value() + } + j = len(shortNames) + } + + if err := opt.Parse(value); err != nil { + return err } } }