Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Flag parameter 'ShowZeroValue' to show zero value in usage message #156

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ type Flag struct {
Hidden bool // used by cobra.Command to allow flags to be hidden from help/usage text
ShorthandDeprecated string // If the shorthand of this flag is deprecated, this string is the new or now thing to use
Annotations map[string][]string // used by cobra.Command bash autocomple code
ShowZeroValue bool // ShowZeroValue is used to indicate, if user wants to show zero value in help/usage messages.
}

// Value is the interface to the dynamic value stored in a flag.
Expand Down Expand Up @@ -693,7 +694,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
}

line += usage
if !flag.defaultIsZeroValue() {
if flag.ShowZeroValue || !flag.defaultIsZeroValue() {
if flag.Value.Type() == "string" {
line += fmt.Sprintf(" (default %q)", flag.DefValue)
} else {
Expand Down
102 changes: 102 additions & 0 deletions flag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,108 @@ func TestPrintDefaults(t *testing.T) {
}
}

const defaultOutputWithZeroValue = ` --A for bootstrapping, allow 'any' type
--Alongflagname disable bounds checking (default false)
-C, --CCC a boolean defaulting to true (default true)
--D path set relative path for local imports
--DD path set relative path for local imports (default "")
-E, --EEE num[=1234] a num with NoOptDefVal (default 4321)
--F number a non-zero number (default 2.7)
--G float a float that defaults to zero
--GG float a float that defaults to zero (default 0)
--IP ip IP address with no default
--IPMask ipMask Netmask address with no default
--IPNet ipNet IP network with no default
--Ints ints int slice with zero default
--Ints2 ints int slice with zero default (default [])
--N int a non-zero int (default 27)
--ND1 string[="bar"] a string with NoOptDefVal (default "foo")
--ND2 num[=4321] a num with NoOptDefVal (default 1234)
--ND3 int[=9876] a zero default value with NoOptDefVal
--ND4 int[=6543] show zero default value with NoOptDefVal (default 0)
--StringArray stringArray string array with zero default
--StringArray2 stringArray string array with zero default (default [])
--StringSlice strings string slice with zero default
--StringSlice2 strings string slice with zero default (default [])
--Z int an int that defaults to zero
--ZZ int an int that defaults to zero (default 0)
--custom custom custom Value implementation
--customP custom a VarP with default (default 10)
--customPP custom a VarP showing zero value default (default 0)
--maxT timeout set timeout for dial
--maxTT timeout set timeout for dial (default 0s)
-v, --verbose count verbosity
-V, --verbose2 count verbosity (default 0)
`

func TestPrintDefaultsWithZeroValue(t *testing.T) {
fs := NewFlagSet("print defaults test", ContinueOnError)
var buf bytes.Buffer
fs.SetOutput(&buf)
fs.Bool("A", false, "for bootstrapping, allow 'any' type")
fs.Bool("Alongflagname", false, "disable bounds checking")
fs.Lookup("Alongflagname").ShowZeroValue = true
fs.BoolP("CCC", "C", true, "a boolean defaulting to true")
fs.String("D", "", "set relative `path` for local imports")
fs.String("DD", "", "set relative `path` for local imports")
fs.Lookup("DD").ShowZeroValue = true
fs.Float64("F", 2.7, "a non-zero `number`")
fs.Float64("G", 0, "a float that defaults to zero")
fs.Float64("GG", 0, "a float that defaults to zero")
fs.Lookup("GG").ShowZeroValue = true
fs.Int("N", 27, "a non-zero int")
fs.IntSlice("Ints", []int{}, "int slice with zero default")
fs.IntSlice("Ints2", []int{}, "int slice with zero default")
fs.Lookup("Ints2").ShowZeroValue = true
fs.IP("IP", nil, "IP address with no default")
fs.IPMask("IPMask", nil, "Netmask address with no default")
fs.IPNet("IPNet", net.IPNet{}, "IP network with no default")
fs.Int("Z", 0, "an int that defaults to zero")
fs.Int("ZZ", 0, "an int that defaults to zero")
fs.Lookup("ZZ").ShowZeroValue = true
fs.Duration("maxT", 0, "set `timeout` for dial")
fs.Duration("maxTT", 0, "set `timeout` for dial")
fs.Lookup("maxTT").ShowZeroValue = true
fs.String("ND1", "foo", "a string with NoOptDefVal")
fs.Lookup("ND1").NoOptDefVal = "bar"
fs.Int("ND2", 1234, "a `num` with NoOptDefVal")
fs.Lookup("ND2").NoOptDefVal = "4321"
fs.Int("ND3", 0, "a zero default value with NoOptDefVal")
fs.Lookup("ND3").NoOptDefVal = "9876"
fs.Int("ND4", 0, "show zero default value with NoOptDefVal")
fs.Lookup("ND4").NoOptDefVal = "6543"
fs.Lookup("ND4").ShowZeroValue = true
fs.IntP("EEE", "E", 4321, "a `num` with NoOptDefVal")
fs.ShorthandLookup("E").NoOptDefVal = "1234"
fs.StringSlice("StringSlice", []string{}, "string slice with zero default")
fs.StringSlice("StringSlice2", []string{}, "string slice with zero default")
fs.Lookup("StringSlice2").ShowZeroValue = true
fs.StringArray("StringArray", []string{}, "string array with zero default")
fs.StringArray("StringArray2", []string{}, "string array with zero default")
fs.Lookup("StringArray2").ShowZeroValue = true
fs.CountP("verbose", "v", "verbosity")
fs.CountP("verbose2", "V", "verbosity")
fs.Lookup("verbose2").ShowZeroValue = true

var cv customValue
fs.Var(&cv, "custom", "custom Value implementation")

cv2 := customValue(10)
fs.VarP(&cv2, "customP", "", "a VarP with default")

cv3 := customValue(0)
fs.VarP(&cv3, "customPP", "", "a VarP showing zero value default")
fs.Lookup("customPP").ShowZeroValue = true

fs.PrintDefaults()
got := buf.String()
if got != defaultOutputWithZeroValue {
fmt.Println("\n" + got)
fmt.Println("\n" + defaultOutputWithZeroValue)
t.Errorf("got %q want %q\n", got, defaultOutputWithZeroValue)
}
}

func TestVisitAllFlagOrder(t *testing.T) {
fs := NewFlagSet("TestVisitAllFlagOrder", ContinueOnError)
fs.SortFlags = false
Expand Down