Replace all "stringly typed" fields with slice equivalents
and alter the Flag interface accordingly Closes #415
This commit is contained in:
parent
65357985c2
commit
81fcf706ea
34
README.md
34
README.md
@ -265,8 +265,9 @@ For example this:
|
||||
|
||||
```go
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Usage: "Load configuration from `FILE`",
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Load configuration from `FILE`",
|
||||
}
|
||||
```
|
||||
|
||||
@ -285,9 +286,10 @@ You can set alternate (or short) names for flags by providing a comma-delimited
|
||||
``` go
|
||||
app.Flags = []cli.Flag {
|
||||
cli.StringFlag{
|
||||
Name: "lang, l",
|
||||
Value: "english",
|
||||
Usage: "language for the greeting",
|
||||
Name: "lang",
|
||||
Aliases: []string{"l"},
|
||||
Value: "english",
|
||||
Usage: "language for the greeting",
|
||||
},
|
||||
}
|
||||
```
|
||||
@ -296,28 +298,30 @@ That flag can then be set with `--lang spanish` or `-l spanish`. Note that givin
|
||||
|
||||
#### Values from the Environment
|
||||
|
||||
You can also have the default value set from the environment via `EnvVar`. e.g.
|
||||
You can also have the default value set from the environment via `EnvVars`. e.g.
|
||||
|
||||
``` go
|
||||
app.Flags = []cli.Flag {
|
||||
cli.StringFlag{
|
||||
Name: "lang, l",
|
||||
Value: "english",
|
||||
Usage: "language for the greeting",
|
||||
EnvVar: "APP_LANG",
|
||||
Name: "lang",
|
||||
Aliases: []string{"l"},
|
||||
Value: "english",
|
||||
Usage: "language for the greeting",
|
||||
EnvVars: []string{"APP_LANG"},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The `EnvVar` may also be given as a comma-delimited "cascade", where the first environment variable that resolves is used as the default.
|
||||
If `EnvVars` contains more than one string, the first environment variable that resolves is used as the default.
|
||||
|
||||
``` go
|
||||
app.Flags = []cli.Flag {
|
||||
cli.StringFlag{
|
||||
Name: "lang, l",
|
||||
Value: "english",
|
||||
Usage: "language for the greeting",
|
||||
EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG",
|
||||
Name: "lang",
|
||||
Aliases: []string{"l"},
|
||||
Value: "english",
|
||||
Usage: "language for the greeting",
|
||||
EnvVars: []string{"LEGACY_COMPAT_LANG", "APP_LANG", "LANG"},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
@ -78,15 +77,15 @@ func NewGenericFlag(flag cli.GenericFlag) *GenericFlag {
|
||||
// ApplyInputSourceValue applies a generic value to the flagSet if required
|
||||
func (f *GenericFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
|
||||
if f.set != nil {
|
||||
if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
|
||||
if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVars) {
|
||||
value, err := isc.Generic(f.GenericFlag.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if value != nil {
|
||||
eachName(f.Name, func(name string) {
|
||||
f.set.Set(f.Name, value.String())
|
||||
})
|
||||
for _, name := range f.Names() {
|
||||
f.set.Set(name, value.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -116,19 +115,19 @@ func NewStringSliceFlag(flag cli.StringSliceFlag) *StringSliceFlag {
|
||||
// ApplyInputSourceValue applies a StringSlice value to the flagSet if required
|
||||
func (f *StringSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
|
||||
if f.set != nil {
|
||||
if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
|
||||
if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVars) {
|
||||
value, err := isc.StringSlice(f.StringSliceFlag.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if value != nil {
|
||||
var sliceValue cli.StringSlice = *(cli.NewStringSlice(value...))
|
||||
eachName(f.Name, func(name string) {
|
||||
underlyingFlag := f.set.Lookup(f.Name)
|
||||
for _, name := range f.Names() {
|
||||
underlyingFlag := f.set.Lookup(name)
|
||||
if underlyingFlag != nil {
|
||||
underlyingFlag.Value = &sliceValue
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -157,19 +156,19 @@ func NewIntSliceFlag(flag cli.IntSliceFlag) *IntSliceFlag {
|
||||
// ApplyInputSourceValue applies a IntSlice value if required
|
||||
func (f *IntSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
|
||||
if f.set != nil {
|
||||
if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
|
||||
if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVars) {
|
||||
value, err := isc.IntSlice(f.IntSliceFlag.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if value != nil {
|
||||
var sliceValue cli.IntSlice = *(cli.NewIntSlice(value...))
|
||||
eachName(f.Name, func(name string) {
|
||||
underlyingFlag := f.set.Lookup(f.Name)
|
||||
for _, name := range f.Names() {
|
||||
underlyingFlag := f.set.Lookup(name)
|
||||
if underlyingFlag != nil {
|
||||
underlyingFlag.Value = &sliceValue
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -198,15 +197,15 @@ func NewBoolFlag(flag cli.BoolFlag) *BoolFlag {
|
||||
// ApplyInputSourceValue applies a Bool value to the flagSet if required
|
||||
func (f *BoolFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
|
||||
if f.set != nil {
|
||||
if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
|
||||
if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVars) {
|
||||
value, err := isc.Bool(f.BoolFlag.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if value {
|
||||
eachName(f.Name, func(name string) {
|
||||
f.set.Set(f.Name, strconv.FormatBool(value))
|
||||
})
|
||||
for _, name := range f.Names() {
|
||||
f.set.Set(name, strconv.FormatBool(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -235,15 +234,15 @@ func NewStringFlag(flag cli.StringFlag) *StringFlag {
|
||||
// ApplyInputSourceValue applies a String value to the flagSet if required
|
||||
func (f *StringFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
|
||||
if f.set != nil {
|
||||
if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) {
|
||||
if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVars)) {
|
||||
value, err := isc.String(f.StringFlag.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if value != "" {
|
||||
eachName(f.Name, func(name string) {
|
||||
f.set.Set(f.Name, value)
|
||||
})
|
||||
for _, name := range f.Names() {
|
||||
f.set.Set(name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -273,15 +272,15 @@ func NewIntFlag(flag cli.IntFlag) *IntFlag {
|
||||
// ApplyInputSourceValue applies a int value to the flagSet if required
|
||||
func (f *IntFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
|
||||
if f.set != nil {
|
||||
if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) {
|
||||
if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVars)) {
|
||||
value, err := isc.Int(f.IntFlag.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if value > 0 {
|
||||
eachName(f.Name, func(name string) {
|
||||
f.set.Set(f.Name, strconv.FormatInt(int64(value), 10))
|
||||
})
|
||||
for _, name := range f.Names() {
|
||||
f.set.Set(name, strconv.FormatInt(int64(value), 10))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -310,15 +309,15 @@ func NewDurationFlag(flag cli.DurationFlag) *DurationFlag {
|
||||
// ApplyInputSourceValue applies a Duration value to the flagSet if required
|
||||
func (f *DurationFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
|
||||
if f.set != nil {
|
||||
if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) {
|
||||
if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVars)) {
|
||||
value, err := isc.Duration(f.DurationFlag.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if value > 0 {
|
||||
eachName(f.Name, func(name string) {
|
||||
f.set.Set(f.Name, value.String())
|
||||
})
|
||||
for _, name := range f.Names() {
|
||||
f.set.Set(name, value.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -348,16 +347,16 @@ func NewFloat64Flag(flag cli.Float64Flag) *Float64Flag {
|
||||
// ApplyInputSourceValue applies a Float64 value to the flagSet if required
|
||||
func (f *Float64Flag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
|
||||
if f.set != nil {
|
||||
if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) {
|
||||
if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVars)) {
|
||||
value, err := isc.Float64(f.Float64Flag.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if value > 0 {
|
||||
floatStr := float64ToString(value)
|
||||
eachName(f.Name, func(name string) {
|
||||
f.set.Set(f.Name, floatStr)
|
||||
})
|
||||
for _, name := range f.Names() {
|
||||
f.set.Set(name, floatStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -372,9 +371,8 @@ func (f *Float64Flag) Apply(set *flag.FlagSet) {
|
||||
f.Float64Flag.Apply(set)
|
||||
}
|
||||
|
||||
func isEnvVarSet(envVars string) bool {
|
||||
for _, envVar := range strings.Split(envVars, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
func isEnvVarSet(envVars []string) bool {
|
||||
for _, envVar := range envVars {
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
// TODO: Can't use this for bools as
|
||||
// set means that it was true or false based on
|
||||
@ -391,11 +389,3 @@ func isEnvVarSet(envVars string) bool {
|
||||
func float64ToString(f float64) string {
|
||||
return fmt.Sprintf("%v", f)
|
||||
}
|
||||
|
||||
func eachName(longName string, fn func(string)) {
|
||||
parts := strings.Split(longName, ",")
|
||||
for _, name := range parts {
|
||||
name = strings.Trim(name, " ")
|
||||
fn(name)
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,11 @@ func TestGenericApplyInputSourceMethodContextSet(t *testing.T) {
|
||||
|
||||
func TestGenericApplyInputSourceMethodEnvVarSet(t *testing.T) {
|
||||
c := runTest(t, testApplyInputSource{
|
||||
Flag: NewGenericFlag(cli.GenericFlag{Name: "test", Value: &Parser{}, EnvVar: "TEST"}),
|
||||
Flag: NewGenericFlag(cli.GenericFlag{
|
||||
Name: "test",
|
||||
Value: &Parser{},
|
||||
EnvVars: []string{"TEST"},
|
||||
}),
|
||||
FlagName: "test",
|
||||
MapValue: &Parser{"efg", "hij"},
|
||||
EnvVarName: "TEST",
|
||||
@ -76,7 +80,7 @@ func TestStringSliceApplyInputSourceMethodContextSet(t *testing.T) {
|
||||
|
||||
func TestStringSliceApplyInputSourceMethodEnvVarSet(t *testing.T) {
|
||||
c := runTest(t, testApplyInputSource{
|
||||
Flag: NewStringSliceFlag(cli.StringSliceFlag{Name: "test", EnvVar: "TEST"}),
|
||||
Flag: NewStringSliceFlag(cli.StringSliceFlag{Name: "test", EnvVars: []string{"TEST"}}),
|
||||
FlagName: "test",
|
||||
MapValue: []string{"hello", "world"},
|
||||
EnvVarName: "TEST",
|
||||
@ -106,7 +110,7 @@ func TestIntSliceApplyInputSourceMethodContextSet(t *testing.T) {
|
||||
|
||||
func TestIntSliceApplyInputSourceMethodEnvVarSet(t *testing.T) {
|
||||
c := runTest(t, testApplyInputSource{
|
||||
Flag: NewIntSliceFlag(cli.IntSliceFlag{Name: "test", EnvVar: "TEST"}),
|
||||
Flag: NewIntSliceFlag(cli.IntSliceFlag{Name: "test", EnvVars: []string{"TEST"}}),
|
||||
FlagName: "test",
|
||||
MapValue: []int{1, 2},
|
||||
EnvVarName: "TEST",
|
||||
@ -136,7 +140,7 @@ func TestBoolApplyInputSourceMethodContextSet(t *testing.T) {
|
||||
|
||||
func TestBoolApplyInputSourceMethodEnvVarSet(t *testing.T) {
|
||||
c := runTest(t, testApplyInputSource{
|
||||
Flag: NewBoolFlag(cli.BoolFlag{Name: "test", EnvVar: "TEST"}),
|
||||
Flag: NewBoolFlag(cli.BoolFlag{Name: "test", EnvVars: []string{"TEST"}}),
|
||||
FlagName: "test",
|
||||
MapValue: false,
|
||||
EnvVarName: "TEST",
|
||||
@ -166,7 +170,7 @@ func TestStringApplyInputSourceMethodContextSet(t *testing.T) {
|
||||
|
||||
func TestStringApplyInputSourceMethodEnvVarSet(t *testing.T) {
|
||||
c := runTest(t, testApplyInputSource{
|
||||
Flag: NewStringFlag(cli.StringFlag{Name: "test", EnvVar: "TEST"}),
|
||||
Flag: NewStringFlag(cli.StringFlag{Name: "test", EnvVars: []string{"TEST"}}),
|
||||
FlagName: "test",
|
||||
MapValue: "hello",
|
||||
EnvVarName: "TEST",
|
||||
@ -196,7 +200,7 @@ func TestIntApplyInputSourceMethodContextSet(t *testing.T) {
|
||||
|
||||
func TestIntApplyInputSourceMethodEnvVarSet(t *testing.T) {
|
||||
c := runTest(t, testApplyInputSource{
|
||||
Flag: NewIntFlag(cli.IntFlag{Name: "test", EnvVar: "TEST"}),
|
||||
Flag: NewIntFlag(cli.IntFlag{Name: "test", EnvVars: []string{"TEST"}}),
|
||||
FlagName: "test",
|
||||
MapValue: 15,
|
||||
EnvVarName: "TEST",
|
||||
@ -226,7 +230,7 @@ func TestDurationApplyInputSourceMethodContextSet(t *testing.T) {
|
||||
|
||||
func TestDurationApplyInputSourceMethodEnvVarSet(t *testing.T) {
|
||||
c := runTest(t, testApplyInputSource{
|
||||
Flag: NewDurationFlag(cli.DurationFlag{Name: "test", EnvVar: "TEST"}),
|
||||
Flag: NewDurationFlag(cli.DurationFlag{Name: "test", EnvVars: []string{"TEST"}}),
|
||||
FlagName: "test",
|
||||
MapValue: time.Duration(30 * time.Second),
|
||||
EnvVarName: "TEST",
|
||||
@ -256,7 +260,7 @@ func TestFloat64ApplyInputSourceMethodContextSet(t *testing.T) {
|
||||
|
||||
func TestFloat64ApplyInputSourceMethodEnvVarSet(t *testing.T) {
|
||||
c := runTest(t, testApplyInputSource{
|
||||
Flag: NewFloat64Flag(cli.Float64Flag{Name: "test", EnvVar: "TEST"}),
|
||||
Flag: NewFloat64Flag(cli.Float64Flag{Name: "test", EnvVars: []string{"TEST"}}),
|
||||
FlagName: "test",
|
||||
MapValue: 1.3,
|
||||
EnvVarName: "TEST",
|
||||
|
@ -68,7 +68,7 @@ func TestCommandYamlFileTestGlobalEnvVarWins(t *testing.T) {
|
||||
return nil
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
NewIntFlag(cli.IntFlag{Name: "test", EnvVar: "THE_TEST"}),
|
||||
NewIntFlag(cli.IntFlag{Name: "test", EnvVars: []string{"THE_TEST"}}),
|
||||
cli.StringFlag{Name: "load"}},
|
||||
}
|
||||
command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
|
||||
@ -103,7 +103,7 @@ func TestCommandYamlFileTestGlobalEnvVarWinsNested(t *testing.T) {
|
||||
return nil
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
NewIntFlag(cli.IntFlag{Name: "top.test", EnvVar: "THE_TEST"}),
|
||||
NewIntFlag(cli.IntFlag{Name: "top.test", EnvVars: []string{"THE_TEST"}}),
|
||||
cli.StringFlag{Name: "load"}},
|
||||
}
|
||||
command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
|
||||
@ -268,7 +268,7 @@ func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWins(t *testing.T
|
||||
return nil
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
NewIntFlag(cli.IntFlag{Name: "test", Value: 7, EnvVar: "THE_TEST"}),
|
||||
NewIntFlag(cli.IntFlag{Name: "test", Value: 7, EnvVars: []string{"THE_TEST"}}),
|
||||
cli.StringFlag{Name: "load"}},
|
||||
}
|
||||
command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
|
||||
@ -303,7 +303,7 @@ func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWinsNested(t *tes
|
||||
return nil
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7, EnvVar: "THE_TEST"}),
|
||||
NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7, EnvVars: []string{"THE_TEST"}}),
|
||||
cli.StringFlag{Name: "load"}},
|
||||
}
|
||||
command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
|
||||
|
7
app.go
7
app.go
@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
@ -121,7 +122,7 @@ func (a *App) Setup() {
|
||||
// append help to commands
|
||||
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
|
||||
a.Commands = append(a.Commands, helpCommand)
|
||||
if (HelpFlag != BoolFlag{}) {
|
||||
if !reflect.DeepEqual(HelpFlag, BoolFlag{}) {
|
||||
a.appendFlag(HelpFlag)
|
||||
}
|
||||
}
|
||||
@ -224,7 +225,7 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
||||
if len(a.Commands) > 0 {
|
||||
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
|
||||
a.Commands = append(a.Commands, helpCommand)
|
||||
if (HelpFlag != BoolFlag{}) {
|
||||
if !reflect.DeepEqual(HelpFlag, BoolFlag{}) {
|
||||
a.appendFlag(HelpFlag)
|
||||
}
|
||||
}
|
||||
@ -379,7 +380,7 @@ func (a *App) VisibleFlags() []Flag {
|
||||
|
||||
func (a *App) hasFlag(flag Flag) bool {
|
||||
for _, f := range a.Flags {
|
||||
if flag == f {
|
||||
if reflect.DeepEqual(flag, f) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package cli
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
@ -69,7 +70,7 @@ func (c Command) Run(ctx *Context) (err error) {
|
||||
return c.startApp(ctx)
|
||||
}
|
||||
|
||||
if !c.HideHelp && (HelpFlag != BoolFlag{}) {
|
||||
if !c.HideHelp && !reflect.DeepEqual(HelpFlag, BoolFlag{}) {
|
||||
// append help to flags
|
||||
c.Flags = append(
|
||||
c.Flags,
|
||||
|
@ -310,7 +310,7 @@ func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
|
||||
visited[f.Name] = true
|
||||
})
|
||||
for _, f := range flags {
|
||||
parts := strings.Split(f.GetName(), ",")
|
||||
parts := f.Names()
|
||||
if len(parts) == 1 {
|
||||
continue
|
||||
}
|
||||
|
264
flag.go
264
flag.go
@ -24,16 +24,18 @@ var BashCompletionFlag = BoolFlag{
|
||||
|
||||
// VersionFlag prints the version for the application
|
||||
var VersionFlag = BoolFlag{
|
||||
Name: "version, v",
|
||||
Usage: "print the version",
|
||||
Name: "version",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "print the version",
|
||||
}
|
||||
|
||||
// HelpFlag prints the help for all commands and subcommands
|
||||
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
|
||||
// unless HideHelp is set to true)
|
||||
// HelpFlag prints the help for all commands and subcommands.
|
||||
// Set to the zero value (BoolFlag{}) to disable the flag. The subcommand
|
||||
// will still be added unless HideHelp is set to true.
|
||||
var HelpFlag = BoolFlag{
|
||||
Name: "help, h",
|
||||
Usage: "show help",
|
||||
Name: "help",
|
||||
Aliases: []string{"h"},
|
||||
Usage: "show help",
|
||||
}
|
||||
|
||||
// FlagStringer converts a flag definition to a string. This is used by help
|
||||
@ -52,7 +54,7 @@ type Flag interface {
|
||||
fmt.Stringer
|
||||
// Apply Flag settings to the given flag set
|
||||
Apply(*flag.FlagSet)
|
||||
GetName() string
|
||||
Names() []string
|
||||
}
|
||||
|
||||
func flagSet(name string, flags []Flag) *flag.FlagSet {
|
||||
@ -64,14 +66,6 @@ func flagSet(name string, flags []Flag) *flag.FlagSet {
|
||||
return set
|
||||
}
|
||||
|
||||
func eachName(longName string, fn func(string)) {
|
||||
parts := strings.Split(longName, ",")
|
||||
for _, name := range parts {
|
||||
name = strings.Trim(name, " ")
|
||||
fn(name)
|
||||
}
|
||||
}
|
||||
|
||||
// Generic is a generic parseable type identified by a specific flag
|
||||
type Generic interface {
|
||||
Set(value string) error
|
||||
@ -80,11 +74,12 @@ type Generic interface {
|
||||
|
||||
// GenericFlag is the flag type for types implementing Generic
|
||||
type GenericFlag struct {
|
||||
Name string
|
||||
Value Generic
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Name string
|
||||
Aliases []string
|
||||
Value Generic
|
||||
Usage string
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
}
|
||||
|
||||
// String returns the string representation of the generic flag to display the
|
||||
@ -98,8 +93,8 @@ func (f GenericFlag) String() string {
|
||||
// provided by the user for parsing by the flag
|
||||
func (f GenericFlag) Apply(set *flag.FlagSet) {
|
||||
val := f.Value
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
if f.EnvVars != nil {
|
||||
for _, envVar := range f.EnvVars {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
val.Set(envVal)
|
||||
@ -108,14 +103,14 @@ func (f GenericFlag) Apply(set *flag.FlagSet) {
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
for _, name := range f.Names() {
|
||||
set.Var(f.Value, name, f.Usage)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// GetName returns the name of a flag.
|
||||
func (f GenericFlag) GetName() string {
|
||||
return f.Name
|
||||
// Names returns the names of a flag.
|
||||
func (f GenericFlag) Names() []string {
|
||||
return append([]string{f.Name}, f.Aliases...)
|
||||
}
|
||||
|
||||
// StringSlice wraps a []string to satisfy flag.Value
|
||||
@ -166,11 +161,12 @@ func (f *StringSlice) Value() []string {
|
||||
// StringSliceFlag is a string flag that can be specified multiple times on the
|
||||
// command-line
|
||||
type StringSliceFlag struct {
|
||||
Name string
|
||||
Value *StringSlice
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Name string
|
||||
Aliases []string
|
||||
Value *StringSlice
|
||||
Usage string
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
@ -180,8 +176,8 @@ func (f StringSliceFlag) String() string {
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f StringSliceFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
if f.EnvVars != nil {
|
||||
for _, envVar := range f.EnvVars {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
newVal := NewStringSlice()
|
||||
@ -199,14 +195,14 @@ func (f StringSliceFlag) Apply(set *flag.FlagSet) {
|
||||
f.Value = NewStringSlice()
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
for _, name := range f.Names() {
|
||||
set.Var(f.Value, name, f.Usage)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// GetName returns the name of a flag.
|
||||
func (f StringSliceFlag) GetName() string {
|
||||
return f.Name
|
||||
// Names returns the name of a flag.
|
||||
func (f StringSliceFlag) Names() []string {
|
||||
return append([]string{f.Name}, f.Aliases...)
|
||||
}
|
||||
|
||||
// IntSlice wraps an []int to satisfy flag.Value
|
||||
@ -272,11 +268,12 @@ func (i *IntSlice) Value() []int {
|
||||
// IntSliceFlag is an int flag that can be specified multiple times on the
|
||||
// command-line
|
||||
type IntSliceFlag struct {
|
||||
Name string
|
||||
Value *IntSlice
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Name string
|
||||
Aliases []string
|
||||
Value *IntSlice
|
||||
Usage string
|
||||
EnvVars []string
|
||||
Hidden bool
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
@ -286,8 +283,8 @@ func (f IntSliceFlag) String() string {
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f IntSliceFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
if f.EnvVars != nil {
|
||||
for _, envVar := range f.EnvVars {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
newVal := NewIntSlice()
|
||||
@ -308,22 +305,23 @@ func (f IntSliceFlag) Apply(set *flag.FlagSet) {
|
||||
f.Value = NewIntSlice()
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
for _, name := range f.Names() {
|
||||
set.Var(f.Value, name, f.Usage)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f IntSliceFlag) GetName() string {
|
||||
return f.Name
|
||||
// Names returns the name of the flag.
|
||||
func (f IntSliceFlag) Names() []string {
|
||||
return append([]string{f.Name}, f.Aliases...)
|
||||
}
|
||||
|
||||
// BoolFlag is a switch that defaults to false
|
||||
type BoolFlag struct {
|
||||
Name string
|
||||
Aliases []string
|
||||
Value bool
|
||||
Usage string
|
||||
EnvVar string
|
||||
EnvVars []string
|
||||
Destination *bool
|
||||
Hidden bool
|
||||
}
|
||||
@ -335,8 +333,8 @@ func (f BoolFlag) String() string {
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f BoolFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
if f.EnvVars != nil {
|
||||
for _, envVar := range f.EnvVars {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValBool, err := strconv.ParseBool(envVal)
|
||||
@ -348,26 +346,27 @@ func (f BoolFlag) Apply(set *flag.FlagSet) {
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
for _, name := range f.Names() {
|
||||
if f.Destination != nil {
|
||||
set.BoolVar(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Bool(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f BoolFlag) GetName() string {
|
||||
return f.Name
|
||||
// Names returns the name of the flag.
|
||||
func (f BoolFlag) Names() []string {
|
||||
return append([]string{f.Name}, f.Aliases...)
|
||||
}
|
||||
|
||||
// StringFlag represents a flag that takes as string value
|
||||
type StringFlag struct {
|
||||
Name string
|
||||
Aliases []string
|
||||
Value string
|
||||
Usage string
|
||||
EnvVar string
|
||||
EnvVars []string
|
||||
Destination *string
|
||||
Hidden bool
|
||||
}
|
||||
@ -379,8 +378,8 @@ func (f StringFlag) String() string {
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f StringFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
if f.EnvVars != nil {
|
||||
for _, envVar := range f.EnvVars {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
f.Value = envVal
|
||||
@ -389,27 +388,28 @@ func (f StringFlag) Apply(set *flag.FlagSet) {
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
for _, name := range f.Names() {
|
||||
if f.Destination != nil {
|
||||
set.StringVar(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.String(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f StringFlag) GetName() string {
|
||||
return f.Name
|
||||
// Names returns the name of the flag.
|
||||
func (f StringFlag) Names() []string {
|
||||
return append([]string{f.Name}, f.Aliases...)
|
||||
}
|
||||
|
||||
// IntFlag is a flag that takes an integer
|
||||
// Errors if the value provided cannot be parsed
|
||||
type IntFlag struct {
|
||||
Name string
|
||||
Aliases []string
|
||||
Value int
|
||||
Usage string
|
||||
EnvVar string
|
||||
EnvVars []string
|
||||
Destination *int
|
||||
Hidden bool
|
||||
}
|
||||
@ -421,8 +421,8 @@ func (f IntFlag) String() string {
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f IntFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
if f.EnvVars != nil {
|
||||
for _, envVar := range f.EnvVars {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
||||
@ -434,27 +434,28 @@ func (f IntFlag) Apply(set *flag.FlagSet) {
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
for _, name := range f.Names() {
|
||||
if f.Destination != nil {
|
||||
set.IntVar(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Int(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f IntFlag) GetName() string {
|
||||
return f.Name
|
||||
// Names returns the name of the flag.
|
||||
func (f IntFlag) Names() []string {
|
||||
return append([]string{f.Name}, f.Aliases...)
|
||||
}
|
||||
|
||||
// DurationFlag is a flag that takes a duration specified in Go's duration
|
||||
// format: https://golang.org/pkg/time/#ParseDuration
|
||||
type DurationFlag struct {
|
||||
Name string
|
||||
Aliases []string
|
||||
Value time.Duration
|
||||
Usage string
|
||||
EnvVar string
|
||||
EnvVars []string
|
||||
Destination *time.Duration
|
||||
Hidden bool
|
||||
}
|
||||
@ -466,8 +467,8 @@ func (f DurationFlag) String() string {
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f DurationFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
if f.EnvVars != nil {
|
||||
for _, envVar := range f.EnvVars {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValDuration, err := time.ParseDuration(envVal)
|
||||
@ -479,27 +480,28 @@ func (f DurationFlag) Apply(set *flag.FlagSet) {
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
for _, name := range f.Names() {
|
||||
if f.Destination != nil {
|
||||
set.DurationVar(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Duration(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f DurationFlag) GetName() string {
|
||||
return f.Name
|
||||
// Names returns the name of the flag.
|
||||
func (f DurationFlag) Names() []string {
|
||||
return append([]string{f.Name}, f.Aliases...)
|
||||
}
|
||||
|
||||
// Float64Flag is a flag that takes an float value
|
||||
// Errors if the value provided cannot be parsed
|
||||
type Float64Flag struct {
|
||||
Name string
|
||||
Aliases []string
|
||||
Value float64
|
||||
Usage string
|
||||
EnvVar string
|
||||
EnvVars []string
|
||||
Destination *float64
|
||||
Hidden bool
|
||||
}
|
||||
@ -511,8 +513,8 @@ func (f Float64Flag) String() string {
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f Float64Flag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
if f.EnvVars != nil {
|
||||
for _, envVar := range f.EnvVars {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValFloat, err := strconv.ParseFloat(envVal, 10)
|
||||
@ -523,18 +525,18 @@ func (f Float64Flag) Apply(set *flag.FlagSet) {
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
for _, name := range f.Names() {
|
||||
if f.Destination != nil {
|
||||
set.Float64Var(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Float64(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f Float64Flag) GetName() string {
|
||||
return f.Name
|
||||
// Names returns the name of the flag.
|
||||
func (f Float64Flag) Names() []string {
|
||||
return append([]string{f.Name}, f.Aliases...)
|
||||
}
|
||||
|
||||
func visibleFlags(fl []Flag) []Flag {
|
||||
@ -574,25 +576,27 @@ func unquoteUsage(usage string) (string, string) {
|
||||
return "", usage
|
||||
}
|
||||
|
||||
func prefixedNames(fullName, placeholder string) string {
|
||||
func prefixedNames(names []string, placeholder string) string {
|
||||
var prefixed string
|
||||
parts := strings.Split(fullName, ",")
|
||||
for i, name := range parts {
|
||||
name = strings.Trim(name, " ")
|
||||
for i, name := range names {
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
prefixed += prefixFor(name) + name
|
||||
if placeholder != "" {
|
||||
prefixed += " " + placeholder
|
||||
}
|
||||
if i < len(parts)-1 {
|
||||
if i < len(names)-1 {
|
||||
prefixed += ", "
|
||||
}
|
||||
}
|
||||
return prefixed
|
||||
}
|
||||
|
||||
func withEnvHint(envVar, str string) string {
|
||||
func withEnvHint(envVars []string, str string) string {
|
||||
envText := ""
|
||||
if envVar != "" {
|
||||
if envVars != nil && len(envVars) > 0 {
|
||||
prefix := "$"
|
||||
suffix := ""
|
||||
sep := ", $"
|
||||
@ -601,21 +605,49 @@ func withEnvHint(envVar, str string) string {
|
||||
suffix = "%"
|
||||
sep = "%, %"
|
||||
}
|
||||
envText = fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(strings.Split(envVar, ","), sep), suffix)
|
||||
envText = fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(envVars, sep), suffix)
|
||||
}
|
||||
return str + envText
|
||||
}
|
||||
|
||||
func stringifyFlag(f Flag) string {
|
||||
func flagStringSliceField(f Flag, name string) []string {
|
||||
fv := flagValue(f)
|
||||
field := fv.FieldByName(name)
|
||||
|
||||
if field.IsValid() {
|
||||
return field.Interface().([]string)
|
||||
}
|
||||
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func flagStringField(f Flag, name string) string {
|
||||
fv := flagValue(f)
|
||||
field := fv.FieldByName(name)
|
||||
|
||||
if field.IsValid() {
|
||||
return field.String()
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func flagValue(f Flag) reflect.Value {
|
||||
fv := reflect.ValueOf(f)
|
||||
for fv.Kind() == reflect.Ptr {
|
||||
fv = reflect.Indirect(fv)
|
||||
}
|
||||
return fv
|
||||
}
|
||||
|
||||
func stringifyFlag(f Flag) string {
|
||||
fv := flagValue(f)
|
||||
|
||||
switch f.(type) {
|
||||
case IntSliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
stringifyIntSliceFlag(f.(IntSliceFlag)))
|
||||
return withEnvHint(flagStringSliceField(f, "EnvVars"), stringifyIntSliceFlag(f.(IntSliceFlag)))
|
||||
case StringSliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
stringifyStringSliceFlag(f.(StringSliceFlag)))
|
||||
return withEnvHint(flagStringSliceField(f, "EnvVars"), stringifyStringSliceFlag(f.(StringSliceFlag)))
|
||||
}
|
||||
|
||||
placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String())
|
||||
@ -643,8 +675,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 withEnvHint(flagStringSliceField(f, "EnvVars"),
|
||||
fmt.Sprintf("%s\t%s", prefixedNames(f.Names(), placeholder), usageWithDefault))
|
||||
}
|
||||
|
||||
func stringifyIntSliceFlag(f IntSliceFlag) string {
|
||||
@ -655,7 +687,7 @@ func stringifyIntSliceFlag(f IntSliceFlag) string {
|
||||
}
|
||||
}
|
||||
|
||||
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
||||
return stringifySliceFlag(f.Usage, append([]string{f.Name}, f.Aliases...), defaultVals)
|
||||
}
|
||||
|
||||
func stringifyStringSliceFlag(f StringSliceFlag) string {
|
||||
@ -668,10 +700,10 @@ func stringifyStringSliceFlag(f StringSliceFlag) string {
|
||||
}
|
||||
}
|
||||
|
||||
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
||||
return stringifySliceFlag(f.Usage, append([]string{f.Name}, f.Aliases...), defaultVals)
|
||||
}
|
||||
|
||||
func stringifySliceFlag(usage, name string, defaultVals []string) string {
|
||||
func stringifySliceFlag(usage string, names, defaultVals []string) string {
|
||||
placeholder, usage := unquoteUsage(usage)
|
||||
if placeholder == "" {
|
||||
placeholder = defaultPlaceholder
|
||||
@ -683,5 +715,15 @@ 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", prefixedNames(names, placeholder), usageWithDefault)
|
||||
}
|
||||
|
||||
func hasFlag(flags []Flag, fl Flag) bool {
|
||||
for _, existing := range flags {
|
||||
if fl == existing {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
132
flag_test.go
132
flag_test.go
@ -31,21 +31,22 @@ func TestBoolFlagHelpOutput(t *testing.T) {
|
||||
|
||||
var stringFlagTests = []struct {
|
||||
name string
|
||||
aliases []string
|
||||
usage string
|
||||
value string
|
||||
expected string
|
||||
}{
|
||||
{"foo", "", "", "--foo value\t"},
|
||||
{"f", "", "", "-f value\t"},
|
||||
{"f", "The total `foo` desired", "all", "-f foo\tThe total foo desired (default: \"all\")"},
|
||||
{"test", "", "Something", "--test value\t(default: \"Something\")"},
|
||||
{"config,c", "Load configuration from `FILE`", "", "--config FILE, -c FILE\tLoad configuration from FILE"},
|
||||
{"config,c", "Load configuration from `CONFIG`", "config.json", "--config CONFIG, -c CONFIG\tLoad configuration from CONFIG (default: \"config.json\")"},
|
||||
{"foo", nil, "", "", "--foo value\t"},
|
||||
{"f", nil, "", "", "-f value\t"},
|
||||
{"f", nil, "The total `foo` desired", "all", "-f foo\tThe total foo desired (default: \"all\")"},
|
||||
{"test", nil, "", "Something", "--test value\t(default: \"Something\")"},
|
||||
{"config", []string{"c"}, "Load configuration from `FILE`", "", "--config FILE, -c FILE\tLoad configuration from FILE"},
|
||||
{"config", []string{"c"}, "Load configuration from `CONFIG`", "config.json", "--config CONFIG, -c CONFIG\tLoad configuration from CONFIG (default: \"config.json\")"},
|
||||
}
|
||||
|
||||
func TestStringFlagHelpOutput(t *testing.T) {
|
||||
for _, test := range stringFlagTests {
|
||||
flag := StringFlag{Name: test.name, Usage: test.usage, Value: test.value}
|
||||
flag := StringFlag{Name: test.name, Aliases: test.aliases, Usage: test.usage, Value: test.value}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
@ -58,7 +59,7 @@ func TestStringFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_FOO", "derp")
|
||||
for _, test := range stringFlagTests {
|
||||
flag := StringFlag{Name: test.name, Value: test.value, EnvVar: "APP_FOO"}
|
||||
flag := StringFlag{Name: test.name, Aliases: test.aliases, Value: test.value, EnvVars: []string{"APP_FOO"}}
|
||||
output := flag.String()
|
||||
|
||||
expectedSuffix := " [$APP_FOO]"
|
||||
@ -73,19 +74,20 @@ func TestStringFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
|
||||
var stringSliceFlagTests = []struct {
|
||||
name string
|
||||
aliases []string
|
||||
value *StringSlice
|
||||
expected string
|
||||
}{
|
||||
{"foo", NewStringSlice(""), "--foo value\t"},
|
||||
{"f", NewStringSlice(""), "-f value\t"},
|
||||
{"f", NewStringSlice("Lipstick"), "-f value\t(default: \"Lipstick\")"},
|
||||
{"test", NewStringSlice("Something"), "--test value\t(default: \"Something\")"},
|
||||
{"d, dee", NewStringSlice("Inka", "Dinka", "dooo"), "-d value, --dee value\t(default: \"Inka\", \"Dinka\", \"dooo\")"},
|
||||
{"foo", nil, NewStringSlice(""), "--foo value\t"},
|
||||
{"f", nil, NewStringSlice(""), "-f value\t"},
|
||||
{"f", nil, NewStringSlice("Lipstick"), "-f value\t(default: \"Lipstick\")"},
|
||||
{"test", nil, NewStringSlice("Something"), "--test value\t(default: \"Something\")"},
|
||||
{"dee", []string{"d"}, NewStringSlice("Inka", "Dinka", "dooo"), "--dee value, -d value\t(default: \"Inka\", \"Dinka\", \"dooo\")"},
|
||||
}
|
||||
|
||||
func TestStringSliceFlagHelpOutput(t *testing.T) {
|
||||
for _, test := range stringSliceFlagTests {
|
||||
flag := StringSliceFlag{Name: test.name, Value: test.value}
|
||||
flag := StringSliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
@ -98,7 +100,7 @@ func TestStringSliceFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_QWWX", "11,4")
|
||||
for _, test := range stringSliceFlagTests {
|
||||
flag := StringSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_QWWX"}
|
||||
flag := StringSliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value, EnvVars: []string{"APP_QWWX"}}
|
||||
output := flag.String()
|
||||
|
||||
expectedSuffix := " [$APP_QWWX]"
|
||||
@ -134,7 +136,7 @@ func TestIntFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_BAR", "2")
|
||||
for _, test := range intFlagTests {
|
||||
flag := IntFlag{Name: test.name, EnvVar: "APP_BAR"}
|
||||
flag := IntFlag{Name: test.name, EnvVars: []string{"APP_BAR"}}
|
||||
output := flag.String()
|
||||
|
||||
expectedSuffix := " [$APP_BAR]"
|
||||
@ -170,7 +172,7 @@ func TestDurationFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_BAR", "2h3m6s")
|
||||
for _, test := range durationFlagTests {
|
||||
flag := DurationFlag{Name: test.name, EnvVar: "APP_BAR"}
|
||||
flag := DurationFlag{Name: test.name, EnvVars: []string{"APP_BAR"}}
|
||||
output := flag.String()
|
||||
|
||||
expectedSuffix := " [$APP_BAR]"
|
||||
@ -185,17 +187,18 @@ func TestDurationFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
|
||||
var intSliceFlagTests = []struct {
|
||||
name string
|
||||
aliases []string
|
||||
value *IntSlice
|
||||
expected string
|
||||
}{
|
||||
{"heads", NewIntSlice(), "--heads value\t"},
|
||||
{"H", NewIntSlice(), "-H value\t"},
|
||||
{"H, heads", NewIntSlice(9, 3), "-H value, --heads value\t(default: 9, 3)"},
|
||||
{"heads", nil, NewIntSlice(), "--heads value\t"},
|
||||
{"H", nil, NewIntSlice(), "-H value\t"},
|
||||
{"H", []string{"heads"}, NewIntSlice(9, 3), "-H value, --heads value\t(default: 9, 3)"},
|
||||
}
|
||||
|
||||
func TestIntSliceFlagHelpOutput(t *testing.T) {
|
||||
for _, test := range intSliceFlagTests {
|
||||
flag := IntSliceFlag{Name: test.name, Value: test.value}
|
||||
flag := IntSliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
@ -208,7 +211,7 @@ func TestIntSliceFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_SMURF", "42,3")
|
||||
for _, test := range intSliceFlagTests {
|
||||
flag := IntSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_SMURF"}
|
||||
flag := IntSliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value, EnvVars: []string{"APP_SMURF"}}
|
||||
output := flag.String()
|
||||
|
||||
expectedSuffix := " [$APP_SMURF]"
|
||||
@ -244,7 +247,7 @@ func TestFloat64FlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_BAZ", "99.4")
|
||||
for _, test := range float64FlagTests {
|
||||
flag := Float64Flag{Name: test.name, EnvVar: "APP_BAZ"}
|
||||
flag := Float64Flag{Name: test.name, EnvVars: []string{"APP_BAZ"}}
|
||||
output := flag.String()
|
||||
|
||||
expectedSuffix := " [$APP_BAZ]"
|
||||
@ -281,7 +284,7 @@ func TestGenericFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_ZAP", "3")
|
||||
for _, test := range genericFlagTests {
|
||||
flag := GenericFlag{Name: test.name, EnvVar: "APP_ZAP"}
|
||||
flag := GenericFlag{Name: test.name, EnvVars: []string{"APP_ZAP"}}
|
||||
output := flag.String()
|
||||
|
||||
expectedSuffix := " [$APP_ZAP]"
|
||||
@ -297,7 +300,7 @@ func TestGenericFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
func TestParseMultiString(t *testing.T) {
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
StringFlag{Name: "serve, s"},
|
||||
StringFlag{Name: "serve", Aliases: []string{"s"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.String("serve") != "10" {
|
||||
@ -335,7 +338,7 @@ func TestParseMultiStringFromEnv(t *testing.T) {
|
||||
os.Setenv("APP_COUNT", "20")
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
StringFlag{Name: "count, c", EnvVar: "APP_COUNT"},
|
||||
StringFlag{Name: "count", Aliases: []string{"c"}, EnvVars: []string{"APP_COUNT"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.String("count") != "20" {
|
||||
@ -354,7 +357,7 @@ func TestParseMultiStringFromEnvCascade(t *testing.T) {
|
||||
os.Setenv("APP_COUNT", "20")
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
StringFlag{Name: "count, c", EnvVar: "COMPAT_COUNT,APP_COUNT"},
|
||||
StringFlag{Name: "count", Aliases: []string{"c"}, EnvVars: []string{"COMPAT_COUNT", "APP_COUNT"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.String("count") != "20" {
|
||||
@ -371,7 +374,7 @@ func TestParseMultiStringFromEnvCascade(t *testing.T) {
|
||||
func TestParseMultiStringSlice(t *testing.T) {
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
StringSliceFlag{Name: "serve, s", Value: NewStringSlice()},
|
||||
StringSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: NewStringSlice()},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
expected := []string{"10", "20"}
|
||||
@ -389,7 +392,7 @@ func TestParseMultiStringSlice(t *testing.T) {
|
||||
func TestParseMultiStringSliceWithDefaults(t *testing.T) {
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
StringSliceFlag{Name: "serve, s", Value: NewStringSlice("9", "2")},
|
||||
StringSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: NewStringSlice("9", "2")},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
expected := []string{"10", "20"}
|
||||
@ -407,7 +410,7 @@ func TestParseMultiStringSliceWithDefaults(t *testing.T) {
|
||||
func TestParseMultiStringSliceWithDefaultsUnset(t *testing.T) {
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
StringSliceFlag{Name: "serve, s", Value: NewStringSlice("9", "2")},
|
||||
StringSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: NewStringSlice("9", "2")},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.StringSlice("serve"), []string{"9", "2"}) {
|
||||
@ -427,7 +430,7 @@ func TestParseMultiStringSliceFromEnv(t *testing.T) {
|
||||
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
StringSliceFlag{Name: "intervals, i", Value: NewStringSlice(), EnvVar: "APP_INTERVALS"},
|
||||
StringSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: NewStringSlice(), EnvVars: []string{"APP_INTERVALS"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) {
|
||||
@ -447,7 +450,7 @@ func TestParseMultiStringSliceFromEnvWithDefaults(t *testing.T) {
|
||||
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
StringSliceFlag{Name: "intervals, i", Value: NewStringSlice("1", "2", "5"), EnvVar: "APP_INTERVALS"},
|
||||
StringSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: NewStringSlice("1", "2", "5"), EnvVars: []string{"APP_INTERVALS"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) {
|
||||
@ -467,7 +470,7 @@ func TestParseMultiStringSliceFromEnvCascade(t *testing.T) {
|
||||
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
StringSliceFlag{Name: "intervals, i", Value: NewStringSlice(), EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"},
|
||||
StringSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: NewStringSlice(), EnvVars: []string{"COMPAT_INTERVALS", "APP_INTERVALS"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) {
|
||||
@ -487,7 +490,7 @@ func TestParseMultiStringSliceFromEnvCascadeWithDefaults(t *testing.T) {
|
||||
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
StringSliceFlag{Name: "intervals, i", Value: NewStringSlice("1", "2", "5"), EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"},
|
||||
StringSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: NewStringSlice("1", "2", "5"), EnvVars: []string{"COMPAT_INTERVALS", "APP_INTERVALS"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) {
|
||||
@ -504,7 +507,7 @@ func TestParseMultiStringSliceFromEnvCascadeWithDefaults(t *testing.T) {
|
||||
func TestParseMultiInt(t *testing.T) {
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
IntFlag{Name: "serve, s"},
|
||||
IntFlag{Name: "serve", Aliases: []string{"s"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Int("serve") != 10 {
|
||||
@ -543,7 +546,7 @@ func TestParseMultiIntFromEnv(t *testing.T) {
|
||||
os.Setenv("APP_TIMEOUT_SECONDS", "10")
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
IntFlag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"},
|
||||
IntFlag{Name: "timeout", Aliases: []string{"t"}, EnvVars: []string{"APP_TIMEOUT_SECONDS"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Int("timeout") != 10 {
|
||||
@ -563,7 +566,7 @@ func TestParseMultiIntFromEnvCascade(t *testing.T) {
|
||||
os.Setenv("APP_TIMEOUT_SECONDS", "10")
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
IntFlag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"},
|
||||
IntFlag{Name: "timeout", Aliases: []string{"t"}, EnvVars: []string{"COMPAT_TIMEOUT_SECONDS", "APP_TIMEOUT_SECONDS"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Int("timeout") != 10 {
|
||||
@ -581,7 +584,7 @@ func TestParseMultiIntFromEnvCascade(t *testing.T) {
|
||||
func TestParseMultiIntSlice(t *testing.T) {
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
IntSliceFlag{Name: "serve, s", Value: NewIntSlice()},
|
||||
IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: NewIntSlice()},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.IntSlice("serve"), []int{10, 20}) {
|
||||
@ -598,7 +601,7 @@ func TestParseMultiIntSlice(t *testing.T) {
|
||||
func TestParseMultiIntSliceWithDefaults(t *testing.T) {
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
IntSliceFlag{Name: "serve, s", Value: NewIntSlice(9, 2)},
|
||||
IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: NewIntSlice(9, 2)},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.IntSlice("serve"), []int{10, 20}) {
|
||||
@ -615,7 +618,7 @@ func TestParseMultiIntSliceWithDefaults(t *testing.T) {
|
||||
func TestParseMultiIntSliceWithDefaultsUnset(t *testing.T) {
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
IntSliceFlag{Name: "serve, s", Value: NewIntSlice(9, 2)},
|
||||
IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: NewIntSlice(9, 2)},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.IntSlice("serve"), []int{9, 2}) {
|
||||
@ -635,7 +638,7 @@ func TestParseMultiIntSliceFromEnv(t *testing.T) {
|
||||
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
IntSliceFlag{Name: "intervals, i", Value: NewIntSlice(), EnvVar: "APP_INTERVALS"},
|
||||
IntSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: NewIntSlice(), EnvVars: []string{"APP_INTERVALS"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) {
|
||||
@ -655,7 +658,7 @@ func TestParseMultiIntSliceFromEnvWithDefaults(t *testing.T) {
|
||||
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
IntSliceFlag{Name: "intervals, i", Value: NewIntSlice(1, 2, 5), EnvVar: "APP_INTERVALS"},
|
||||
IntSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: NewIntSlice(1, 2, 5), EnvVars: []string{"APP_INTERVALS"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) {
|
||||
@ -675,7 +678,7 @@ func TestParseMultiIntSliceFromEnvCascade(t *testing.T) {
|
||||
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
IntSliceFlag{Name: "intervals, i", Value: NewIntSlice(), EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"},
|
||||
IntSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: NewIntSlice(), EnvVars: []string{"COMPAT_INTERVALS", "APP_INTERVALS"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) {
|
||||
@ -692,7 +695,7 @@ func TestParseMultiIntSliceFromEnvCascade(t *testing.T) {
|
||||
func TestParseMultiFloat64(t *testing.T) {
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
Float64Flag{Name: "serve, s"},
|
||||
Float64Flag{Name: "serve", Aliases: []string{"s"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Float64("serve") != 10.2 {
|
||||
@ -731,7 +734,7 @@ func TestParseMultiFloat64FromEnv(t *testing.T) {
|
||||
os.Setenv("APP_TIMEOUT_SECONDS", "15.5")
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
Float64Flag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"},
|
||||
Float64Flag{Name: "timeout", Aliases: []string{"t"}, EnvVars: []string{"APP_TIMEOUT_SECONDS"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Float64("timeout") != 15.5 {
|
||||
@ -751,7 +754,7 @@ func TestParseMultiFloat64FromEnvCascade(t *testing.T) {
|
||||
os.Setenv("APP_TIMEOUT_SECONDS", "15.5")
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
Float64Flag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"},
|
||||
Float64Flag{Name: "timeout", Aliases: []string{"t"}, EnvVars: []string{"COMPAT_TIMEOUT_SECONDS", "APP_TIMEOUT_SECONDS"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Float64("timeout") != 15.5 {
|
||||
@ -769,7 +772,7 @@ func TestParseMultiFloat64FromEnvCascade(t *testing.T) {
|
||||
func TestParseMultiBool(t *testing.T) {
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
BoolFlag{Name: "serve, s"},
|
||||
BoolFlag{Name: "serve", Aliases: []string{"s"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Bool("serve") != true {
|
||||
@ -808,7 +811,7 @@ func TestParseMultiBoolFromEnv(t *testing.T) {
|
||||
os.Setenv("APP_DEBUG", "1")
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
BoolFlag{Name: "debug, d", EnvVar: "APP_DEBUG"},
|
||||
BoolFlag{Name: "debug", Aliases: []string{"d"}, EnvVars: []string{"APP_DEBUG"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Bool("debug") != true {
|
||||
@ -828,7 +831,7 @@ func TestParseMultiBoolFromEnvCascade(t *testing.T) {
|
||||
os.Setenv("APP_DEBUG", "1")
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
BoolFlag{Name: "debug, d", EnvVar: "COMPAT_DEBUG,APP_DEBUG"},
|
||||
BoolFlag{Name: "debug", Aliases: []string{"d"}, EnvVars: []string{"COMPAT_DEBUG", "APP_DEBUG"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Bool("debug") != true {
|
||||
@ -846,7 +849,7 @@ func TestParseMultiBoolFromEnvCascade(t *testing.T) {
|
||||
func TestParseMultiBoolTrue(t *testing.T) {
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
BoolFlag{Name: "implode, i", Value: true},
|
||||
BoolFlag{Name: "implode", Aliases: []string{"i"}, Value: true},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Bool("implode") {
|
||||
@ -888,9 +891,10 @@ func TestParseMultiBoolTrueFromEnv(t *testing.T) {
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
BoolFlag{
|
||||
Name: "debug, d",
|
||||
Value: true,
|
||||
EnvVar: "APP_DEBUG",
|
||||
Name: "debug",
|
||||
Aliases: []string{"d"},
|
||||
Value: true,
|
||||
EnvVars: []string{"APP_DEBUG"},
|
||||
},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
@ -912,9 +916,10 @@ func TestParseMultiBoolTrueFromEnvCascade(t *testing.T) {
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
BoolFlag{
|
||||
Name: "debug, d",
|
||||
Value: true,
|
||||
EnvVar: "COMPAT_DEBUG,APP_DEBUG",
|
||||
Name: "debug",
|
||||
Aliases: []string{"d"},
|
||||
Value: true,
|
||||
EnvVars: []string{"COMPAT_DEBUG", "APP_DEBUG"},
|
||||
},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
@ -951,7 +956,7 @@ func (p *Parser) String() string {
|
||||
func TestParseGeneric(t *testing.T) {
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
GenericFlag{Name: "serve, s", Value: &Parser{}},
|
||||
GenericFlag{Name: "serve", Aliases: []string{"s"}, Value: &Parser{}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.Generic("serve"), &Parser{"10", "20"}) {
|
||||
@ -971,7 +976,12 @@ func TestParseGenericFromEnv(t *testing.T) {
|
||||
os.Setenv("APP_SERVE", "20,30")
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
GenericFlag{Name: "serve, s", Value: &Parser{}, EnvVar: "APP_SERVE"},
|
||||
GenericFlag{
|
||||
Name: "serve",
|
||||
Aliases: []string{"s"},
|
||||
Value: &Parser{},
|
||||
EnvVars: []string{"APP_SERVE"},
|
||||
},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.Generic("serve"), &Parser{"20", "30"}) {
|
||||
@ -991,7 +1001,11 @@ func TestParseGenericFromEnvCascade(t *testing.T) {
|
||||
os.Setenv("APP_FOO", "99,2000")
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
GenericFlag{Name: "foos", Value: &Parser{}, EnvVar: "COMPAT_FOO,APP_FOO"},
|
||||
GenericFlag{
|
||||
Name: "foos",
|
||||
Value: &Parser{},
|
||||
EnvVars: []string{"COMPAT_FOO", "APP_FOO"},
|
||||
},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.Generic("foos"), &Parser{"99", "2000"}) {
|
||||
|
8
help.go
8
help.go
@ -208,11 +208,11 @@ func printHelp(out io.Writer, templ string, data interface{}) {
|
||||
func checkVersion(c *Context) bool {
|
||||
found := false
|
||||
if VersionFlag.Name != "" {
|
||||
eachName(VersionFlag.Name, func(name string) {
|
||||
for _, name := range VersionFlag.Names() {
|
||||
if c.Bool(name) {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
@ -220,11 +220,11 @@ func checkVersion(c *Context) bool {
|
||||
func checkHelp(c *Context) bool {
|
||||
found := false
|
||||
if HelpFlag.Name != "" {
|
||||
eachName(HelpFlag.Name, func(name string) {
|
||||
for _, name := range HelpFlag.Names() {
|
||||
if c.Bool(name) {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
14
help_test.go
14
help_test.go
@ -60,13 +60,14 @@ func Test_Help_Custom_Flags(t *testing.T) {
|
||||
}()
|
||||
|
||||
HelpFlag = BoolFlag{
|
||||
Name: "help, x",
|
||||
Usage: "show help",
|
||||
Name: "help",
|
||||
Aliases: []string{"x"},
|
||||
Usage: "show help",
|
||||
}
|
||||
|
||||
app := App{
|
||||
Flags: []Flag{
|
||||
BoolFlag{Name: "foo, h"},
|
||||
BoolFlag{Name: "foo", Aliases: []string{"h"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Bool("h") != true {
|
||||
@ -90,13 +91,14 @@ func Test_Version_Custom_Flags(t *testing.T) {
|
||||
}()
|
||||
|
||||
VersionFlag = BoolFlag{
|
||||
Name: "version, V",
|
||||
Usage: "show version",
|
||||
Name: "version",
|
||||
Aliases: []string{"V"},
|
||||
Usage: "show version",
|
||||
}
|
||||
|
||||
app := App{
|
||||
Flags: []Flag{
|
||||
BoolFlag{Name: "foo, v"},
|
||||
BoolFlag{Name: "foo", Aliases: []string{"v"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Bool("v") != true {
|
||||
|
Loading…
Reference in New Issue
Block a user