1 package cli
2
3 import (
4 "encoding/json"
5 "flag"
6 "fmt"
7 "strconv"
8 "strings"
9 )
10
11
12 type UintSlice struct {
13 slice []uint
14 separator separatorSpec
15 hasBeenSet bool
16 }
17
18
19 func NewUintSlice(defaults ...uint) *UintSlice {
20 return &UintSlice{slice: append([]uint{}, defaults...)}
21 }
22
23
24 func (i *UintSlice) clone() *UintSlice {
25 n := &UintSlice{
26 slice: make([]uint, len(i.slice)),
27 hasBeenSet: i.hasBeenSet,
28 }
29 copy(n.slice, i.slice)
30 return n
31 }
32
33
34
35 func (i *UintSlice) SetUint(value uint) {
36 if !i.hasBeenSet {
37 i.slice = []uint{}
38 i.hasBeenSet = true
39 }
40
41 i.slice = append(i.slice, value)
42 }
43
44
45 func (i *UintSlice) Set(value string) error {
46 if !i.hasBeenSet {
47 i.slice = []uint{}
48 i.hasBeenSet = true
49 }
50
51 if strings.HasPrefix(value, slPfx) {
52
53 _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &i.slice)
54 i.hasBeenSet = true
55 return nil
56 }
57
58 for _, s := range i.separator.flagSplitMultiValues(value) {
59 tmp, err := strconv.ParseUint(strings.TrimSpace(s), 0, 32)
60 if err != nil {
61 return err
62 }
63
64 i.slice = append(i.slice, uint(tmp))
65 }
66
67 return nil
68 }
69
70 func (i *UintSlice) WithSeparatorSpec(spec separatorSpec) {
71 i.separator = spec
72 }
73
74
75 func (i *UintSlice) String() string {
76 v := i.slice
77 if v == nil {
78
79 v = make([]uint, 0)
80 }
81 str := fmt.Sprintf("%d", v)
82 str = strings.Replace(str, " ", ", ", -1)
83 str = strings.Replace(str, "[", "{", -1)
84 str = strings.Replace(str, "]", "}", -1)
85 return fmt.Sprintf("[]uint%s", str)
86 }
87
88
89 func (i *UintSlice) Serialize() string {
90 jsonBytes, _ := json.Marshal(i.slice)
91 return fmt.Sprintf("%s%s", slPfx, string(jsonBytes))
92 }
93
94
95 func (i *UintSlice) Value() []uint {
96 return i.slice
97 }
98
99
100 func (i *UintSlice) Get() interface{} {
101 return *i
102 }
103
104
105
106 func (f *UintSliceFlag) String() string {
107 return FlagStringer(f)
108 }
109
110
111 func (f *UintSliceFlag) TakesValue() bool {
112 return true
113 }
114
115
116 func (f *UintSliceFlag) GetUsage() string {
117 return f.Usage
118 }
119
120
121 func (f *UintSliceFlag) GetCategory() string {
122 return f.Category
123 }
124
125
126
127 func (f *UintSliceFlag) GetValue() string {
128 var defaultVals []string
129 if f.Value != nil && len(f.Value.Value()) > 0 {
130 for _, i := range f.Value.Value() {
131 defaultVals = append(defaultVals, strconv.FormatUint(uint64(i), 10))
132 }
133 }
134 return strings.Join(defaultVals, ", ")
135 }
136
137
138 func (f *UintSliceFlag) GetDefaultText() string {
139 if f.DefaultText != "" {
140 return f.DefaultText
141 }
142 return f.GetValue()
143 }
144
145
146 func (f *UintSliceFlag) GetEnvVars() []string {
147 return f.EnvVars
148 }
149
150
151 func (f *UintSliceFlag) IsSliceFlag() bool {
152 return true
153 }
154
155
156 func (f *UintSliceFlag) Apply(set *flag.FlagSet) error {
157
158 if f.Destination != nil && f.Value != nil {
159 f.Destination.slice = make([]uint, len(f.Value.slice))
160 copy(f.Destination.slice, f.Value.slice)
161 }
162
163
164 var setValue *UintSlice
165 switch {
166 case f.Destination != nil:
167 setValue = f.Destination
168 case f.Value != nil:
169 setValue = f.Value.clone()
170 default:
171 setValue = new(UintSlice)
172 setValue.WithSeparatorSpec(f.separator)
173 }
174
175 if val, source, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok && val != "" {
176 for _, s := range f.separator.flagSplitMultiValues(val) {
177 if err := setValue.Set(strings.TrimSpace(s)); err != nil {
178 return fmt.Errorf("could not parse %q as uint slice value from %s for flag %s: %s", val, source, f.Name, err)
179 }
180 }
181
182
183
184 setValue.hasBeenSet = false
185 f.HasBeenSet = true
186 }
187
188 for _, name := range f.Names() {
189 set.Var(setValue, name, f.Usage)
190 }
191
192 return nil
193 }
194
195 func (f *UintSliceFlag) WithSeparatorSpec(spec separatorSpec) {
196 f.separator = spec
197 }
198
199
200 func (f *UintSliceFlag) Get(ctx *Context) []uint {
201 return ctx.UintSlice(f.Name)
202 }
203
204
205 func (f *UintSliceFlag) RunAction(c *Context) error {
206 if f.Action != nil {
207 return f.Action(c, c.UintSlice(f.Name))
208 }
209
210 return nil
211 }
212
213
214
215 func (cCtx *Context) UintSlice(name string) []uint {
216 if fs := cCtx.lookupFlagSet(name); fs != nil {
217 return lookupUintSlice(name, fs)
218 }
219 return nil
220 }
221
222 func lookupUintSlice(name string, set *flag.FlagSet) []uint {
223 f := set.Lookup(name)
224 if f != nil {
225 if slice, ok := unwrapFlagValue(f.Value).(*UintSlice); ok {
226 return slice.Value()
227 }
228 }
229 return nil
230 }
231
View as plain text