Skip to content

Commit

Permalink
other variadic types
Browse files Browse the repository at this point in the history
  • Loading branch information
mailund committed Jun 20, 2021
1 parent 3ab20e4 commit 4c5ca25
Show file tree
Hide file tree
Showing 3 changed files with 295 additions and 0 deletions.
28 changes: 28 additions & 0 deletions commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,34 @@ Arguments:
if msg != expected {
t.Errorf("Expected usage message %s but got %s\n", expected, msg)
}

cmd = cli.NewCommand("name", "short", "", init)

builder = new(strings.Builder)
cmd.SetOutput(builder)
cmd.Usage()
msg = builder.String()
expected = `Usage: name [options] bar
short
Options:
-foo
set foo
-help
show help for name
Arguments:
bar
a bar
`
msg = space.ReplaceAllString(msg, " ")
expected = space.ReplaceAllString(expected, " ")
if msg != expected {
t.Errorf("Expected usage message %s but got %s\n", expected, msg)
}
}

func TestCommandCalled(t *testing.T) {
Expand Down
203 changes: 203 additions & 0 deletions params/paramset.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,28 @@ func intParser(target *int) func(string) error {
}
}

func boolParser(target *bool) func(string) error {
return func(arg string) error {
if val, err := strconv.ParseBool(arg); err != nil {
return fmt.Errorf("argument `%s` cannot be parsed as a bool", arg)
} else {
*target = val
return nil
}
}
}

func floatParser(target *float64) func(string) error {
return func(arg string) error {
if val, err := strconv.ParseFloat(arg, 64); err != nil {
return fmt.Errorf("argument `%s` cannot be parsed as a float", arg)
} else {
*target = val
return nil
}
}
}

// StringVar appends a string argument to the set. If the
// parameter set is parsed succesfully, the parsed value for this
// parameter will have been written to target.
Expand Down Expand Up @@ -282,6 +304,58 @@ func (p *ParamSet) Int(name, desc string) *int {
return &x
}

// BoolVar appends a boolean argument to the set. If the
// parameter set is parsed succesfully, the parsed value for this
// parameter will have been written to target.
//
// Parameters:
// - target: Pointer to where the parsed argument should be written.
// - name: Name of the argument, used when printing usage.
// - desc: Description of the argument. Used when printing usage.
func (p *ParamSet) BoolVar(target *bool, name, desc string) {
p.Func(name, desc, boolParser(target))
}

// Bool appends a boolean argument to the set and returns
// a pointer to the new variable's target. If the
// parameter set is parsed succesfully, the parsed value for this
// parameter will have been written to target.
//
// Parameters:
// - name: Name of the argument, used when printing usage.
// - desc: Description of the argument. Used when printing usage.
func (p *ParamSet) Bool(name, desc string) *bool {
var x bool
p.BoolVar(&x, name, desc)
return &x
}

// FloatVar appends a floating point argument to the set. If the
// parameter set is parsed succesfully, the parsed value for this
// parameter will have been written to target.
//
// Parameters:
// - target: Pointer to where the parsed argument should be written.
// - name: Name of the argument, used when printing usage.
// - desc: Description of the argument. Used when printing usage.
func (p *ParamSet) FloatVar(target *float64, name, desc string) {
p.Func(name, desc, floatParser(target))
}

// Float appends a floating point argument to the set and returns
// a pointer to the new variable's target. If the
// parameter set is parsed succesfully, the parsed value for this
// parameter will have been written to target.
//
// Parameters:
// - name: Name of the argument, used when printing usage.
// - desc: Description of the argument. Used when printing usage.
func (p *ParamSet) Float(name, desc string) *float64 {
var x float64
p.FloatVar(&x, name, desc)
return &x
}

// Func appends a callback function as an argument. When
// the parameter set is parsed, this function will be called.
// If the function returns nil, the parser assumes that all
Expand All @@ -303,6 +377,51 @@ func variadicStringParser(target *[]string) func([]string) error {
}
}

func variadicBoolParser(target *[]bool) func([]string) error {
return func(args []string) error {
res := make([]bool, len(args))
for i, x := range args {
if val, err := strconv.ParseBool(x); err == nil {
res[i] = val
} else {
return err
}
}
*target = res
return nil
}
}

func variadicIntParser(target *[]int) func([]string) error {
return func(args []string) error {
res := make([]int, len(args))
for i, x := range args {
if val, err := strconv.Atoi(x); err == nil {
res[i] = val
} else {
return err
}
}
*target = res
return nil
}
}

func variadicFloatParser(target *[]float64) func([]string) error {
return func(args []string) error {
res := make([]float64, len(args))
for i, x := range args {
if val, err := strconv.ParseFloat(x, 64); err == nil {
res[i] = val
} else {
return err
}
}
*target = res
return nil
}
}

// VariadicStringVar install a variadic string argument
// as the last parameter(s) for the parameter set.
//
Expand Down Expand Up @@ -331,6 +450,90 @@ func (p *ParamSet) VariadicString(name, desc string, min int) *[]string {
return &x
}

