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

@ -7,8 +7,9 @@ import (
)
var (
ErrUnknownOption = errors.New("unknown option")
ErrCannotChainOption = errors.New("cannot chain option")
ErrUnknownOption = errors.New("unknown option")
ErrCannotChainOption = errors.New("cannot chain option")
ErrOptionRequiresValue = errors.New("option requires value")
)
type Parser struct {
@ -76,12 +77,12 @@ func (p *Parser) peek() string {
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(), "-")) {
return ""
return "", false
}
return p.next()
return p.next(), true
}
func (p *Parser) restArgs() []string {
@ -109,7 +110,11 @@ func (p *Parser) parseLongOption(longName string) error {
}
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 {
@ -121,7 +126,7 @@ func (p *Parser) parseLongOption(longName string) error {
func (p *Parser) parseShortOption(shortNames string) error {
if len(shortNames) == 1 {
value := p.value()
value, valOk := p.value()
opt, ok := p.opts.GetByShortName(shortNames)
if !ok {
@ -132,6 +137,10 @@ func (p *Parser) parseShortOption(shortNames string) error {
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 {
return err
}
@ -156,9 +165,6 @@ func (p *Parser) parseShortOption(shortNames string) error {
value = shortNames[1:]
value = strings.TrimPrefix(value, "=")
if len(value) == 0 {
value = p.value()
}
j = len(shortNames)
}

View File

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