diff options
| -rw-r--r-- | flag.go | 46 | ||||
| -rw-r--r-- | flag_test.go | 12 |
2 files changed, 38 insertions, 20 deletions
@@ -6,6 +6,8 @@ package core import ( "flag" "fmt" + "os" + "strings" "time" ) @@ -28,20 +30,29 @@ func FlagTVar[T any](fs *flag.FlagSet, p *T, name string, value T, usage string, // FlagTSlice works like FlagT, except slices are created; flags created // that way can therefore be repeated. A valid *[]T is returned for use // by the caller. -func FlagTSlice[T any](fs *flag.FlagSet, name string, values []T, usage string, parse ParseFunc[T]) *[]T { +// +// A separator can also be passed so that multiple values may be passed +// as a single argument. An empty string disables that behavior. Note +// that having a separator still allows for repeated flags, so the +// following, with a ‘,’ separator, are equivalent: +// +// - -flag=val -flag=val-2 -flag=val-3 +// - -flag=val,val-2 -flag=val-3 +// - -flag=val,val-2,val-3 +func FlagTSlice[T any](fs *flag.FlagSet, name string, values []T, usage string, parse ParseFunc[T], sep string) *[]T { p := new([]T) - FlagTSliceVar(fs, p, name, values, usage, parse) + FlagTSliceVar(fs, p, name, values, usage, parse, sep) return p } // FlagTSliceVar works like FlagTSlice, except it is up to the caller to // supply a valid *[]T. -func FlagTSliceVar[T any](fs *flag.FlagSet, p *[]T, name string, values []T, usage string, parse ParseFunc[T]) { +func FlagTSliceVar[T any](fs *flag.FlagSet, p *[]T, name string, values []T, usage string, parse ParseFunc[T], sep string) { if values != nil { *p = make([]T, len(values)) copy(*p, values) } - fs.Var(&flagValueSlice[T]{Parse: parse, Values: p}, name, usage) + fs.Var(&flagValueSlice[T]{Parse: parse, Separator: sep, Values: p}, name, usage) } // ParseString returns the string passed with no error set. @@ -83,8 +94,9 @@ func (f *flagValue[T]) String() string { } type flagValueSlice[T any] struct { - Parse ParseFunc[T] - Values *[]T + Parse ParseFunc[T] + Separator string + Values *[]T shouldAppend bool } @@ -92,15 +104,21 @@ type flagValueSlice[T any] struct { var _ flag.Value = &flagValueSlice[any]{} func (f *flagValueSlice[T]) Set(s string) error { - val, err := f.Parse(s) - if err != nil { - return err + vals := []string{s} + if f.Separator != "" { + vals = strings.Split(s, f.Separator) } - if f.shouldAppend { - *f.Values = append(*f.Values, val) - } else { - *f.Values = []T{val} - f.shouldAppend = true + for _, val := range vals { + parsed, err := f.Parse(val) + if err != nil { + return err + } + if f.shouldAppend { + *f.Values = append(*f.Values, parsed) + } else { + *f.Values = []T{parsed} + f.shouldAppend = true + } } return nil } diff --git a/flag_test.go b/flag_test.go index 1492e7a..ccbfadb 100644 --- a/flag_test.go +++ b/flag_test.go @@ -36,10 +36,10 @@ func TestFlagTSlice(s *testing.T) { t := core.T{T: s} fs := flag.NewFlagSet("", flag.PanicOnError) - fl := core.FlagTSlice(fs, "test", []int{42}, "", strconv.Atoi) + fl := core.FlagTSlice(fs, "test", []int{42}, "", strconv.Atoi, ",") t.AssertEqual([]int{42}, *fl) - t.AssertErrorIs(nil, fs.Parse([]string{"-test=1", "-test=2", "-test=42"})) - t.AssertEqual([]int{1, 2, 42}, *fl) + t.AssertErrorIs(nil, fs.Parse([]string{"-test=1", "-test=2", "-test=42,84"})) + t.AssertEqual([]int{1, 2, 42, 84}, *fl) } func TestFlagTSliceVar(s *testing.T) { @@ -47,8 +47,8 @@ func TestFlagTSliceVar(s *testing.T) { fs := flag.NewFlagSet("", flag.PanicOnError) var fl []int - core.FlagTSliceVar(fs, &fl, "test", []int{42}, "", strconv.Atoi) + core.FlagTSliceVar(fs, &fl, "test", []int{42}, "", strconv.Atoi, ",") t.AssertEqual([]int{42}, fl) - t.AssertErrorIs(nil, fs.Parse([]string{"-test=1", "-test=2", "-test=42"})) - t.AssertEqual([]int{1, 2, 42}, fl) + t.AssertErrorIs(nil, fs.Parse([]string{"-test=1", "-test=2", "-test=42,84"})) + t.AssertEqual([]int{1, 2, 42, 84}, fl) } |
