Skip to content

Commit

Permalink
refactor bool parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
phm07 committed Jun 5, 2024
1 parent 3f63626 commit 5e5ac80
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 8 deletions.
13 changes: 13 additions & 0 deletions internal/cmd/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,3 +289,16 @@ func ToAnySlice[T any](a []T) []any {
}
return s
}

// ParseBoolLenient parses the passed string as a boolean. It is different from strconv.ParseBool in that it
// is case-insensitive and also accepts "yes"/"y" and "no"/"n" as valid values.
func ParseBoolLenient(s string) (bool, error) {
switch strings.ToLower(s) {
case "true", "t", "yes", "y", "1":
return true, nil
case "false", "f", "no", "n", "0":
return false, nil
default:
return false, fmt.Errorf("invalid boolean value: %s", s)
}
}
43 changes: 43 additions & 0 deletions internal/cmd/util/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,3 +337,46 @@ func TestToAnySlice(t *testing.T) {
assert.Equal(t, []any{1, 2, 3}, util.ToAnySlice([]int{1, 2, 3}))
assert.Equal(t, []any{true, false}, util.ToAnySlice([]bool{true, false}))
}

func TestParseBoolLenient(t *testing.T) {
b, err := util.ParseBoolLenient("true")
assert.NoError(t, err)
assert.True(t, b)
b, err = util.ParseBoolLenient("True")
assert.NoError(t, err)
assert.True(t, b)
b, err = util.ParseBoolLenient("t")
assert.NoError(t, err)
assert.True(t, b)
b, err = util.ParseBoolLenient("yes")
assert.NoError(t, err)
assert.True(t, b)
b, err = util.ParseBoolLenient("y")
assert.NoError(t, err)
assert.True(t, b)
b, err = util.ParseBoolLenient("1")
assert.NoError(t, err)
assert.True(t, b)
b, err = util.ParseBoolLenient("false")
assert.NoError(t, err)
assert.False(t, b)
b, err = util.ParseBoolLenient("False")
assert.NoError(t, err)
assert.False(t, b)
b, err = util.ParseBoolLenient("f")
assert.NoError(t, err)
assert.False(t, b)
b, err = util.ParseBoolLenient("no")
assert.NoError(t, err)
assert.False(t, b)
b, err = util.ParseBoolLenient("n")
assert.NoError(t, err)
assert.False(t, b)
b, err = util.ParseBoolLenient("0")
assert.NoError(t, err)
assert.False(t, b)
b, err = util.ParseBoolLenient("invalid")
assert.EqualError(t, err, "invalid boolean value: invalid")
b, err = util.ParseBoolLenient("")
assert.EqualError(t, err, "invalid boolean value: ")
}
12 changes: 4 additions & 8 deletions internal/state/config/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,14 +255,10 @@ func (o *Option[T]) Parse(values []string) (any, error) {
if len(values) != 1 {
return nil, fmt.Errorf("expected exactly one value")
}
value := values[0]
switch strings.ToLower(value) {
case "true", "t", "yes", "y", "1":
val = true
case "false", "f", "no", "n", "0":
val = false
default:
return nil, fmt.Errorf("invalid boolean value: %s", value)
var err error
val, err = util.ParseBoolLenient(values[0])
if err != nil {
return nil, err
}
case string:
if len(values) != 1 {
Expand Down

0 comments on commit 5e5ac80

Please sign in to comment.