// VariadicBoolVar install a variadic bool argument
// as the last parameter(s) for the parameter set.
//
// Parameters:
// - target: Pointer to where the parsed arguments should be written.
// - name: Name of the argument, used when printing usage.
// - desc: Description of the argument. Used when printing usage.
// - min: The minumum number of arguments that the command line must
// have for this parameter.
func (p *ParamSet) VariadicBoolVar(target *[]bool, name, desc string, min int) {
p.VariadicFunc(name, desc, min, variadicBoolParser(target))
}

// VariadicBool install a variadic bool argument
// as the last parameter(s) for the parameter set. It returns a pointer
// to where the parsed values will go if parsing is successfull.
//
// Parameters:
// - name: Name of the argument, used when printing usage.
// - desc: Description of the argument. Used when printing usage.
// - min: The minumum number of arguments that the command line must
// have for this parameter.
func (p *ParamSet) VariadicBool(name, desc string, min int) *[]bool {
var x = []bool{}
p.VariadicBoolVar(&x, name, desc, min)
return &x
}

// VariadicIntVar install a variadic int argument
// as the last parameter(s) for the parameter set.
//
// Parameters:
// - target: Pointer to where the parsed arguments should be written.
// - name: Name of the argument, used when printing usage.
// - desc: Description of the argument. Used when printing usage.
// - min: The minumum number of arguments that the command line must
// have for this parameter.
func (p *ParamSet) VariadicIntVar(target *[]int, name, desc string, min int) {
p.VariadicFunc(name, desc, min, variadicIntParser(target))
}

// VariadicInt install a variadic int argument
// as the last parameter(s) for the parameter set. It returns a pointer
// to where the parsed values will go if parsing is successfull.
//
// Parameters:
// - name: Name of the argument, used when printing usage.
// - desc: Description of the argument. Used when printing usage.
// - min: The minumum number of arguments that the command line must
// have for this parameter.
func (p *ParamSet) VariadicInt(name, desc string, min int) *[]int {
var x = []int{}
p.VariadicIntVar(&x, name, desc, min)
return &x
}

// VariadicIntVar install a variadic float argument
// as the last parameter(s) for the parameter set.
//
// Parameters:
// - target: Pointer to where the parsed arguments should be written.
// - name: Name of the argument, used when printing usage.
// - desc: Description of the argument. Used when printing usage.
// - min: The minumum number of arguments that the command line must
// have for this parameter.
func (p *ParamSet) VariadicFloatVar(target *[]float64, name, desc string, min int) {
p.VariadicFunc(name, desc, min, variadicFloatParser(target))
}

// VariadicInt install a variadic float argument
// as the last parameter(s) for the parameter set. It returns a pointer
// to where the parsed values will go if parsing is successfull.
//
// Parameters:
// - name: Name of the argument, used when printing usage.
// - desc: Description of the argument. Used when printing usage.
// - min: The minumum number of arguments that the command line must
// have for this parameter.
func (p *ParamSet) VariadicFloat(name, desc string, min int) *[]float64 {
var x = []float64{}
p.VariadicFloatVar(&x, name, desc, min)
return &x
}

// VariadicFunc install a variadic callback function
// as the last parameter(s) for the parameter set. The callback will be
// invoked when the parser reaches the end of the normal parameters.
Expand Down
64 changes: 64 additions & 0 deletions params/paramset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,3 +321,67 @@ func TestInt(t *testing.T) {
t.Errorf("Unexpected error message %s", errmsg)
}
}

func TestBool(t *testing.T) {
var failed = false
failure.Failure = func() { failed = true }

p := params.NewParamSet("test", params.ExitOnError)
bp := p.Bool("var", "")
p.Parse([]string{"1"})
if !*bp {
t.Errorf("Parse error, val is %t", *bp)
}
p.Parse([]string{"0"})
if *bp {
t.Errorf("Parse error, val is %t", *bp)
}
p.Parse([]string{"false"})
if *bp {
t.Errorf("Parse error, val is %t", *bp)
}
p.Parse([]string{"true"})
if !*bp {
t.Errorf("Parse error, val is %t", *bp)
}

builder := new(strings.Builder)
p.SetOutput(builder)
err := p.Parse([]string{"foo"})
if err == nil {
t.Error("Expected an error")
}
if !failed {
t.Error("Expected to fail")
}
errmsg := builder.String()
if !strings.HasPrefix(errmsg, `Error parsing parameter var='foo'`) {
t.Errorf("Unexpected error message %s", errmsg)
}
}

func TestFloat(t *testing.T) {
var failed = false
failure.Failure = func() { failed = true }

p := params.NewParamSet("test", params.ExitOnError)
x := p.Float("var", "")
p.Parse([]string{"3.14"})
if *x != 3.14 {
t.Errorf("Parse error, x is %f", *x)
}

builder := new(strings.Builder)
p.SetOutput(builder)
err := p.Parse([]string{"foo"})
if err == nil {
t.Error("Expected an error")
}
if !failed {
t.Error("Expected to fail")
}
errmsg := builder.String()
if !strings.HasPrefix(errmsg, `Error parsing parameter var='foo'`) {
t.Errorf("Unexpected error message %s", errmsg)
}
}

0 comments on commit 4c5ca25

Please sign in to comment.