string_slice.go (5171B)
1 package pflag 2 3 import ( 4 "bytes" 5 "encoding/csv" 6 "strings" 7 ) 8 9 // -- stringSlice Value 10 type stringSliceValue struct { 11 value *[]string 12 changed bool 13 } 14 15 func newStringSliceValue(val []string, p *[]string) *stringSliceValue { 16 ssv := new(stringSliceValue) 17 ssv.value = p 18 *ssv.value = val 19 return ssv 20 } 21 22 func 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 31 func 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 42 func (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 56 func (s *stringSliceValue) Type() string { 57 return "stringSlice" 58 } 59 60 func (s *stringSliceValue) String() string { 61 str, _ := writeAsCSV(*s.value) 62 return "[" + str + "]" 63 } 64 65 func (s *stringSliceValue) Append(val string) error { 66 *s.value = append(*s.value, val) 67 return nil 68 } 69 70 func (s *stringSliceValue) Replace(val []string) error { 71 *s.value = val 72 return nil 73 } 74 75 func (s *stringSliceValue) GetSlice() []string { 76 return *s.value 77 } 78 79 func 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 89 func (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"} 104 func (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. 109 func (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"} 120 func 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. 125 func 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"} 136 func (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. 143 func (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"} 156 func 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. 161 func StringSliceP(name, shorthand string, value []string, usage string) *[]string { 162 return CommandLine.StringSliceP(name, shorthand, value, usage) 163 }