pflag
pflag copied to clipboard
Value's that implement IsBoolFlag() always show a default value
I've implemented a custom Value
type for managing generic data. Everything works as it should, but the flags always show a default in their usage string regardless of whether they have a zero value:
type Value struct {
data interface{}
dataType string
}
func (v *Value) String() string {
return cast.ToString(v.Get())
}
func (v *Value) Get() interface{} {
return v.data
}
func (v *Value) Set(data string) error {
// validates, casts, and sets v.data using v.Type()
}
func (v *Value) Type() string {
return v.dataType
}
func (v *Value) IsBoolFlag() bool {
return v.Type() == "bool"
}
func main() {
value := &Value{
data: "",
dataType: "string",
}
pflag.Var(value, "project-name", "Some usage text")
pflag.Parse()
// Prints:
// --project-name string Some usage text (default "")
pflag.Usage()
flag := pflag.Lookup("project-name")
// Prints:
// default: '', isZero: false
fmt.Printf("default: %q, isZero: %v", flag.DefValue, flag.defaultIsZeroValue())
}
The issue seems to be caused here - by checking for whether the value implements the boolFlag interface (rather than the return value of IsBoolFlag()
):
https://github.com/spf13/pflag/blob/d5e0c0615acee7028e1e2740a11102313be88de1/flag.go#L536-L541
Seems like the fix would be to move the boolFlag check prior to the switch statement and have it actually call IsBoolFlag()
, like so:
if bf, ok := f.Value.(boolFlag); ok && bf.IsBoolFlag() {
return f.DefValue == "false"
}
switch f.Value.(type) { ... }
Then custom values would make it through to the default case in the switch statement.