aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrégoire Duchêne <gduchene@awhk.org>2022-12-03 10:37:56 +0000
committerGrégoire Duchêne <gduchene@awhk.org>2022-12-03 10:37:56 +0000
commit66757999fb5aa554d1277a21ba59a5f2e6ca0271 (patch)
tree0400dc36b48418cc193115dcc8e92a6b66807b34
parent2336eb2530e1f6df6817f309e0ea2a4102056967 (diff)
Have FlagTSlice{,Var} take an optional separator
This separator, when passed, allows for multiple values to be passed at a time.
-rw-r--r--flag.go46
-rw-r--r--flag_test.go12
2 files changed, 38 insertions, 20 deletions
diff --git a/flag.go b/flag.go
index 2a6e22d..9200b6f 100644
--- a/flag.go
+++ b/flag.go
@@ -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)
}