Merge pull request #74 from zimmski/fix-multiple-concated-required-shorts
remove concated short arguments from the parser lookup map
diff --git a/parser.go b/parser.go
index 4662200..674d0e4 100644
--- a/parser.go
+++ b/parser.go
@@ -174,15 +174,15 @@
}
var err error
- var option *Option
+ var options []*Option
prefix, optname, islong := stripOptionPrefix(arg)
optname, argument := splitOption(prefix, optname, islong)
if islong {
- option, err = p.parseLong(s, optname, argument)
+ options, err = p.parseLong(s, optname, argument)
} else {
- option, err = p.parseShort(s, optname, argument)
+ options, err = p.parseShort(s, optname, argument)
}
if err != nil {
@@ -198,7 +198,9 @@
s.retargs = append(s.retargs, arg)
}
} else {
- delete(s.lookup.required, option)
+ for _, option := range options {
+ delete(s.lookup.required, option)
+ }
}
}
diff --git a/parser_private.go b/parser_private.go
index 656aa82..8d29b6b 100644
--- a/parser_private.go
+++ b/parser_private.go
@@ -110,11 +110,11 @@
return newError(errtype, msg)
}
-func (p *Parser) parseOption(s *parseState, name string, option *Option, canarg bool, argument *string) (retoption *Option, err error) {
+func (p *Parser) parseOption(s *parseState, name string, option *Option, canarg bool, argument *string) (err error) {
if !option.canArgument() {
if argument != nil {
msg := fmt.Sprintf("bool flag `%s' cannot have an argument", option)
- return option, newError(ErrNoArgumentForBool, msg)
+ return newError(ErrNoArgumentForBool, msg)
}
err = option.set(nil)
@@ -149,16 +149,20 @@
}
}
- return option, err
+ return err
}
-func (p *Parser) parseLong(s *parseState, name string, argument *string) (option *Option, err error) {
+func (p *Parser) parseLong(s *parseState, name string, argument *string) (options []*Option, err error) {
if option := s.lookup.longNames[name]; option != nil {
+ options = append(options, option)
+
// Only long options that are required can consume an argument
// from the argument list
canarg := !option.OptionalArgument
- return p.parseOption(s, name, option, canarg, argument)
+ err := p.parseOption(s, name, option, canarg, argument)
+
+ return options, err
}
return nil, newError(ErrUnknownFlag, fmt.Sprintf("unknown flag `%s'", name))
@@ -181,7 +185,7 @@
return optname, nil
}
-func (p *Parser) parseShort(s *parseState, optname string, argument *string) (option *Option, err error) {
+func (p *Parser) parseShort(s *parseState, optname string, argument *string) (options []*Option, err error) {
if argument == nil {
optname, argument = p.splitShortConcatArg(s, optname)
}
@@ -189,13 +193,15 @@
for i, c := range optname {
shortname := string(c)
- if option = s.lookup.shortNames[shortname]; option != nil {
+ if option := s.lookup.shortNames[shortname]; option != nil {
+ options = append(options, option)
+
// Only the last short argument can consume an argument from
// the arguments list, and only if it's non optional
canarg := (i+utf8.RuneLen(c) == len(optname)) && !option.OptionalArgument
- if _, err := p.parseOption(s, shortname, option, canarg, argument); err != nil {
- return option, err
+ if err := p.parseOption(s, shortname, option, canarg, argument); err != nil {
+ return options, err
}
} else {
return nil, newError(ErrUnknownFlag, fmt.Sprintf("unknown flag `%s'", shortname))
@@ -206,7 +212,7 @@
argument = nil
}
- return option, nil
+ return options, nil
}
func (p *Parser) parseNonOption(s *parseState) error {
diff --git a/short_test.go b/short_test.go
index 20a7a38..d08702b 100644
--- a/short_test.go
+++ b/short_test.go
@@ -58,6 +58,30 @@
}
}
+func TestShortMultiRequiredConcat(t *testing.T) {
+ var opts = struct {
+ V bool `short:"v" required:"true"`
+ O bool `short:"o" required:"true"`
+ F bool `short:"f" required:"true"`
+ }{}
+
+ ret := assertParseSuccess(t, &opts, "-vo", "-f")
+
+ assertStringArray(t, ret, []string{})
+
+ if !opts.V {
+ t.Errorf("Expected V to be true")
+ }
+
+ if !opts.O {
+ t.Errorf("Expected O to be true")
+ }
+
+ if !opts.F {
+ t.Errorf("Expected F to be true")
+ }
+}
+
func TestShortMultiSlice(t *testing.T) {
var opts = struct {
Values []bool `short:"v"`