Skip to content

Commit 4730aa0

Browse files
committed
fix help message for Func and BoolFunc flags #430
* have '.Type()' for boolfuncValue return "boolfunc" (dedicated value, which now makes it distinct from funcValue) * hide extra "(default )" by stating that "" should be treated as a zero value for a boolFlag note: - a boolfuncValue matches 'case boolFlag:', as it implements the boolFlag interface, - treating "" as a value which shouldn't trigger a "(default )" for a regular Bool flag does not look like a breaking change * hide extra "[=something]" for boolfuncValue * set default placeholder name for "boolfunc" and "func" flag types
1 parent f4c97c2 commit 4730aa0

File tree

4 files changed

+66
-4
lines changed

4 files changed

+66
-4
lines changed

bool_func.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ type boolfuncValue func(string) error
55

66
func (f boolfuncValue) Set(s string) error { return f(s) }
77

8-
func (f boolfuncValue) Type() string { return "func" }
8+
func (f boolfuncValue) Type() string { return "boolfunc" }
99

1010
func (f boolfuncValue) String() string { return "" } // same behavior as stdlib 'flag' package
1111

bool_func_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,33 @@ func TestBoolFuncCompat(t *testing.T) {
145145
}
146146
})
147147
}
148+
149+
func TestBoolFuncUsage(t *testing.T) {
150+
t.Run("regular func flag", func(t *testing.T) {
151+
// regular boolfunc flag:
152+
// expect to see '--flag1' followed by the usageMessage, and no mention of a default value
153+
fset := NewFlagSet("unittest", ContinueOnError)
154+
fset.BoolFunc("flag1", "usage message", func(s string) error { return nil })
155+
usage := fset.FlagUsagesWrapped(80)
156+
157+
usage = strings.TrimSpace(usage)
158+
expected := "--flag1 usage message"
159+
if usage != expected {
160+
t.Fatalf("unexpected generated usage message\n expected: %s\n got: %s", expected, usage)
161+
}
162+
})
163+
164+
t.Run("func flag with placeholder name", func(t *testing.T) {
165+
// func flag, with a placeholder name:
166+
// if usageMesage contains a placeholder, expect '--flag2 {placeholder}'; still expect no mention of a default value
167+
fset := NewFlagSet("unittest", ContinueOnError)
168+
fset.BoolFunc("flag2", "usage message with `name` placeholder", func(s string) error { return nil })
169+
usage := fset.FlagUsagesWrapped(80)
170+
171+
usage = strings.TrimSpace(usage)
172+
expected := "--flag2 name usage message with name placeholder"
173+
if usage != expected {
174+
t.Fatalf("unexpected generated usage message\n expected: %s\n got: %s", expected, usage)
175+
}
176+
})
177+
}

flag.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ func (f *FlagSet) PrintDefaults() {
549549
func (f *Flag) defaultIsZeroValue() bool {
550550
switch f.Value.(type) {
551551
case boolFlag:
552-
return f.DefValue == "false"
552+
return f.DefValue == "false" || f.DefValue == ""
553553
case *durationValue:
554554
// Beginning in Go 1.7, duration zero values are "0s"
555555
return f.DefValue == "0" || f.DefValue == "0s"
@@ -599,8 +599,10 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
599599

600600
name = flag.Value.Type()
601601
switch name {
602-
case "bool":
602+
case "bool", "boolfunc":
603603
name = ""
604+
case "func":
605+
name = "value"
604606
case "float64":
605607
name = "float"
606608
case "int64":
@@ -718,7 +720,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
718720
switch flag.Value.Type() {
719721
case "string":
720722
line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
721-
case "bool":
723+
case "bool", "boolfunc":
722724
if flag.NoOptDefVal != "true" {
723725
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
724726
}

func_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,33 @@ func TestFuncCompat(t *testing.T) {
151151
}
152152
})
153153
}
154+
155+
func TestFuncUsage(t *testing.T) {
156+
t.Run("regular func flag", func(t *testing.T) {
157+
// regular func flag:
158+
// expect to see '--flag1 value' followed by the usageMessage, and no mention of a default value
159+
fset := NewFlagSet("unittest", ContinueOnError)
160+
fset.Func("flag1", "usage message", func(s string) error { return nil })
161+
usage := fset.FlagUsagesWrapped(80)
162+
163+
usage = strings.TrimSpace(usage)
164+
expected := "--flag1 value usage message"
165+
if usage != expected {
166+
t.Fatalf("unexpected generated usage message\n expected: %s\n got: %s", expected, usage)
167+
}
168+
})
169+
170+
t.Run("func flag with placeholder name", func(t *testing.T) {
171+
// func flag, with a placeholder name:
172+
// if usageMesage contains a placeholder, expect that name; still expect no mention of a default value
173+
fset := NewFlagSet("unittest", ContinueOnError)
174+
fset.Func("flag2", "usage message with `name` placeholder", func(s string) error { return nil })
175+
usage := fset.FlagUsagesWrapped(80)
176+
177+
usage = strings.TrimSpace(usage)
178+
expected := "--flag2 name usage message with name placeholder"
179+
if usage != expected {
180+
t.Fatalf("unexpected generated usage message\n expected: %s\n got: %s", expected, usage)
181+
}
182+
})
183+
}

0 commit comments

Comments
 (0)