Skip to content

Commit

Permalink
Add opt.SetValue
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidGamba committed Feb 22, 2024
1 parent 2b8f132 commit 24b4362
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 5 deletions.
2 changes: 2 additions & 0 deletions changelog.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Tested with Go 1.16, 1.17, 1.18, 1.19, 1.20 and 1.21.

=== New Features

* Add `opt.SetValue` to allow setting the value of an option.

* Add `opt.SuggestedValues` ModifyFn to allow setting autocompletion suggestions for an option.
+
Works just like the existing `opt.ValidValues` but it doesn't error out if the value is not in the list of suggestions.
Expand Down
3 changes: 3 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ var ErrorHelpCalled = fmt.Errorf("help called")

// ErrorParsing - Indicates that there was an error with cli args parsing
var ErrorParsing = errors.New("")

// ErrorNotFound - Generic not found error
var ErrorNotFound = fmt.Errorf("not found")
12 changes: 7 additions & 5 deletions internal/option/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -472,12 +472,14 @@ func (opt *Option) Save(a ...string) error {
opt.SetFloat64Slice(append(*opt.pFloat64S, ff...))
return nil
case StringMapType:
keyValue := strings.Split(a[0], "=")
if len(keyValue) < 2 {
// TODO: Create error type for use in tests with errors.Is
return fmt.Errorf(text.ErrorArgumentIsNotKeyValue, opt.UsedAlias)
for _, e := range a {
keyValue := strings.Split(e, "=")
if len(keyValue) < 2 {
// TODO: Create error type for use in tests with errors.Is
return fmt.Errorf(text.ErrorArgumentIsNotKeyValue, opt.UsedAlias)
}
opt.SetKeyValueToStringMap(keyValue[0], keyValue[1])
}
opt.SetKeyValueToStringMap(keyValue[0], keyValue[1])
return nil
case IncrementType:
opt.SetInt(opt.Int() + 1)
Expand Down
76 changes: 76 additions & 0 deletions public_api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"os"
"path/filepath"
"reflect"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -4148,3 +4149,78 @@ SYNOPSIS:
}
})
}

func TestSetValue(t *testing.T) {
t.Run("not found error", func(t *testing.T) {
opt := getoptions.New()
opt.String("str", "")
err := opt.SetValue("x", "y")
if err == nil {
t.Errorf("no error")
}
if !strings.Contains(err.Error(), "not found") {
t.Errorf("wrong error: %s", err)
}
})
t.Run("string", func(t *testing.T) {
opt := getoptions.New()
opt.String("str", "")
opt.SetValue("str", "hello")
if opt.Value("str") != "hello" {
t.Errorf("wrong value %v", opt.Value("str"))
}
})
t.Run("bool", func(t *testing.T) {
opt := getoptions.New()
opt.Bool("bool", false)
opt.SetValue("bool")
if opt.Value("bool") != true {
t.Errorf("wrong value %v", opt.Value("bool"))
}
})
t.Run("int", func(t *testing.T) {
opt := getoptions.New()
opt.Int("int", 0)
opt.SetValue("int", "123")
if opt.Value("int") != 123 {
t.Errorf("wrong value %v", opt.Value("int"))
}
})
t.Run("float64", func(t *testing.T) {
opt := getoptions.New()
opt.Float64("float64", 0)
opt.SetValue("float64", "3.14")
if opt.Value("float64") != 3.14 {
t.Errorf("wrong value %v", opt.Value("float64"))
}
})
t.Run("float64 error", func(t *testing.T) {
opt := getoptions.New()
opt.Float64("float64", 0)
err := opt.SetValue("float64", "x")
if err == nil {
t.Errorf("no error")
}
if !strings.Contains(err.Error(), "Can't convert string to float64: 'x'") {
t.Errorf("wrong error: %s", err)
}
})
t.Run("stringSlice", func(t *testing.T) {
opt := getoptions.New()
opt.StringSlice("str", 1, 99)
opt.SetValue("str", "hello", "world")
opt.SetValue("str", "hello", "world")
if !reflect.DeepEqual(opt.Value("str"), []string{"hello", "world", "hello", "world"}) {
t.Errorf("wrong value %v", opt.Value("str"))
}
})
t.Run("stringMap", func(t *testing.T) {
opt := getoptions.New()
opt.StringMap("str", 1, 99)
opt.SetValue("str", "hello=world", "goodbye=world")
opt.SetValue("str", "hola=mundo")
if !reflect.DeepEqual(opt.Value("str"), map[string]string{"hello": "world", "goodbye": "world", "hola": "mundo"}) {
t.Errorf("wrong value %v", opt.Value("str"))
}
})
}
17 changes: 17 additions & 0 deletions user_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,23 @@ func (gopt *GetOpt) Value(name string) interface{} {
return nil
}

// SetValue - Set the value of the given option using strings as an argument.
//
// Examples:
//
// opt.SetValue("bool") // boolean - sets to opposite of default
// opt.SetValue("int", "123") // int
// err := opt.SetValue("float64", "x") // error because "x" is not a valid float64
// opt.SetValue("slice", "a", "b", "c") // []string
// opt.SetValue("slice", "d", "e", "f") // Can be called multiple times for options that allow it
// opt.SetValue("map", "hello=world", "hola=mundo") // map[string]string
func (gopt *GetOpt) SetValue(name string, value ...string) error {
if v, ok := gopt.programTree.ChildOptions[name]; ok {
return v.Save(value...)
}
return ErrorNotFound
}

// Bool - define a `bool` option and its aliases.
// It returns a `*bool` pointing to the variable holding the result.
// If the option is found, the result will be the opposite of the provided default.
Expand Down

0 comments on commit 24b4362

Please sign in to comment.