Merge pull request #1078 from davidsbond/stringslice-destination
Allow specifying a StringSlice destination for StringSliceFlag
This commit is contained in:
commit
573004ad6a
@ -71,6 +71,7 @@ type StringSliceFlag struct {
|
|||||||
Value *StringSlice
|
Value *StringSlice
|
||||||
DefaultText string
|
DefaultText string
|
||||||
HasBeenSet bool
|
HasBeenSet bool
|
||||||
|
Destination *StringSlice
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSet returns whether or not the flag has been set through env or file
|
// IsSet returns whether or not the flag has been set through env or file
|
||||||
@ -117,13 +118,20 @@ func (f *StringSliceFlag) GetValue() string {
|
|||||||
func (f *StringSliceFlag) Apply(set *flag.FlagSet) error {
|
func (f *StringSliceFlag) Apply(set *flag.FlagSet) error {
|
||||||
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
|
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
|
||||||
f.Value = &StringSlice{}
|
f.Value = &StringSlice{}
|
||||||
|
destination := f.Value
|
||||||
|
if f.Destination != nil {
|
||||||
|
destination = f.Destination
|
||||||
|
}
|
||||||
|
|
||||||
for _, s := range strings.Split(val, ",") {
|
for _, s := range strings.Split(val, ",") {
|
||||||
if err := f.Value.Set(strings.TrimSpace(s)); err != nil {
|
if err := destination.Set(strings.TrimSpace(s)); err != nil {
|
||||||
return fmt.Errorf("could not parse %q as string value for flag %s: %s", val, f.Name, err)
|
return fmt.Errorf("could not parse %q as string value for flag %s: %s", val, f.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set this to false so that we reset the slice if we then set values from
|
||||||
|
// flags that have already been set by the environment.
|
||||||
|
destination.hasBeenSet = false
|
||||||
f.HasBeenSet = true
|
f.HasBeenSet = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,6 +139,12 @@ func (f *StringSliceFlag) Apply(set *flag.FlagSet) error {
|
|||||||
if f.Value == nil {
|
if f.Value == nil {
|
||||||
f.Value = &StringSlice{}
|
f.Value = &StringSlice{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if f.Destination != nil {
|
||||||
|
set.Var(f.Destination, name, f.Usage)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
set.Var(f.Value, name, f.Usage)
|
set.Var(f.Value, name, f.Usage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
64
flag_test.go
64
flag_test.go
@ -59,7 +59,7 @@ func TestFlagsFromEnv(t *testing.T) {
|
|||||||
|
|
||||||
newSetStringSlice := func(defaults ...string) StringSlice {
|
newSetStringSlice := func(defaults ...string) StringSlice {
|
||||||
s := NewStringSlice(defaults...)
|
s := NewStringSlice(defaults...)
|
||||||
s.hasBeenSet = true
|
s.hasBeenSet = false
|
||||||
return *s
|
return *s
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -917,6 +917,47 @@ func TestParseMultiStringSliceWithDefaults(t *testing.T) {
|
|||||||
}).Run([]string{"run", "-s", "10", "-s", "20"})
|
}).Run([]string{"run", "-s", "10", "-s", "20"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseMultiStringSliceWithDestination(t *testing.T) {
|
||||||
|
dest := &StringSlice{}
|
||||||
|
_ = (&App{
|
||||||
|
Flags: []Flag{
|
||||||
|
&StringSliceFlag{Name: "serve", Aliases: []string{"s"}, Destination: dest},
|
||||||
|
},
|
||||||
|
Action: func(ctx *Context) error {
|
||||||
|
expected := []string{"10", "20"}
|
||||||
|
if !reflect.DeepEqual(dest.slice, expected) {
|
||||||
|
t.Errorf("main name not set: %v != %v", expected, ctx.StringSlice("serve"))
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(dest.slice, expected) {
|
||||||
|
t.Errorf("short name not set: %v != %v", expected, ctx.StringSlice("s"))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}).Run([]string{"run", "-s", "10", "-s", "20"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseMultiStringSliceWithDestinationAndEnv(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
_ = os.Setenv("APP_INTERVALS", "20,30,40")
|
||||||
|
|
||||||
|
dest := &StringSlice{}
|
||||||
|
_ = (&App{
|
||||||
|
Flags: []Flag{
|
||||||
|
&StringSliceFlag{Name: "serve", Aliases: []string{"s"}, Destination: dest, EnvVars: []string{"APP_INTERVALS"}},
|
||||||
|
},
|
||||||
|
Action: func(ctx *Context) error {
|
||||||
|
expected := []string{"10", "20"}
|
||||||
|
if !reflect.DeepEqual(dest.slice, expected) {
|
||||||
|
t.Errorf("main name not set: %v != %v", expected, ctx.StringSlice("serve"))
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(dest.slice, expected) {
|
||||||
|
t.Errorf("short name not set: %v != %v", expected, ctx.StringSlice("s"))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}).Run([]string{"run", "-s", "10", "-s", "20"})
|
||||||
|
}
|
||||||
|
|
||||||
func TestParseMultiStringSliceWithDefaultsUnset(t *testing.T) {
|
func TestParseMultiStringSliceWithDefaultsUnset(t *testing.T) {
|
||||||
_ = (&App{
|
_ = (&App{
|
||||||
Flags: []Flag{
|
Flags: []Flag{
|
||||||
@ -1014,6 +1055,27 @@ func TestParseMultiStringSliceFromEnvCascadeWithDefaults(t *testing.T) {
|
|||||||
}).Run([]string{"run"})
|
}).Run([]string{"run"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseMultiStringSliceFromEnvWithDestination(t *testing.T) {
|
||||||
|
os.Clearenv()
|
||||||
|
_ = os.Setenv("APP_INTERVALS", "20,30,40")
|
||||||
|
|
||||||
|
dest := &StringSlice{}
|
||||||
|
_ = (&App{
|
||||||
|
Flags: []Flag{
|
||||||
|
&StringSliceFlag{Name: "intervals", Aliases: []string{"i"}, Destination: dest, EnvVars: []string{"APP_INTERVALS"}},
|
||||||
|
},
|
||||||
|
Action: func(ctx *Context) error {
|
||||||
|
if !reflect.DeepEqual(dest.slice, []string{"20", "30", "40"}) {
|
||||||
|
t.Errorf("main name not set from env")
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(dest.slice, []string{"20", "30", "40"}) {
|
||||||
|
t.Errorf("short name not set from env")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}).Run([]string{"run"})
|
||||||
|
}
|
||||||
|
|
||||||
func TestParseMultiInt(t *testing.T) {
|
func TestParseMultiInt(t *testing.T) {
|
||||||
_ = (&App{
|
_ = (&App{
|
||||||
Flags: []Flag{
|
Flags: []Flag{
|
||||||
|
Loading…
Reference in New Issue
Block a user