Merge pull request #514 from grubernaut/f-default-value-text
Add DefaultValue text for flags
This commit is contained in:
commit
c72728f424
43
README.md
43
README.md
@ -32,6 +32,7 @@ applications in an expressive way.
|
||||
+ [Alternate Names](#alternate-names)
|
||||
+ [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)
|
||||
+ [Default Values for help output](#default-values-for-help-output)
|
||||
* [Subcommands](#subcommands)
|
||||
* [Subcommands categories](#subcommands-categories)
|
||||
* [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": ["--help"],
|
||||
"output": "--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 can be defined for a more git-like command line app.
|
||||
|
7
flag.go
7
flag.go
@ -730,7 +730,6 @@ func stringifyFlag(f Flag) string {
|
||||
needsPlaceholder := false
|
||||
defaultValueString := ""
|
||||
val := fv.FieldByName("Value")
|
||||
|
||||
if val.IsValid() {
|
||||
needsPlaceholder = val.Kind() != reflect.Bool
|
||||
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: )" {
|
||||
defaultValueString = ""
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ type BoolFlag struct {
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value bool
|
||||
DefaultText string
|
||||
Destination *bool
|
||||
}
|
||||
|
||||
@ -59,6 +60,7 @@ type DurationFlag struct {
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value time.Duration
|
||||
DefaultText string
|
||||
Destination *time.Duration
|
||||
}
|
||||
|
||||
@ -102,6 +104,7 @@ type Float64Flag struct {
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value float64
|
||||
DefaultText string
|
||||
Destination *float64
|
||||
}
|
||||
|
||||
@ -145,6 +148,7 @@ type GenericFlag struct {
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value Generic
|
||||
DefaultText string
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
@ -187,6 +191,7 @@ type Int64Flag struct {
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value int64
|
||||
DefaultText string
|
||||
Destination *int64
|
||||
}
|
||||
|
||||
@ -230,6 +235,7 @@ type IntFlag struct {
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value int
|
||||
DefaultText string
|
||||
Destination *int
|
||||
}
|
||||
|
||||
@ -273,6 +279,7 @@ type IntSliceFlag struct {
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value *IntSlice
|
||||
DefaultText string
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
@ -315,6 +322,7 @@ type Int64SliceFlag struct {
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value *Int64Slice
|
||||
DefaultText string
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
@ -357,6 +365,7 @@ type Float64SliceFlag struct {
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value *Float64Slice
|
||||
DefaultText string
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
@ -399,6 +408,7 @@ type StringFlag struct {
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value string
|
||||
DefaultText string
|
||||
Destination *string
|
||||
}
|
||||
|
||||
@ -442,6 +452,7 @@ type StringSliceFlag struct {
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value *StringSlice
|
||||
DefaultText string
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
@ -484,6 +495,7 @@ type Uint64Flag struct {
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value uint64
|
||||
DefaultText string
|
||||
Destination *uint64
|
||||
}
|
||||
|
||||
@ -527,6 +539,7 @@ type UintFlag struct {
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value uint
|
||||
DefaultText string
|
||||
Destination *uint
|
||||
}
|
||||
|
||||
|
15
flag_test.go
15
flag_test.go
@ -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) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_FOO", "derp")
|
||||
@ -482,7 +492,6 @@ func TestFloat64FlagApply_SetsAllNames(t *testing.T) {
|
||||
expect(t, v, float64(43.33333))
|
||||
}
|
||||
|
||||
|
||||
var float64SliceFlagTests = []struct {
|
||||
name string
|
||||
aliases []string
|
||||
@ -523,8 +532,6 @@ func TestFloat64SliceFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var genericFlagTests = []struct {
|
||||
name string
|
||||
value Generic
|
||||
@ -1100,7 +1107,6 @@ func TestParseMultiFloat64FromEnvCascade(t *testing.T) {
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
|
||||
func TestParseMultiFloat64SliceFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_INTERVALS", "0.1,-10.5")
|
||||
@ -1141,7 +1147,6 @@ func TestParseMultiFloat64SliceFromEnvCascade(t *testing.T) {
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
|
||||
func TestParseMultiBool(t *testing.T) {
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
|
@ -145,6 +145,7 @@ def _write_cli_flag_types(outfile, types):
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
Value {type}
|
||||
DefaultText string
|
||||
""".format(**typedef))
|
||||
|
||||
if typedef['dest']:
|
||||
|
Loading…
Reference in New Issue
Block a user