Skip to content

Commit a958721

Browse files
Don't show empty slices as flag default values in help (#175)
1 parent 8662191 commit a958721

4 files changed

Lines changed: 49 additions & 17 deletions

File tree

command_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,8 @@ func TestHelp(t *testing.T) {
600600
cli.SubCommands(sub1, sub2),
601601
cli.Flag(new(bool), "delete", 'd', false, "Delete something"),
602602
cli.Flag(new(int), "count", cli.NoShortHand, -1, "Count something"),
603+
cli.Flag(new([]string), "things", cli.NoShortHand, nil, "Names of things"),
604+
cli.Flag(new([]string), "more", cli.NoShortHand, []string{"one", "two"}, "Names of things with a default"),
603605
},
604606
wantErr: false,
605607
},

go.sum

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,11 @@ go.followtheprocess.codes/hue v1.0.0 h1:0fYXAGR1o+w7Vja+Q+iVtqeEP3/CE6ET/pniyl8e
22
go.followtheprocess.codes/hue v1.0.0/go.mod h1:gSn5xK6KJapih+eFgQk3woo1qg3/rx9XSrAanUIuDr8=
33
go.followtheprocess.codes/snapshot v0.6.1 h1:cZkQtEjL21BSrHn98Lm0S4yTzcOje/K60Iog/u/A5tM=
44
go.followtheprocess.codes/snapshot v0.6.1/go.mod h1:CM2E92Ah/j0XL4Z2UyOl7GlSuD0ZLLl8rJCpFylKcIg=
5-
go.followtheprocess.codes/test v0.23.1 h1:VoucCC8qKb6tKnBOCRZ7Ln2Ex1oV+HMXHdZyJ6DURB8=
6-
go.followtheprocess.codes/test v0.23.1/go.mod h1:sL19ttHv+BSJSMtdPXTP05aWwl58ciap0SoLp1hucKk=
75
go.followtheprocess.codes/test v1.0.0 h1:5m2MPOQpohDC9pf5hgqpH+4ldJP5g+YFVdoGQY41aeU=
86
go.followtheprocess.codes/test v1.0.0/go.mod h1:e627pR8IhsTV/RfuP/WKYjyL0BmuIbmaw2iKlQBCWrY=
9-
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
10-
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
117
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
128
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
13-
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
14-
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
159
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
1610
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
17-
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
18-
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
11+
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
12+
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=

internal/flag/flag.go

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func New[T Flaggable](p *T, name string, short rune, value T, usage string) (Fla
107107

108108
// If the default value is not the zero value for the type, it is treated as
109109
// significant and shown to the user
110-
if !isZero(value) {
110+
if !isZeroIsh(value) {
111111
// \t so that defaults get aligned by tabwriter when the command
112112
// dumps the flags
113113
usage += fmt.Sprintf("\t[default: %v]", value)
@@ -905,8 +905,16 @@ func formatStringSlice(slice []string) string {
905905
return s.String()
906906
}
907907

908-
// isZero reports whether value is the zero value for it's type.
909-
func isZero[T Flaggable](value T) bool {
908+
// isZeroIsh reports whether value is the zero value (ish) for it's type.
909+
//
910+
// "ish" means that empty slices will return true from isZeroIsh despite their official
911+
// zero value being nil. The primary use of isZeroIsh is to determine whether or not
912+
// a default value is worth displaying to the user in the help text, and an empty slice
913+
// is probably not.
914+
func isZeroIsh[T Flaggable](value T) bool { //nolint:cyclop // Not much else we can do here
915+
// Note: all the slice values ([]T) are in their own separate branches because if you
916+
// combine them, the resulting value in the body of the case block is 'any' and
917+
// you cannot do len(any)
910918
switch typ := any(value).(type) {
911919
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64:
912920
return typ == 0
@@ -916,8 +924,34 @@ func isZero[T Flaggable](value T) bool {
916924
return typ == ""
917925
case bool:
918926
return !typ
919-
case []byte, net.IP, []int, []int8, []int16, []int32, []int64, []uint, []uint16, []uint32, []uint64, []float32, []float64, []string:
920-
return typ == nil
927+
case []byte:
928+
return len(typ) == 0
929+
case net.IP:
930+
return len(typ) == 0
931+
case []int:
932+
return len(typ) == 0
933+
case []int8:
934+
return len(typ) == 0
935+
case []int16:
936+
return len(typ) == 0
937+
case []int32:
938+
return len(typ) == 0
939+
case []int64:
940+
return len(typ) == 0
941+
case []uint:
942+
return len(typ) == 0
943+
case []uint16:
944+
return len(typ) == 0
945+
case []uint32:
946+
return len(typ) == 0
947+
case []uint64:
948+
return len(typ) == 0
949+
case []float32:
950+
return len(typ) == 0
951+
case []float64:
952+
return len(typ) == 0
953+
case []string:
954+
return len(typ) == 0
921955
case time.Time:
922956
var zero time.Time
923957
return typ.Equal(zero)

testdata/snapshots/TestHelp/with_subcommands_and_flags.snap.txt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ Commands:
1111

1212
Options:
1313

14-
N/A --count int Count something [default: -1]
15-
-d --delete bool Delete something
16-
-h --help bool Show help for test
17-
-V --version bool Show version info for test
14+
N/A --count int Count something [default: -1]
15+
-d --delete bool Delete something
16+
-h --help bool Show help for test
17+
N/A --more []string Names of things with a default [default: [one two]]
18+
N/A --things []string Names of things
19+
-V --version bool Show version info for test
1820

1921
Use "test [command] -h/--help" for more information about a command.

0 commit comments

Comments
 (0)