Skip to content

Commit b22fc70

Browse files
Expand SliceValue support to all slice and array types.
1 parent c6c0f0f commit b22fc70

20 files changed

+556
-0
lines changed

bool_slice.go

+38
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,44 @@ func (s *boolSliceValue) String() string {
7171
return "[" + out + "]"
7272
}
7373

74+
func (s *boolSliceValue) fromString(val string) (bool, error) {
75+
return strconv.ParseBool(val)
76+
}
77+
78+
func (s *boolSliceValue) toString(val bool) string {
79+
return strconv.FormatBool(val)
80+
}
81+
82+
func (s *boolSliceValue) Append(val string) error {
83+
i, err := s.fromString(val)
84+
if err != nil {
85+
return err
86+
}
87+
*s.value = append(*s.value, i)
88+
return nil
89+
}
90+
91+
func (s *boolSliceValue) Replace(val []string) error {
92+
out := make([]bool, len(val))
93+
for i, d := range val {
94+
var err error
95+
out[i], err = s.fromString(d)
96+
if err != nil {
97+
return err
98+
}
99+
}
100+
*s.value = out
101+
return nil
102+
}
103+
104+
func (s *boolSliceValue) GetSlice() []string {
105+
out := make([]string, len(*s.value))
106+
for i, d := range *s.value {
107+
out[i] = s.toString(d)
108+
}
109+
return out
110+
}
111+
74112
func boolSliceConv(val string) (interface{}, error) {
75113
val = strings.Trim(val, "[]")
76114
// Empty string would cause a slice with one (empty) entry

bool_slice_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,29 @@ func TestBSCalledTwice(t *testing.T) {
160160
}
161161
}
162162

