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