Merge branch 'master' into master
This commit is contained in:
commit
40263f4d6a
@ -22,15 +22,15 @@ func nestedVal(name string, tree map[interface{}]interface{}) (interface{}, bool
|
|||||||
if sections := strings.Split(name, "."); len(sections) > 1 {
|
if sections := strings.Split(name, "."); len(sections) > 1 {
|
||||||
node := tree
|
node := tree
|
||||||
for _, section := range sections[:len(sections)-1] {
|
for _, section := range sections[:len(sections)-1] {
|
||||||
if child, ok := node[section]; !ok {
|
child, ok := node[section]
|
||||||
|
if !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
} else {
|
|
||||||
if ctype, ok := child.(map[interface{}]interface{}); !ok {
|
|
||||||
return nil, false
|
|
||||||
} else {
|
|
||||||
node = ctype
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ctype, ok := child.(map[interface{}]interface{})
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
node = ctype
|
||||||
}
|
}
|
||||||
if val, ok := node[sections[len(sections)-1]]; ok {
|
if val, ok := node[sections[len(sections)-1]]; ok {
|
||||||
return val, true
|
return val, true
|
||||||
|
@ -66,9 +66,9 @@ func unmarshalMap(i interface{}) (ret map[interface{}]interface{}, err error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *tomlMap) UnmarshalTOML(i interface{}) error {
|
func (tm *tomlMap) UnmarshalTOML(i interface{}) error {
|
||||||
if tmp, err := unmarshalMap(i); err == nil {
|
if tmp, err := unmarshalMap(i); err == nil {
|
||||||
self.Map = tmp
|
tm.Map = tmp
|
||||||
} else {
|
} else {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ func loadDataFrom(filePath string) ([]byte, error) {
|
|||||||
return nil, fmt.Errorf("Cannot read from file: '%s' because it does not exist.", filePath)
|
return nil, fmt.Errorf("Cannot read from file: '%s' because it does not exist.", filePath)
|
||||||
}
|
}
|
||||||
return ioutil.ReadFile(filePath)
|
return ioutil.ReadFile(filePath)
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("unable to determine how to load from path %s", filePath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("unable to determine how to load from path %s", filePath)
|
||||||
}
|
}
|
||||||
|
4
app.go
4
app.go
@ -503,7 +503,7 @@ func HandleAction(action interface{}, context *Context) (err error) {
|
|||||||
} else if a, ok := action.(func(*Context)); ok { // deprecated function signature
|
} else if a, ok := action.(func(*Context)); ok { // deprecated function signature
|
||||||
a(context)
|
a(context)
|
||||||
return nil
|
return nil
|
||||||
} else {
|
|
||||||
return errInvalidActionType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return errInvalidActionType
|
||||||
}
|
}
|
||||||
|
@ -497,7 +497,6 @@ func TestApp_Float64Flag(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestApp_ParseSliceFlags(t *testing.T) {
|
func TestApp_ParseSliceFlags(t *testing.T) {
|
||||||
var parsedOption, firstArg string
|
|
||||||
var parsedIntSlice []int
|
var parsedIntSlice []int
|
||||||
var parsedStringSlice []string
|
var parsedStringSlice []string
|
||||||
|
|
||||||
@ -511,8 +510,6 @@ func TestApp_ParseSliceFlags(t *testing.T) {
|
|||||||
Action: func(c *Context) error {
|
Action: func(c *Context) error {
|
||||||
parsedIntSlice = c.IntSlice("p")
|
parsedIntSlice = c.IntSlice("p")
|
||||||
parsedStringSlice = c.StringSlice("ip")
|
parsedStringSlice = c.StringSlice("ip")
|
||||||
parsedOption = c.String("option")
|
|
||||||
firstArg = c.Args().First()
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ func (c *Context) IsSet(name string) bool {
|
|||||||
// change in version 2 to add `IsSet` to the Flag interface to push the
|
// change in version 2 to add `IsSet` to the Flag interface to push the
|
||||||
// responsibility closer to where the information required to determine
|
// responsibility closer to where the information required to determine
|
||||||
// whether a flag is set by non-standard means such as environment
|
// whether a flag is set by non-standard means such as environment
|
||||||
// variables is avaliable.
|
// variables is available.
|
||||||
//
|
//
|
||||||
// See https://github.com/urfave/cli/issues/294 for additional discussion
|
// See https://github.com/urfave/cli/issues/294 for additional discussion
|
||||||
flags := c.Command.Flags
|
flags := c.Command.Flags
|
||||||
|
20
flag.go
20
flag.go
@ -37,6 +37,14 @@ var HelpFlag Flag = BoolFlag{
|
|||||||
// to display a flag.
|
// to display a flag.
|
||||||
var FlagStringer FlagStringFunc = stringifyFlag
|
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.
|
// FlagsByName is a slice of Flag.
|
||||||
type FlagsByName []Flag
|
type FlagsByName []Flag
|
||||||
|
|
||||||
@ -710,13 +718,13 @@ func stringifyFlag(f Flag) string {
|
|||||||
|
|
||||||
switch f.(type) {
|
switch f.(type) {
|
||||||
case IntSliceFlag:
|
case IntSliceFlag:
|
||||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
return FlagEnvHinter(fv.FieldByName("EnvVar").String(),
|
||||||
stringifyIntSliceFlag(f.(IntSliceFlag)))
|
stringifyIntSliceFlag(f.(IntSliceFlag)))
|
||||||
case Int64SliceFlag:
|
case Int64SliceFlag:
|
||||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
return FlagEnvHinter(fv.FieldByName("EnvVar").String(),
|
||||||
stringifyInt64SliceFlag(f.(Int64SliceFlag)))
|
stringifyInt64SliceFlag(f.(Int64SliceFlag)))
|
||||||
case StringSliceFlag:
|
case StringSliceFlag:
|
||||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
return FlagEnvHinter(fv.FieldByName("EnvVar").String(),
|
||||||
stringifyStringSliceFlag(f.(StringSliceFlag)))
|
stringifyStringSliceFlag(f.(StringSliceFlag)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,8 +752,8 @@ func stringifyFlag(f Flag) string {
|
|||||||
|
|
||||||
usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultValueString))
|
usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultValueString))
|
||||||
|
|
||||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
return FlagEnvHinter(fv.FieldByName("EnvVar").String(),
|
||||||
fmt.Sprintf("%s\t%s", prefixedNames(fv.FieldByName("Name").String(), placeholder), usageWithDefault))
|
fmt.Sprintf("%s\t%s", FlagNamePrefixer(fv.FieldByName("Name").String(), placeholder), usageWithDefault))
|
||||||
}
|
}
|
||||||
|
|
||||||
func stringifyIntSliceFlag(f IntSliceFlag) string {
|
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))
|
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 {
|
var stringSliceFlagTests = []struct {
|
||||||
name string
|
name string
|
||||||
value *StringSlice
|
value *StringSlice
|
||||||
|
15
funcs.go
15
funcs.go
@ -23,10 +23,19 @@ type CommandNotFoundFunc func(*Context, string)
|
|||||||
// is displayed and the execution is interrupted.
|
// is displayed and the execution is interrupted.
|
||||||
type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error
|
type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error
|
||||||
|
|
||||||
|
// ExitErrHandlerFunc is executed if provided in order to handle ExitError values
|
||||||
|
// returned by Actions and Before/After functions.
|
||||||
|
type ExitErrHandlerFunc func(context *Context, err error)
|
||||||
|
|
||||||
// FlagStringFunc is used by the help generation to display a flag, which is
|
// FlagStringFunc is used by the help generation to display a flag, which is
|
||||||
// expected to be a single line.
|
// expected to be a single line.
|
||||||
type FlagStringFunc func(Flag) string
|
type FlagStringFunc func(Flag) string
|
||||||
|
|
||||||
// ExitErrHandlerFunc is executed if provided in order to handle ExitError values
|
// FlagNamePrefixFunc is used by the default FlagStringFunc to create prefix
|
||||||
// returned by Actions and Before/After functions.
|
// text for a flag's full name.
|
||||||
type ExitErrHandlerFunc func(context *Context, err error)
|
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