Add DefaultValue text for flags

Allows a user to override the default value of a flag in the displayed help output.

Ex:
```
cli.IntFlag{
	Name: "foo, f",
	DefaultText: "random foo",
	Value: "bar",
}
```

Running `(app.name) -h` will now yield:

```
--foo value     (default: "random foo")
```

Fixes: #504
This commit is contained in:
Jake Champlin 2016-08-28 03:14:39 -04:00
parent a095a5a896
commit e0556cf9e8
No known key found for this signature in database
GPG Key ID: DC31F41958EF4AC2
4 changed files with 60 additions and 36 deletions

View File

@ -730,7 +730,6 @@ func stringifyFlag(f Flag) string {
needsPlaceholder := false needsPlaceholder := false
defaultValueString := "" defaultValueString := ""
val := fv.FieldByName("Value") val := fv.FieldByName("Value")
if val.IsValid() { if val.IsValid() {
needsPlaceholder = val.Kind() != reflect.Bool needsPlaceholder = val.Kind() != reflect.Bool
defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface()) defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())
@ -740,6 +739,12 @@ func stringifyFlag(f Flag) string {
} }
} }
helpText := fv.FieldByName("DefaultText")
if helpText.IsValid() && helpText.String() != "" {
needsPlaceholder = val.Kind() != reflect.Bool
defaultValueString = fmt.Sprintf(" (default: %q)", helpText.String())
}
if defaultValueString == " (default: )" { if defaultValueString == " (default: )" {
defaultValueString = "" defaultValueString = ""
} }

View File

@ -16,6 +16,7 @@ type BoolFlag struct {
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value bool Value bool
DefaultText string
Destination *bool Destination *bool
} }
@ -59,6 +60,7 @@ type DurationFlag struct {
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value time.Duration Value time.Duration
DefaultText string
Destination *time.Duration Destination *time.Duration
} }
@ -102,6 +104,7 @@ type Float64Flag struct {
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value float64 Value float64
DefaultText string
Destination *float64 Destination *float64
} }
@ -139,12 +142,13 @@ func lookupFloat64(name string, set *flag.FlagSet) float64 {
// GenericFlag is a flag with type Generic // GenericFlag is a flag with type Generic
type GenericFlag struct { type GenericFlag struct {
Name string Name string
Aliases []string Aliases []string
Usage string Usage string
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value Generic Value Generic
DefaultText string
} }
// String returns a readable representation of this value // String returns a readable representation of this value
@ -187,6 +191,7 @@ type Int64Flag struct {
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value int64 Value int64
DefaultText string
Destination *int64 Destination *int64
} }
@ -230,6 +235,7 @@ type IntFlag struct {
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value int Value int
DefaultText string
Destination *int Destination *int
} }
@ -267,12 +273,13 @@ func lookupInt(name string, set *flag.FlagSet) int {
// IntSliceFlag is a flag with type *IntSlice // IntSliceFlag is a flag with type *IntSlice
type IntSliceFlag struct { type IntSliceFlag struct {
Name string Name string
Aliases []string Aliases []string
Usage string Usage string
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value *IntSlice Value *IntSlice
DefaultText string
} }
// String returns a readable representation of this value // String returns a readable representation of this value
@ -309,12 +316,13 @@ func lookupIntSlice(name string, set *flag.FlagSet) []int {
// Int64SliceFlag is a flag with type *Int64Slice // Int64SliceFlag is a flag with type *Int64Slice
type Int64SliceFlag struct { type Int64SliceFlag struct {
Name string Name string
Aliases []string Aliases []string
Usage string Usage string
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value *Int64Slice Value *Int64Slice
DefaultText string
} }
// String returns a readable representation of this value // String returns a readable representation of this value
@ -351,12 +359,13 @@ func lookupInt64Slice(name string, set *flag.FlagSet) []int64 {
// Float64SliceFlag is a flag with type *Float64Slice // Float64SliceFlag is a flag with type *Float64Slice
type Float64SliceFlag struct { type Float64SliceFlag struct {
Name string Name string
Aliases []string Aliases []string
Usage string Usage string
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value *Float64Slice Value *Float64Slice
DefaultText string
} }
// String returns a readable representation of this value // String returns a readable representation of this value
@ -399,6 +408,7 @@ type StringFlag struct {
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value string Value string
DefaultText string
Destination *string Destination *string
} }
@ -436,12 +446,13 @@ func lookupString(name string, set *flag.FlagSet) string {
// StringSliceFlag is a flag with type *StringSlice // StringSliceFlag is a flag with type *StringSlice
type StringSliceFlag struct { type StringSliceFlag struct {
Name string Name string
Aliases []string Aliases []string
Usage string Usage string
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value *StringSlice Value *StringSlice
DefaultText string
} }
// String returns a readable representation of this value // String returns a readable representation of this value
@ -484,6 +495,7 @@ type Uint64Flag struct {
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value uint64 Value uint64
DefaultText string
Destination *uint64 Destination *uint64
} }
@ -527,6 +539,7 @@ type UintFlag struct {
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value uint Value uint
DefaultText string
Destination *uint Destination *uint
} }

View File

@ -67,6 +67,16 @@ func TestStringFlagHelpOutput(t *testing.T) {
} }
} }
func TestStringFlagDefaultText(t *testing.T) {
flag := &StringFlag{Name: "foo", Aliases: nil, Usage: "amount of `foo` requested", Value: "none", DefaultText: "all of it"}
expected := "--foo foo\tamount of foo requested (default: \"all of it\")"
output := flag.String()
if output != expected {
t.Errorf("%q does not match %q", output, expected)
}
}
func TestStringFlagWithEnvVarHelpOutput(t *testing.T) { func TestStringFlagWithEnvVarHelpOutput(t *testing.T) {
os.Clearenv() os.Clearenv()
os.Setenv("APP_FOO", "derp") os.Setenv("APP_FOO", "derp")
@ -482,7 +492,6 @@ func TestFloat64FlagApply_SetsAllNames(t *testing.T) {
expect(t, v, float64(43.33333)) expect(t, v, float64(43.33333))
} }
var float64SliceFlagTests = []struct { var float64SliceFlagTests = []struct {
name string name string
aliases []string aliases []string
@ -523,8 +532,6 @@ func TestFloat64SliceFlagWithEnvVarHelpOutput(t *testing.T) {
} }
} }
var genericFlagTests = []struct { var genericFlagTests = []struct {
name string name string
value Generic value Generic
@ -1100,7 +1107,6 @@ func TestParseMultiFloat64FromEnvCascade(t *testing.T) {
a.Run([]string{"run"}) a.Run([]string{"run"})
} }
func TestParseMultiFloat64SliceFromEnv(t *testing.T) { func TestParseMultiFloat64SliceFromEnv(t *testing.T) {
os.Clearenv() os.Clearenv()
os.Setenv("APP_INTERVALS", "0.1,-10.5") os.Setenv("APP_INTERVALS", "0.1,-10.5")
@ -1141,7 +1147,6 @@ func TestParseMultiFloat64SliceFromEnvCascade(t *testing.T) {
}).Run([]string{"run"}) }).Run([]string{"run"})
} }
func TestParseMultiBool(t *testing.T) { func TestParseMultiBool(t *testing.T) {
a := App{ a := App{
Flags: []Flag{ Flags: []Flag{

View File

@ -145,6 +145,7 @@ def _write_cli_flag_types(outfile, types):
EnvVars []string EnvVars []string
Hidden bool Hidden bool
Value {type} Value {type}
DefaultText string
""".format(**typedef)) """.format(**typedef))
if typedef['dest']: if typedef['dest']: