Merge pull request #661 from rliebz/custom-flag-help
Allow customization of prefixes and environment variable hints in flag help strings
This commit is contained in:
commit
ac249472b7
20
flag.go
20
flag.go
@ -37,6 +37,14 @@ var HelpFlag Flag = BoolFlag{
|
||||
// to display a flag.
|
||||
var FlagStringer FlagStringFunc = stringifyFlag
|
||||
|
||||
// FlagNamePrefixer converts a full flag name and its placeholder into the help
|
||||
// message flag prefix. This is used by the default FlagStringer.
|
||||
var FlagNamePrefixer FlagNamePrefixFunc = prefixedNames
|
||||
|
||||
// FlagEnvHinter annotates flag help message with the environment variable
|
||||
// details. This is used by the default FlagStringer.
|
||||
var FlagEnvHinter FlagEnvHintFunc = withEnvHint
|
||||
|
||||
// FlagsByName is a slice of Flag.
|
||||
type FlagsByName []Flag
|
||||
|
||||
@ -710,13 +718,13 @@ func stringifyFlag(f Flag) string {
|
||||
|
||||
switch f.(type) {
|
||||
case IntSliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
return FlagEnvHinter(fv.FieldByName("EnvVar").String(),
|
||||
stringifyIntSliceFlag(f.(IntSliceFlag)))
|
||||
case Int64SliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
return FlagEnvHinter(fv.FieldByName("EnvVar").String(),
|
||||
stringifyInt64SliceFlag(f.(Int64SliceFlag)))
|
||||
case StringSliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
return FlagEnvHinter(fv.FieldByName("EnvVar").String(),
|
||||
stringifyStringSliceFlag(f.(StringSliceFlag)))
|
||||
}
|
||||
|
||||
@ -744,8 +752,8 @@ func stringifyFlag(f Flag) string {
|
||||
|
||||
usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultValueString))
|
||||
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
fmt.Sprintf("%s\t%s", prefixedNames(fv.FieldByName("Name").String(), placeholder), usageWithDefault))
|
||||
return FlagEnvHinter(fv.FieldByName("EnvVar").String(),
|
||||
fmt.Sprintf("%s\t%s", FlagNamePrefixer(fv.FieldByName("Name").String(), placeholder), usageWithDefault))
|
||||
}
|
||||
|
||||
func stringifyIntSliceFlag(f IntSliceFlag) string {
|
||||
@ -795,5 +803,5 @@ func stringifySliceFlag(usage, name string, defaultVals []string) string {
|
||||
}
|
||||
|
||||
usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal))
|
||||
return fmt.Sprintf("%s\t%s", prefixedNames(name, placeholder), usageWithDefault)
|
||||
return fmt.Sprintf("%s\t%s", FlagNamePrefixer(name, placeholder), usageWithDefault)
|
||||
}
|
||||
|
77
flag_test.go
77
flag_test.go
@ -158,6 +158,83 @@ func TestStringFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
var prefixStringFlagTests = []struct {
|
||||
name string
|
||||
usage string
|
||||
value string
|
||||
prefixer FlagNamePrefixFunc
|
||||
expected string
|
||||
}{
|
||||
{"foo", "", "", func(a, b string) string {
|
||||
return fmt.Sprintf("name: %s, ph: %s", a, b)
|
||||
}, "name: foo, ph: value\t"},
|
||||
{"f", "", "", func(a, b string) string {
|
||||
return fmt.Sprintf("name: %s, ph: %s", a, b)
|
||||
}, "name: f, ph: value\t"},
|
||||
{"f", "The total `foo` desired", "all", func(a, b string) string {
|
||||
return fmt.Sprintf("name: %s, ph: %s", a, b)
|
||||
}, "name: f, ph: foo\tThe total foo desired (default: \"all\")"},
|
||||
{"test", "", "Something", func(a, b string) string {
|
||||
return fmt.Sprintf("name: %s, ph: %s", a, b)
|
||||
}, "name: test, ph: value\t(default: \"Something\")"},
|
||||
{"config,c", "Load configuration from `FILE`", "", func(a, b string) string {
|
||||
return fmt.Sprintf("name: %s, ph: %s", a, b)
|
||||
}, "name: config,c, ph: FILE\tLoad configuration from FILE"},
|
||||
{"config,c", "Load configuration from `CONFIG`", "config.json", func(a, b string) string {
|
||||
return fmt.Sprintf("name: %s, ph: %s", a, b)
|
||||
}, "name: config,c, ph: CONFIG\tLoad configuration from CONFIG (default: \"config.json\")"},
|
||||
}
|
||||
|
||||
func TestFlagNamePrefixer(t *testing.T) {
|
||||
defer func() {
|
||||
FlagNamePrefixer = prefixedNames
|
||||
}()
|
||||
|
||||
for _, test := range prefixStringFlagTests {
|
||||
FlagNamePrefixer = test.prefixer
|
||||
flag := StringFlag{Name: test.name, Usage: test.usage, Value: test.value}
|
||||
output := flag.String()
|
||||
if output != test.expected {
|
||||
t.Errorf("%q does not match %q", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var envHintFlagTests = []struct {
|
||||
name string
|
||||
env string
|
||||
hinter FlagEnvHintFunc
|
||||
expected string
|
||||
}{
|
||||
{"foo", "", func(a, b string) string {
|
||||
return fmt.Sprintf("env: %s, str: %s", a, b)
|
||||
}, "env: , str: --foo value\t"},
|
||||
{"f", "", func(a, b string) string {
|
||||
return fmt.Sprintf("env: %s, str: %s", a, b)
|
||||
}, "env: , str: -f value\t"},
|
||||
{"foo", "ENV_VAR", func(a, b string) string {
|
||||
return fmt.Sprintf("env: %s, str: %s", a, b)
|
||||
}, "env: ENV_VAR, str: --foo value\t"},
|
||||
{"f", "ENV_VAR", func(a, b string) string {
|
||||
return fmt.Sprintf("env: %s, str: %s", a, b)
|
||||
}, "env: ENV_VAR, str: -f value\t"},
|
||||
}
|
||||
|
||||
func TestFlagEnvHinter(t *testing.T) {
|
||||
defer func() {
|
||||
FlagEnvHinter = withEnvHint
|
||||
}()
|
||||
|
||||
for _, test := range envHintFlagTests {
|
||||
FlagEnvHinter = test.hinter
|
||||
flag := StringFlag{Name: test.name, EnvVar: test.env}
|
||||
output := flag.String()
|
||||
if output != test.expected {
|
||||
t.Errorf("%q does not match %q", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var stringSliceFlagTests = []struct {
|
||||
name string
|
||||
value *StringSlice
|
||||
|
8
funcs.go
8
funcs.go
@ -26,3 +26,11 @@ type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error
|
||||
// FlagStringFunc is used by the help generation to display a flag, which is
|
||||
// expected to be a single line.
|
||||
type FlagStringFunc func(Flag) string
|
||||
|
||||
// FlagNamePrefixFunc is used by the default FlagStringFunc to create prefix
|
||||
// text for a flag's full name.
|
||||
type FlagNamePrefixFunc func(fullName, placeholder string) string
|
||||
|
||||
// FlagEnvHintFunc is used by the default FlagStringFunc to annotate flag help
|
||||
// with the environment variable details.
|
||||
type FlagEnvHintFunc func(envVar, str string) string
|
||||
|
Loading…
Reference in New Issue
Block a user