In the standard flag package the flag.boolValue interface with its special IsBoolFlag() bool method is honored by the parser and allows creating flag.Value types that don't require an argument.
In pflag creating such a flag is only possible by overwriting the pflag.Flag's NoOptDefVal field with "true" or an equivalent (see strconv.ParseBool). The behavior of custom Value types that also implement IsBoolFlag() bool (hence are flag.boolValue or pflag.boolValue) is not compatible to the flag package, since passing no argument for the flag results in an error.
This snippet demonstrates it:
package main
import (
"flag"
"log"
"strconv"
"github.com/spf13/pflag"
)
/* straight from bool.go */
// -- bool Value
type boolValue bool
func newBoolValue(val bool, p *bool) *boolValue {
*p = val
return (*boolValue)(p)
}
func (b *boolValue) Set(s string) error {
v, err := strconv.ParseBool(s)
*b = boolValue(v)
return err
}
func (b *boolValue) Type() string {
return "bool"
}
func (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) }
func (b *boolValue) IsBoolFlag() bool { return true }
func main() {
var flagValue, pflagValue, pflagValue2 bool
flagSet := flag.NewFlagSet("flag", flag.ContinueOnError)
flagSet.Var(newBoolValue(false, &flagValue), "bool", "may omit argument")
pflagSet := pflag.NewFlagSet("pflag", pflag.ContinueOnError)
pflagSet.Var(newBoolValue(false, &pflagValue), "bool", "can't omit argument")
boolFlag := pflagSet.VarPF(newBoolValue(false, &pflagValue2), "bool2", "", "has default argument if none exists")
boolFlag.NoOptDefVal = "true"
fErr := flagSet.Parse([]string{"--bool"})
pfErr := pflagSet.Parse([]string{"--bool2", "--bool"})
if (fErr == nil) != (pfErr == nil) {
log.Println("flag and pflag handle boolValue differently")
}
if !pflagValue && pflagValue2 {
log.Println("have to modify pflag.Flag value to get same behavior as with flag")
}
}
Is this an aspect that is supposed to be compatible to flag?
I can understand that it makes sense to place the possibility to omit an argument to the Flag type and not the Value type.
But I also think it's good if I can specify that my Value type can be set without a value.
If this should be "fixed", I'd be happy to help.
In the standard
flagpackage theflag.boolValueinterface with its specialIsBoolFlag() boolmethod is honored by the parser and allows creatingflag.Valuetypes that don't require an argument.In
pflagcreating such a flag is only possible by overwriting thepflag.Flag'sNoOptDefValfield with"true"or an equivalent (seestrconv.ParseBool). The behavior of customValuetypes that also implementIsBoolFlag() bool(hence areflag.boolValueorpflag.boolValue) is not compatible to theflagpackage, since passing no argument for the flag results in an error.This snippet demonstrates it:
Is this an aspect that is supposed to be compatible to
flag?I can understand that it makes sense to place the possibility to omit an argument to the
Flagtype and not theValuetype.But I also think it's good if I can specify that my
Valuetype can be set without a value.If this should be "fixed", I'd be happy to help.