add processSequence and make it responsible for respecting "overwrite"

This commit is contained in:
Alex Flint 2022-10-04 13:23:57 -07:00
parent b365ec0781
commit 1cc263f9f2
1 changed files with 47 additions and 39 deletions

View File

@ -206,9 +206,8 @@ func (p *Parser) processOptions(args []string, overwrite bool) ([]string, error)
return nil, fmt.Errorf("unknown argument %s", token) return nil, fmt.Errorf("unknown argument %s", token)
} }
// deal with the case of multiple values // for the case of multiple values, consume tokens until next --option
if arg.cardinality == multiple && !arg.separate { if arg.cardinality == multiple && !arg.separate {
// consume tokens until next --option
var values []string var values []string
if value == "" { if value == "" {
for i+1 < len(args) && !isFlag(args[i+1]) && args[i+1] != "--" { for i+1 < len(args) && !isFlag(args[i+1]) && args[i+1] != "--" {
@ -219,21 +218,9 @@ func (p *Parser) processOptions(args []string, overwrite bool) ([]string, error)
values = append(values, value) values = append(values, value)
} }
// TODO: call p.processVector if err := p.processSequence(arg, values, overwrite); err != nil {
return nil, err
// this is the first time we can check p.seen because we need to correctly
// increment i above, even when we then ignore the value
if p.seen[arg] && !overwrite {
continue
} }
// store the values into the slice or map
err := setSliceOrMap(p.val(arg.dest), values)
if err != nil {
return nil, fmt.Errorf("error processing %s: %v", token, err)
}
p.seen[arg] = true
continue continue
} }
@ -256,7 +243,7 @@ func (p *Parser) processOptions(args []string, overwrite bool) ([]string, error)
} }
// send the value to the argument // send the value to the argument
if err := p.processSingle(arg, value, overwrite); err != nil { if err := p.processScalar(arg, value, overwrite); err != nil {
return nil, err return nil, err
} }
} }
@ -287,21 +274,17 @@ func (p *Parser) processPositionals(positionals []string, overwrite bool) error
break break
} }
if arg.cardinality == multiple { if arg.cardinality == multiple {
// TODO: call p.processMultiple if err := p.processSequence(arg, positionals, overwrite); err != nil {
if !p.seen[arg] || overwrite {
err := setSliceOrMap(p.val(arg.dest), positionals)
if err != nil {
return fmt.Errorf("error processing %s: %v", arg.field.Name, err)
}
p.seen[arg] = true
}
positionals = nil
} else {
if err := p.processSingle(arg, positionals[0], overwrite); err != nil {
return err return err
} }
positionals = positionals[1:] positionals = nil
break
} }
if err := p.processScalar(arg, positionals[0], overwrite); err != nil {
return err
}
positionals = positionals[1:]
} }
if len(positionals) > 0 { if len(positionals) > 0 {
@ -351,8 +334,8 @@ func (p *Parser) processEnvironment(environ []string, overwrite bool) error {
// expect a CSV string in an environment // expect a CSV string in an environment
// variable in the case of multiple values // variable in the case of multiple values
var values []string var values []string
var err error
if len(strings.TrimSpace(value)) > 0 { if len(strings.TrimSpace(value)) > 0 {
var err error
values, err = csv.NewReader(strings.NewReader(value)).Read() values, err = csv.NewReader(strings.NewReader(value)).Read()
if err != nil { if err != nil {
return fmt.Errorf("error parsing CSV string from environment variable %s: %v", arg.env, err) return fmt.Errorf("error parsing CSV string from environment variable %s: %v", arg.env, err)
@ -360,14 +343,14 @@ func (p *Parser) processEnvironment(environ []string, overwrite bool) error {
} }
// TODO: call p.processMultiple, respect "overwrite" // TODO: call p.processMultiple, respect "overwrite"
if err = setSliceOrMap(p.val(arg.dest), values); err != nil { if err := p.processSequence(arg, values, overwrite); err != nil {
return fmt.Errorf("error processing environment variable %s: %v", arg.env, err) return fmt.Errorf("error processing environment variable %s: %v", arg.env, err)
} }
continue continue
} }
if err := p.processSingle(arg, value, overwrite); err != nil { if err := p.processScalar(arg, value, overwrite); err != nil {
return err return fmt.Errorf("error processing environment variable %s: %v", arg.env, err)
} }
} }
@ -393,7 +376,7 @@ func (p *Parser) processDefaults(overwrite bool) error {
if arg.defaultVal == "" { if arg.defaultVal == "" {
continue continue
} }
if err := p.processSingle(arg, arg.defaultVal, overwrite); err != nil { if err := p.processScalar(arg, arg.defaultVal, overwrite); err != nil {
return err return err
} }
} }
@ -401,11 +384,10 @@ func (p *Parser) processDefaults(overwrite bool) error {
return nil return nil
} }
// processSingle parses a single argument, inserts it into the struct, // processScalar parses a single argument, inserts it into the struct,
// and marks the argument as "seen" for the sake of required arguments // and marks the argument as "seen" (unless the argument has been seen
// and overwrite semantics. If the argument has been seen before and // before and overwrite=false, in which case the value is ignored)
// overwrite=false then the value is ignored. func (p *Parser) processScalar(arg *Argument, value string, overwrite bool) error {
func (p *Parser) processSingle(arg *Argument, value string, overwrite bool) error {
if p.seen[arg] && !overwrite && !arg.separate { if p.seen[arg] && !overwrite && !arg.separate {
return nil return nil
} }
@ -431,6 +413,32 @@ func (p *Parser) processSingle(arg *Argument, value string, overwrite bool) erro
return nil return nil
} }
// processSequence parses a sequence argument, inserts it into the struct,
// and marks the argument as "seen" (unless the argument has been seen
// before and overwrite=false, in which case the value is ignored)
func (p *Parser) processSequence(arg *Argument, values []string, overwrite bool) error {
if p.seen[arg] && !overwrite && !arg.separate {
return nil
}
name := strings.ToLower(arg.field.Name)
if arg.long != "" && !arg.positional {
name = "--" + arg.long
}
if arg.cardinality != multiple {
panic(fmt.Sprintf("processSequence called for argument %s which has cardinality %v", arg.field.Name, arg.cardinality))
}
err := setSliceOrMap(p.val(arg.dest), values)
if err != nil {
return fmt.Errorf("error processing default value for %s: %v", name, err)
}
p.seen[arg] = true
return nil
}
// Missing returns a list of required arguments that were not provided // Missing returns a list of required arguments that were not provided
func (p *Parser) Missing() []*Argument { func (p *Parser) Missing() []*Argument {
var missing []*Argument var missing []*Argument