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