string_slice.go raw

   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  }
 164