Return error when value is not specified and add more test cases

This commit is contained in:
Evan Fiordeliso 2023-11-12 17:06:43 -05:00
parent 9456b4097b
commit b8a7d72433
2 changed files with 41 additions and 13 deletions

View File

@ -9,6 +9,7 @@ import (
var ( var (
ErrUnknownOption = errors.New("unknown option") ErrUnknownOption = errors.New("unknown option")
ErrCannotChainOption = errors.New("cannot chain option") ErrCannotChainOption = errors.New("cannot chain option")
ErrOptionRequiresValue = errors.New("option requires value")
) )
type Parser struct { type Parser struct {
@ -76,12 +77,12 @@ func (p *Parser) peek() string {
return p.args[p.curr+1] return p.args[p.curr+1]
} }
func (p *Parser) value() string { func (p *Parser) value() (string, bool) {
if !p.hasNext() || (p.peek() != "-" && strings.HasPrefix(p.peek(), "-")) { if !p.hasNext() || (p.peek() != "-" && strings.HasPrefix(p.peek(), "-")) {
return "" return "", false
} }
return p.next() return p.next(), true
} }
func (p *Parser) restArgs() []string { func (p *Parser) restArgs() []string {
@ -109,7 +110,11 @@ func (p *Parser) parseLongOption(longName string) error {
} }
if value == "" && opt.TakesArg() { if value == "" && opt.TakesArg() {
value = p.value() var ok bool
value, ok = p.value()
if !ok {
return fmt.Errorf("%w: %s", ErrOptionRequiresValue, "--"+longName)
}
} }
if err := opt.Parse(value); err != nil { if err := opt.Parse(value); err != nil {
@ -121,7 +126,7 @@ func (p *Parser) parseLongOption(longName string) error {
func (p *Parser) parseShortOption(shortNames string) error { func (p *Parser) parseShortOption(shortNames string) error {
if len(shortNames) == 1 { if len(shortNames) == 1 {
value := p.value() value, valOk := p.value()
opt, ok := p.opts.GetByShortName(shortNames) opt, ok := p.opts.GetByShortName(shortNames)
if !ok { if !ok {
@ -132,6 +137,10 @@ func (p *Parser) parseShortOption(shortNames string) error {
return nil // Ignore unknown option. Continue parsing. return nil // Ignore unknown option. Continue parsing.
} }
if !valOk && opt.TakesArg() {
return fmt.Errorf("%w: %s", ErrOptionRequiresValue, "-"+shortNames)
}
if err := opt.Parse(value); err != nil { if err := opt.Parse(value); err != nil {
return err return err
} }
@ -156,9 +165,6 @@ func (p *Parser) parseShortOption(shortNames string) error {
value = shortNames[1:] value = shortNames[1:]
value = strings.TrimPrefix(value, "=") value = strings.TrimPrefix(value, "=")
if len(value) == 0 {
value = p.value()
}
j = len(shortNames) j = len(shortNames)
} }

View File

@ -168,15 +168,15 @@ func TestParseLongOptionWithValueAndSpace(t *testing.T) {
func TestParseOptionTerminator(t *testing.T) { func TestParseOptionTerminator(t *testing.T) {
opt := opts.String("fruit", "f", "banana", "") opt := opts.String("fruit", "f", "banana", "")
set := opts.Set{opt} set := opts.Set{opt}
args := []string{"--fruit", "--", "hello", "world"} args := []string{"--fruit", "apple", "--", "hello", "world"}
parser := opts.NewParser(args, set, false) parser := opts.NewParser(args, set, false)
restArgs, err := parser.Parse() restArgs, err := parser.Parse()
if err != nil { if err != nil {
t.Errorf("Expected no error, got: %s", err.Error()) t.Errorf("Expected no error, got: %s", err.Error())
} }
if opt.Value() != "banana" { if opt.Value() != "apple" {
t.Errorf("Expected fruit to be 'banana', got: %s", opt.Value()) t.Errorf("Expected fruit to be 'apple', got: %s", opt.Value())
} }
if len(restArgs) != 2 { if len(restArgs) != 2 {
@ -311,3 +311,25 @@ func TestParseShortOptionWithEqualBadValue(t *testing.T) {
t.Error("Expected error") t.Error("Expected error")
} }
} }
func TestParseLongOptionMissingValue(t *testing.T) {
opt := opts.Int("fruit", "f", 0, "")
set := opts.Set{opt}
args := []string{"--fruit"}
parser := opts.NewParser(args, set, false)
_, err := parser.Parse()
if err == nil {
t.Error("Expected error")
}
}
func TestParseShortOptionMissingValue(t *testing.T) {
opt := opts.Int("fruit", "f", 0, "")
set := opts.Set{opt}
args := []string{"-f"}
parser := opts.NewParser(args, set, false)
_, err := parser.Parse()
if err == nil {
t.Error("Expected error")
}
}