1package pflag 2 3import ( 4 "bytes" 5 "encoding/csv" 6 "strings" 7) 8 9// -- stringSlice Value 10type stringSliceValue struct { 11 value *[]string 12 changed bool 13} 14 15func newStringSliceValue(val []string, p *[]string) *stringSliceValue { 16 ssv := new(stringSliceValue) 17 ssv.value = p 18 *ssv.value = val 19 return ssv 20} 21 22func readAsCSV(val string) ([]string, error) { 23 if val == "" { 24 return []string{}, nil 25 } 26 stringReader := strings.NewReader(val) 27 csvReader := csv.NewReader(stringReader) 28 return csvReader.Read() 29} 30 31func writeAsCSV(vals []string) (string, error) { 32 b := &bytes.Buffer{} 33 w := csv.NewWriter(b) 34 err := w.Write(vals) 35 if err != nil { 36 return "", err 37 } 38 w.Flush() 39 return strings.TrimSuffix(b.String(), "\n"), nil 40} 41 42func (s *stringSliceValue) Set(val string) error { 43 v, err := readAsCSV(val) 44 if err != nil { 45 return err 46 } 47 if !s.changed { 48 *s.value = v 49 } else { 50 *s.value = append(*s.value, v...) 51 } 52 s.changed = true 53 return nil 54} 55 56func (s *stringSliceValue) Type() string { 57 return "stringSlice" 58} 59 60func (s *stringSliceValue) String() string { 61 str, _ := writeAsCSV(*s.value) 62 return "[" + str + "]" 63} 64 65func (s *stringSliceValue) Append(val string) error { 66 *s.value = append(*s.value, val) 67 return nil 68} 69 70func (s *stringSliceValue) Replace(val []string) error { 71 *s.value = val 72 return nil 73} 74 75func (s *stringSliceValue) GetSlice() []string { 76 return *s.value 77} 78 79func stringSliceConv(sval string) (interface{}, error) { 80 sval = sval[1 : len(sval)-1] 81 // An empty string would cause a slice with one (empty) string 82 if len(sval) == 0 { 83 return []string{}, nil 84 } 85 return readAsCSV(sval) 86} 87 88// GetStringSlice return the []string value of a flag with the given name 89func (f *FlagSet) GetStringSlice(name string) ([]string, error) { 90 val, err := f.getFlagType(name, "stringSlice", stringSliceConv) 91 if err != nil { 92 return []string{}, err 93 } 94 return val.([]string), nil 95} 96 97// StringSliceVar defines a string flag with specified name, default value, and usage string. 98// The argument p points to a []string variable in which to store the value of the flag. 99// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. 100// For example: 101// --ss="v1,v2" --ss="v3" 102// will result in 103// []string{"v1", "v2", "v3"} 104func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) { 105 f.VarP(newStringSliceValue(value, p), name, "", usage) 106} 107 108// StringSliceVarP is like StringSliceVar, but accepts a shorthand letter that can be used after a single dash. 109func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) { 110 f.VarP(newStringSliceValue(value, p), name, shorthand, usage) 111} 112 113// StringSliceVar defines a string flag with specified name, default value, and usage string. 114// The argument p points to a []string variable in which to store the value of the flag. 115// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. 116// For example: 117// --ss="v1,v2" --ss="v3" 118// will result in 119// []string{"v1", "v2", "v3"} 120func StringSliceVar(p *[]string, name string, value []string, usage string) { 121 CommandLine.VarP(newStringSliceValue(value, p), name, "", usage) 122} 123 124// StringSliceVarP is like StringSliceVar, but accepts a shorthand letter that can be used after a single dash. 125func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) { 126 CommandLine.VarP(newStringSliceValue(value, p), name, shorthand, usage) 127} 128 129// StringSlice defines a string flag with specified name, default value, and usage string. 130// The return value is the address of a []string variable that stores the value of the flag. 131// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. 132// For example: 133// --ss="v1,v2" --ss="v3" 134// will result in 135// []string{"v1", "v2", "v3"} 136func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string { 137 p := []string{} 138 f.StringSliceVarP(&p, name, "", value, usage) 139 return &p 140} 141 142// StringSliceP is like StringSlice, but accepts a shorthand letter that can be used after a single dash. 143func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage string) *[]string { 144 p := []string{} 145 f.StringSliceVarP(&p, name, shorthand, value, usage) 146 return &p 147} 148 149// StringSlice defines a string flag with specified name, default value, and usage string. 150// The return value is the address of a []string variable that stores the value of the flag. 151// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. 152// For example: 153// --ss="v1,v2" --ss="v3" 154// will result in 155// []string{"v1", "v2", "v3"} 156func StringSlice(name string, value []string, usage string) *[]string { 157 return CommandLine.StringSliceP(name, "", value, usage) 158} 159 160// StringSliceP is like StringSlice, but accepts a shorthand letter that can be used after a single dash. 161func StringSliceP(name, shorthand string, value []string, usage string) *[]string { 162 return CommandLine.StringSliceP(name, shorthand, value, usage) 163} 164