163+
func TestBSAsSliceValue(t *testing.T) {
164+
var bs []bool
165+
f := setUpBSFlagSet(&bs)
166+
167+
in := []string{"true", "false"}
168+
argfmt := "--bs=%s"
169+
arg1 := fmt.Sprintf(argfmt, in[0])
170+
arg2 := fmt.Sprintf(argfmt, in[1])
171+
err := f.Parse([]string{arg1, arg2})
172+
if err != nil {
173+
t.Fatal("expected no error; got", err)
174+
}
175+
176+
f.VisitAll(func(f *Flag) {
177+
if val, ok := f.Value.(SliceValue); ok {
178+
_ = val.Replace([]string{"false"})
179+
}
180+
})
181+
if len(bs) != 1 || bs[0]!= false {
182+
t.Fatalf("Expected ss to be overwritten with 'false', but got: %v", bs)
183+
}
184+
}
185+
163186
func TestBSBadQuoting(t *testing.T) {
164187

165188
tests := []struct {

duration_slice.go

+38
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,44 @@ func (s *durationSliceValue) String() string {
5151
return "[" + strings.Join(out, ",") + "]"
5252
}
5353

54+
func (s *durationSliceValue) fromString(val string) (time.Duration, error) {
55+
return time.ParseDuration(val)
56+
}
57+
58+
func (s *durationSliceValue) toString(val time.Duration) string {
59+
return fmt.Sprintf("%s", val)
60+
}
61+
62+
func (s *durationSliceValue) Append(val string) error {
63+
i, err := s.fromString(val)
64+
if err != nil {
65+
return err
66+
}
67+
*s.value = append(*s.value, i)
68+
return nil
69+
}
70+
71+
func (s *durationSliceValue) Replace(val []string) error {
72+
out := make([]time.Duration, len(val))
73+
for i, d := range val {
74+
var err error
75+
out[i], err = s.fromString(d)
76+
if err != nil {
77+
return err
78+
}
79+
}
80+
*s.value = out
81+
return nil
82+
}
83+
84+
func (s *durationSliceValue) GetSlice() []string {
85+
out := make([]string, len(*s.value))
86+
for i, d := range *s.value {
87+
out[i] = s.toString(d)
88+
}
89+
return out
90+
}
91+
5492
func durationSliceConv(val string) (interface{}, error) {
5593
val = strings.Trim(val, "[]")
5694
// Empty string would cause a slice with one (empty) entry

duration_slice_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,29 @@ func TestDSWithDefault(t *testing.T) {
144144
}
145145
}
146146

147+
func TestDSAsSliceValue(t *testing.T) {
148+
var ds []time.Duration
149+
f := setUpDSFlagSet(&ds)
150+
151+
in := []string{"1ns", "2ns"}
152+
argfmt := "--ds=%s"
153+
arg1 := fmt.Sprintf(argfmt, in[0])
154+
arg2 := fmt.Sprintf(argfmt, in[1])
155+
err := f.Parse([]string{arg1, arg2})
156+
if err != nil {
157+
t.Fatal("expected no error; got", err)
158+
}
159+
160+
f.VisitAll(func(f *Flag) {
161+
if val, ok := f.Value.(SliceValue); ok {
162+
_ = val.Replace([]string{"3ns"})
163+
}
164+
})
165+
if len(ds) != 1 || ds[0]!= time.Duration(3) {
166+
t.Fatalf("Expected ss to be overwritten with '3ns', but got: %v", ds)
167+
}
168+
}
169+
147170
func TestDSCalledTwice(t *testing.T) {
148171
var ds []time.Duration
149172
f := setUpDSFlagSet(&ds)

float32_slice.go

+42
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,48 @@ func (s *float32SliceValue) String() string {
5353
return "[" + strings.Join(out, ",") + "]"
5454
}
5555

56+
func (s *float32SliceValue) fromString(val string) (float32, error) {
57+
t64, err := strconv.ParseFloat(val, 32)
58+
if err != nil {
59+
return 0, err
60+
}
61+
return float32(t64), nil
62+
}
63+
64+
func (s *float32SliceValue) toString(val float32) string {
65+
return fmt.Sprintf("%f", val)
66+
}
67+
68+
func (s *float32SliceValue) Append(val string) error {
69+
i, err := s.fromString(val)
70+
if err != nil {
71+
return err
72+
}
73+
*s.value = append(*s.value, i)
74+
return nil
75+
}
76+
77+
func (s *float32SliceValue) Replace(val []string) error {
78+
out := make([]float32, len(val))
79+
for i, d := range val {
80+
var err error
81+
out[i], err = s.fromString(d)
82+
if err != nil {
83+
return err
84+
}
85+
}
86+
*s.value = out
87+
return nil
88+
}
89+
90+
func (s *float32SliceValue) GetSlice() []string {
91+
out := make([]string, len(*s.value))
92+
for i, d := range *s.value {
93+
out[i] = s.toString(d)
94+
}
95+
return out
96+
}
97+
5698
func float32SliceConv(val string) (interface{}, error) {
5799
val = strings.Trim(val, "[]")
58100
// Empty string would cause a slice with one (empty) entry

float32_slice_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,29 @@ func TestF32SWithDefault(t *testing.T) {
156156
}
157157
}
158158

159+
func TestF32SAsSliceValue(t *testing.T) {
160+
var f32s []float32
161+
f := setUpF32SFlagSet(&f32s)
162+
163+
in := []string{"1.0", "2.0"}
164+
argfmt := "--f32s=%s"
165+
arg1 := fmt.Sprintf(argfmt, in[0])
166+
arg2 := fmt.Sprintf(argfmt, in[1])
167+
err := f.Parse([]string{arg1, arg2})
168+
if err != nil {
169+
t.Fatal("expected no error; got", err)
170+
}
171+
172+
f.VisitAll(func(f *Flag) {
173+
if val, ok := f.Value.(SliceValue); ok {
174+
_ = val.Replace([]string{"3.1"})
175+
}
176+
})
177+
if len(f32s) != 1 || f32s[0]!= 3.1 {
178+
t.Fatalf("Expected ss to be overwritten with '3.1', but got: %v", f32s)
179+
}
180+
}
181+
159182
func TestF32SCalledTwice(t *testing.T) {
160183
var f32s []float32
161184
f := setUpF32SFlagSet(&f32s)

float64_slice.go

+38
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,44 @@ func (s *float64SliceValue) String() string {
5151
return "[" + strings.Join(out, ",") + "]"
5252
}
5353

54+
func (s *float64SliceValue) fromString(val string) (float64, error) {
55+
return strconv.ParseFloat(val, 64)
56+
}
57+
58+
func (s *float64SliceValue) toString(val float64) string {
59+
return fmt.Sprintf("%f", val)
60+
}
61+
62+
func (s *float64SliceValue) Append(val string) error {
63+
i, err := s.fromString(val)
64+
if err != nil {
65+
return err
66+
}
67+
*s.value = append(*s.value, i)
68+
return nil
69+
}
70+
71+
func (s *float64SliceValue) Replace(val []string) error {
72+
out := make([]float64, len(val))
73+
for i, d := range val {
74+
var err error
75+
out[i], err = s.fromString(d)
76+
if err != nil {
77+
return err
78+
}
79+
}
80+
*s.value = out
81+
return nil
82+
}
83+
84+
func (s *float64SliceValue) GetSlice() []string {
85+
out := make([]string, len(*s.value))
86+
for i, d := range *s.value {
87+
out[i] = s.toString(d)
88+
}
89+
return out
90+
}
91+
5492
func float64SliceConv(val string) (interface{}, error) {
5593
val = strings.Trim(val, "[]")
5694
// Empty string would cause a slice with one (empty) entry

float64_slice_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,29 @@ func TestF64SWithDefault(t *testing.T) {
144144
}
145145
}
146146

147+
func TestF64SAsSliceValue(t *testing.T) {
148+
var f64s []float64
149+
f := setUpF64SFlagSet(&f64s)
150+
151+
in := []string{"1.0", "2.0"}
152+
argfmt := "--f64s=%s"
153+
arg1 := fmt.Sprintf(argfmt, in[0])
154+
arg2 := fmt.Sprintf(argfmt, in[1])
155+
err := f.Parse([]string{arg1, arg2})
156+
if err != nil {
157+
t.Fatal("expected no error; got", err)
158+
}
159+
160+
f.VisitAll(func(f *Flag) {
161+
if val, ok := f.Value.(SliceValue); ok {
162+
_ = val.Replace([]string{"3.1"})
163+
}
164+
})
165+
if len(f64s) != 1 || f64s[0]!= 3.1 {
166+
t.Fatalf("Expected ss to be overwritten with '3.1', but got: %v", f64s)
167+
}
168+
}
169+
147170
func TestF64SCalledTwice(t *testing.T) {
148171
var f64s []float64
149172
f := setUpF64SFlagSet(&f64s)

go.mod

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module github.com/spf13/pflags
2+
3+
go 1.12
4+
5+
require github.com/spf13/pflag v1.0.3

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
2+
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=

int32_slice.go

+42
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,48 @@ func (s *int32SliceValue) String() string {
5353
return "[" + strings.Join(out, ",") + "]"
5454
}
5555

56+
func (s *int32SliceValue) fromString(val string) (int32, error) {
57+
t64, err := strconv.ParseInt(val, 0, 32)
58+
if err != nil {
59+
return 0, err
60+
}
61+
return int32(t64), nil
62+
}
63+
64+
func (s *int32SliceValue) toString(val int32) string {
65+
return fmt.Sprintf("%d", val)
66+
}
67+
68+
func (s *int32SliceValue) Append(val string) error {
69+
i, err := s.fromString(val)
70+
if err != nil {
71+
return err
72+
}
73+
*s.value = append(*s.value, i)
74+
return nil
75+
}
76+
77+
func (s *int32SliceValue) Replace(val []string) error {
78+
out := make([]int32, len(val))
79+
for i, d := range val {
80+
var err error
81+
out[i], err = s.fromString(d)
82+
if err != nil {
83+
return err
84+
}
85+
}
86+
*s.value = out
87+
return nil
88+
}
89+
90+
func (s *int32SliceValue) GetSlice() []string {
91+
out := make([]string, len(*s.value))
92+
for i, d := range *s.value {
93+
out[i] = s.toString(d)
94+
}
95+
return out
96+
}
97+
5698
func int32SliceConv(val string) (interface{}, error) {
5799
val = strings.Trim(val, "[]")
58100
// Empty string would cause a slice with one (empty) entry

int32_slice_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,29 @@ func TestI32SWithDefault(t *testing.T) {
150150
}
151151
}
152152

153+
func TestI32SAsSliceValue(t *testing.T) {
154+
var i32s []int32
155+
f := setUpI32SFlagSet(&i32s)
156+
157+
in := []string{"1", "2"}
158+
argfmt := "--is=%s"
159+
arg1 := fmt.Sprintf(argfmt, in[0])
160+
arg2 := fmt.Sprintf(argfmt, in[1])
161+
err := f.Parse([]string{arg1, arg2})
162+
if err != nil {
163+
t.Fatal("expected no error; got", err)
164+
}
165+
166+
f.VisitAll(func(f *Flag) {
167+
if val, ok := f.Value.(SliceValue); ok {
168+
_ = val.Replace([]string{"3"})
169+
}
170+
})
171+
if len(i32s) != 1 || i32s[0]!= 3 {
172+
t.Fatalf("Expected ss to be overwritten with '3.1', but got: %v", i32s)
173+
}
174+
}
175+
153176
func TestI32SCalledTwice(t *testing.T) {
154177
var is []int32
155178
f := setUpI32SFlagSet(&is)

0 commit comments

Comments
 (0)