string_to_string.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package pflag
  2. import (
  3. "bytes"
  4. "encoding/csv"
  5. "fmt"
  6. "sort"
  7. "strings"
  8. )
  9. // -- stringToString Value
  10. type stringToStringValue struct {
  11. value *map[string]string
  12. changed bool
  13. }
  14. func newStringToStringValue(val map[string]string, p *map[string]string) *stringToStringValue {
  15. ssv := new(stringToStringValue)
  16. ssv.value = p
  17. *ssv.value = val
  18. return ssv
  19. }
  20. // Format: a=1,b=2
  21. func (s *stringToStringValue) Set(val string) error {
  22. var ss []string
  23. n := strings.Count(val, "=")
  24. switch n {
  25. case 0:
  26. return fmt.Errorf("%s must be formatted as key=value", val)
  27. case 1:
  28. ss = append(ss, strings.Trim(val, `"`))
  29. default:
  30. r := csv.NewReader(strings.NewReader(val))
  31. var err error
  32. ss, err = r.Read()
  33. if err != nil {
  34. return err
  35. }
  36. }
  37. out := make(map[string]string, len(ss))
  38. for _, pair := range ss {
  39. kv := strings.SplitN(pair, "=", 2)
  40. if len(kv) != 2 {
  41. return fmt.Errorf("%s must be formatted as key=value", pair)
  42. }
  43. out[kv[0]] = kv[1]
  44. }
  45. if !s.changed {
  46. *s.value = out
  47. } else {
  48. for k, v := range out {
  49. (*s.value)[k] = v
  50. }
  51. }
  52. s.changed = true
  53. return nil
  54. }
  55. func (s *stringToStringValue) Type() string {
  56. return "stringToString"
  57. }
  58. func (s *stringToStringValue) String() string {
  59. keys := make([]string, 0, len(*s.value))
  60. for k := range *s.value {
  61. keys = append(keys, k)
  62. }
  63. sort.Strings(keys)
  64. records := make([]string, 0, len(*s.value)>>1)
  65. for _, k := range keys {
  66. v := (*s.value)[k]
  67. records = append(records, k+"="+v)
  68. }
  69. var buf bytes.Buffer
  70. w := csv.NewWriter(&buf)
  71. if err := w.Write(records); err != nil {
  72. panic(err)
  73. }
  74. w.Flush()
  75. return "[" + strings.TrimSpace(buf.String()) + "]"
  76. }
  77. func stringToStringConv(val string) (interface{}, error) {
  78. val = strings.Trim(val, "[]")
  79. // An empty string would cause an empty map
  80. if len(val) == 0 {
  81. return map[string]string{}, nil
  82. }
  83. r := csv.NewReader(strings.NewReader(val))
  84. ss, err := r.Read()
  85. if err != nil {
  86. return nil, err
  87. }
  88. out := make(map[string]string, len(ss))
  89. for _, pair := range ss {
  90. kv := strings.SplitN(pair, "=", 2)
  91. if len(kv) != 2 {
  92. return nil, fmt.Errorf("%s must be formatted as key=value", pair)
  93. }
  94. out[kv[0]] = kv[1]
  95. }
  96. return out, nil
  97. }
  98. // GetStringToString return the map[string]string value of a flag with the given name
  99. func (f *FlagSet) GetStringToString(name string) (map[string]string, error) {
  100. val, err := f.getFlagType(name, "stringToString", stringToStringConv)
  101. if err != nil {
  102. return map[string]string{}, err
  103. }
  104. return val.(map[string]string), nil
  105. }
  106. // StringToStringVar defines a string flag with specified name, default value, and usage string.
  107. // The argument p points to a map[string]string variable in which to store the values of the multiple flags.
  108. // The value of each argument will not try to be separated by comma
  109. func (f *FlagSet) StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
  110. f.VarP(newStringToStringValue(value, p), name, "", usage)
  111. }
  112. // StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
  113. func (f *FlagSet) StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
  114. f.VarP(newStringToStringValue(value, p), name, shorthand, usage)
  115. }
  116. // StringToStringVar defines a string flag with specified name, default value, and usage string.
  117. // The argument p points to a map[string]string variable in which to store the value of the flag.
  118. // The value of each argument will not try to be separated by comma
  119. func StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
  120. CommandLine.VarP(newStringToStringValue(value, p), name, "", usage)
  121. }
  122. // StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
  123. func StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
  124. CommandLine.VarP(newStringToStringValue(value, p), name, shorthand, usage)
  125. }
  126. // StringToString defines a string flag with specified name, default value, and usage string.
  127. // The return value is the address of a map[string]string variable that stores the value of the flag.
  128. // The value of each argument will not try to be separated by comma
  129. func (f *FlagSet) StringToString(name string, value map[string]string, usage string) *map[string]string {
  130. p := map[string]string{}
  131. f.StringToStringVarP(&p, name, "", value, usage)
  132. return &p
  133. }
  134. // StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
  135. func (f *FlagSet) StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
  136. p := map[string]string{}
  137. f.StringToStringVarP(&p, name, shorthand, value, usage)
  138. return &p
  139. }
  140. // StringToString defines a string flag with specified name, default value, and usage string.
  141. // The return value is the address of a map[string]string variable that stores the value of the flag.
  142. // The value of each argument will not try to be separated by comma
  143. func StringToString(name string, value map[string]string, usage string) *map[string]string {
  144. return CommandLine.StringToStringP(name, "", value, usage)
  145. }
  146. // StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
  147. func StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
  148. return CommandLine.StringToStringP(name, shorthand, value, usage)
  149. }