Skip to content

Commit 1c62fb2

Browse files
authored
Merge pull request #431 from LeGEC/430-fix-usage-message-for-func-flags
fix usage message for func flags, fix arguments order
2 parents 8a6c85f + 1a4b5b2 commit 1c62fb2

File tree

5 files changed

+73
-11
lines changed

5 files changed

+73
-11
lines changed

‎bool_func.go‎

Lines changed: 2 additions & 2 deletions
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

@@ -35,6 +35,6 @@ func BoolFunc(name string, usage string, fn func(string) error) {
3535
}
3636

3737
// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash.
38-
func BoolFuncP(name, shorthand string, fn func(string) error, usage string) {
38+
func BoolFuncP(name, shorthand string, usage string, fn func(string) error) {
3939
CommandLine.BoolFuncP(name, shorthand, usage, fn)
4040
}

‎bool_func_test.go‎

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func TestBoolFuncCompat(t *testing.T) {
7575
args := []string{"--bflag", "--bflag=false", "--bflag=1", "--bflag=bar", "--bflag="}
7676

7777
// It turns out that, even though the function is called "BoolFunc",
78-
// the stanard flag package does not try to parse the value assigned to
78+
// the standard flag package does not try to parse the value assigned to
7979
// that cli flag as a boolean. The string provided on the command line is
8080
// passed as is to the callback.
8181
// e.g: with "--bflag=not_a_bool" on the command line, the FlagSet does not
@@ -106,7 +106,7 @@ func TestBoolFuncCompat(t *testing.T) {
106106
flagName := "bflag"
107107
args := []string{"--bflag", "--bflag=err", "--bflag=after"}
108108

109-
// test behavior of standard flag.Fset with an error triggere by the callback:
109+
// test behavior of standard flag.Fset with an error triggered by the callback:
110110
// (note: as can be seen in 'runCase()', if the callback sees "err" as a value
111111
// for the bool flag, it will return an error)
112112
stdFSet := flag.NewFlagSet("std test", flag.ContinueOnError)
@@ -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.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ func (f *FlagSet) FuncP(name string, shorthand string, usage string, fn func(str
2727
//
2828
// The callback function will be called every time "--{name}={value}" (or equivalent) is
2929
// parsed on the command line, with "{value}" as an argument.
30-
func Func(name string, fn func(string) error, usage string) {
30+
func Func(name string, usage string, fn func(string) error) {
3131
CommandLine.FuncP(name, "", usage, fn)
3232
}
3333

3434
// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash.
35-
func FuncP(name, shorthand string, fn func(string) error, usage string) {
35+
func FuncP(name, shorthand string, usage string, fn func(string) error) {
3636
CommandLine.FuncP(name, shorthand, usage, fn)
3737
}

‎func_test.go‎

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@ func TestFuncCompat(t *testing.T) {
112112
flagName := "fnflag"
113113
args := []string{"--fnflag", "before", "--fnflag", "err", "--fnflag", "after"}
114114

115-
// test behavior of standard flag.Fset with an error triggere by the callback:
115+
// test behavior of standard flag.Fset with an error triggered by the callback:
116116
// (note: as can be seen in 'runCase()', if the callback sees "err" as a value
117-
// for the bool flag, it will return an error)
117+
// for the flag, it will return an error)
118118
stdFSet := flag.NewFlagSet("std test", flag.ContinueOnError)
119119
stdFSet.SetOutput(io.Discard) // suppress output
120120

@@ -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)