@@ -13,47 +13,35 @@ type Value interface {
13
13
flag.Getter
14
14
}
15
15
16
- // simple wrapper to intercept Value operations
17
- // to check for duplicates
18
- type valueWrapper struct {
19
- value Value
20
- count int
21
- onlyOnce bool
16
+ type boolFlag interface {
17
+ IsBoolFlag () bool
22
18
}
23
19
24
- func (v * valueWrapper ) String () string {
25
- if v .value == nil {
26
- return ""
27
- }
28
- return v .value .String ()
20
+ type fnValue struct {
21
+ fn func (string ) error
22
+ isBool bool
23
+ v Value
29
24
}
30
25
31
- func (v * valueWrapper ) Set (s string ) error {
32
- if v .count == 1 && v .onlyOnce {
33
- return fmt .Errorf ("cant duplicate this flag" )
26
+ func (f * fnValue ) Get () any { return f .v .Get () }
27
+ func (f * fnValue ) Set (s string ) error { return f .fn (s ) }
28
+ func (f * fnValue ) String () string {
29
+ if f .v == nil {
30
+ return ""
34
31
}
35
- v .count ++
36
- return v .value .Set (s )
37
- }
38
-
39
- func (v * valueWrapper ) Get () any {
40
- return v .value .Get ()
41
- }
42
-
43
- func (v * valueWrapper ) IsBoolFlag () bool {
44
- _ , ok := v .value .(* boolValue )
45
- return ok
32
+ return f .v .String ()
46
33
}
47
34
48
- func (v * valueWrapper ) Serialize () string {
49
- if s , ok := v . value .(Serializer ); ok {
35
+ func (f * fnValue ) Serialize () string {
36
+ if s , ok := f . v .(Serializer ); ok {
50
37
return s .Serialize ()
51
38
}
52
- return v . value .String ()
39
+ return f . v .String ()
53
40
}
54
41
55
- func (v * valueWrapper ) Count () int {
56
- if s , ok := v .value .(Countable ); ok {
42
+ func (f * fnValue ) IsBoolFlag () bool { return f .isBool }
43
+ func (f * fnValue ) Count () int {
44
+ if s , ok := f .v .(Countable ); ok {
57
45
return s .Count ()
58
46
}
59
47
return 0
@@ -105,7 +93,10 @@ type FlagBase[T any, C any, VC ValueCreator[T, C]] struct {
105
93
106
94
OnlyOnce bool // whether this flag can be duplicated on the command line
107
95
96
+ Validator func (T ) error // custom function to validate this flag value
97
+
108
98
// unexported fields for internal use
99
+ count int // number of times the flag has been set
109
100
hasBeenSet bool // whether the flag has been set from env or file
110
101
applied bool // whether the flag has been applied to a flag set already
111
102
creator VC // value creator for this flag type
@@ -160,15 +151,48 @@ func (f *FlagBase[T, C, V]) Apply(set *flag.FlagSet) error {
160
151
} else {
161
152
f .value = f .creator .Create (newVal , f .Destination , f .Config )
162
153
}
154
+
155
+ // Validate the given default or values set from external sources as well
156
+ if f .Validator != nil {
157
+ if v , ok := f .value .Get ().(T ); ! ok {
158
+ return & typeError [T ]{
159
+ other : f .value .Get (),
160
+ }
161
+ } else if err := f .Validator (v ); err != nil {
162
+ return err
163
+ }
164
+ }
163
165
}
164
166
165
- vw := & valueWrapper {
166
- value : f .value ,
167
- onlyOnce : f . OnlyOnce ,
167
+ isBool := false
168
+ if b , ok := f .value .( boolFlag ); ok && b . IsBoolFlag () {
169
+ isBool = true
168
170
}
169
171
170
172
for _ , name := range f .Names () {
171
- set .Var (vw , name , f .Usage )
173
+ set .Var (& fnValue {
174
+ fn : func (val string ) error {
175
+ if f .count == 1 && f .OnlyOnce {
176
+ return fmt .Errorf ("cant duplicate this flag" )
177
+ }
178
+ f .count ++
179
+ if err := f .value .Set (val ); err != nil {
180
+ return err
181
+ }
182
+ if f .Validator != nil {
183
+ if v , ok := f .value .Get ().(T ); ! ok {
184
+ return & typeError [T ]{
185
+ other : f .value .Get (),
186
+ }
187
+ } else if err := f .Validator (v ); err != nil {
188
+ return err
189
+ }
190
+ }
191
+ return nil
192
+ },
193
+ isBool : isBool ,
194
+ v : f .value ,
195
+ }, name , f .Usage )
172
196
}
173
197
174
198
f .applied = true
0 commit comments