Merge pull request #514 from grubernaut/f-default-value-text

Add DefaultValue text for flags
This commit is contained in:
Dan Buch 2016-08-31 13:44:05 -04:00 committed by GitHub
commit c72728f424
5 changed files with 103 additions and 36 deletions

View File

@ -32,6 +32,7 @@ applications in an expressive way.
+ [Alternate Names](#alternate-names) + [Alternate Names](#alternate-names)
+ [Values from the Environment](#values-from-the-environment) + [Values from the Environment](#values-from-the-environment)
+ [Values from alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others) + [Values from alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others)
+ [Default Values for help output](#default-values-for-help-output)
* [Subcommands](#subcommands) * [Subcommands](#subcommands)
* [Subcommands categories](#subcommands-categories) * [Subcommands categories](#subcommands-categories)
* [Exit code](#exit-code) * [Exit code](#exit-code)
@ -589,6 +590,48 @@ func main() {
} }
``` ```
#### Default Values for help output
Sometimes it's useful to specify a flag's default help-text value within the flag declaration. This can be useful if the default value for a flag is a computed value. The default value can be set via the `DefaultText` struct field.
For example this:
<!-- {
"args": ["&#45;&#45;help"],
"output": "&#45;&#45;port value"
} -->
```go
package main
import (
"os"
"gopkg.in/urfave/cli.v2"
)
func main() {
app := &cli.App{
Flags: []cli.Flag{
&cli.IntFlag{
Name: "port",
Usage: "Use a randomized port",
Value: 0,
DefaultText: "random",
},
},
}
app.Run(os.Args)
}
```
Will result in help output like:
```
--port value Use a randomized port (default: random)
```
### Subcommands ### Subcommands
Subcommands can be defined for a more git-like command line app. Subcommands can be defined for a more git-like command line app.

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: %s)", 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']: