Merge branch 'master' into v2-master-merge

main
Ajitem Sahasrabuddhe 5 years ago
commit b776c20ef3
No known key found for this signature in database
GPG Key ID: 782DEBC01D3967A5

@ -690,7 +690,7 @@ The code above will use the "load" string as a flag name to get the file name of
a yaml file from the cli.Context. It will then use that file name to initialize a yaml file from the cli.Context. It will then use that file name to initialize
the yaml input source for any flags that are defined on that command. As a note the yaml input source for any flags that are defined on that command. As a note
the "load" flag used would also have to be defined on the command flags in order the "load" flag used would also have to be defined on the command flags in order
for this code snipped to work. for this code snippet to work.
Currently only YAML, JSON, and TOML files are supported but developers can add support Currently only YAML, JSON, and TOML files are supported but developers can add support
for other input sources by implementing the altsrc.InputSourceContext for their for other input sources by implementing the altsrc.InputSourceContext for their

@ -61,8 +61,13 @@ func TestParseAndRunShortOpts(t *testing.T) {
{testArgs: args{"foo", "test", "-af"}, expectedErr: nil, expectedArgs: &args{}}, {testArgs: args{"foo", "test", "-af"}, expectedErr: nil, expectedArgs: &args{}},
{testArgs: args{"foo", "test", "-cf"}, expectedErr: nil, expectedArgs: &args{}}, {testArgs: args{"foo", "test", "-cf"}, expectedErr: nil, expectedArgs: &args{}},
{testArgs: args{"foo", "test", "-acf"}, expectedErr: nil, expectedArgs: &args{}}, {testArgs: args{"foo", "test", "-acf"}, expectedErr: nil, expectedArgs: &args{}},
{testArgs: args{"foo", "test", "--acf"}, expectedErr: errors.New("flag provided but not defined: -acf"), expectedArgs: nil},
{testArgs: args{"foo", "test", "-invalid"}, expectedErr: errors.New("flag provided but not defined: -invalid"), expectedArgs: nil}, {testArgs: args{"foo", "test", "-invalid"}, expectedErr: errors.New("flag provided but not defined: -invalid"), expectedArgs: nil},
{testArgs: args{"foo", "test", "-acf", "-invalid"}, expectedErr: errors.New("flag provided but not defined: -invalid"), expectedArgs: nil},
{testArgs: args{"foo", "test", "--invalid"}, expectedErr: errors.New("flag provided but not defined: -invalid"), expectedArgs: nil},
{testArgs: args{"foo", "test", "-acf", "--invalid"}, expectedErr: errors.New("flag provided but not defined: -invalid"), expectedArgs: nil},
{testArgs: args{"foo", "test", "-acf", "arg1", "-invalid"}, expectedErr: nil, expectedArgs: &args{"arg1", "-invalid"}}, {testArgs: args{"foo", "test", "-acf", "arg1", "-invalid"}, expectedErr: nil, expectedArgs: &args{"arg1", "-invalid"}},
{testArgs: args{"foo", "test", "-acf", "arg1", "--invalid"}, expectedErr: nil, expectedArgs: &args{"arg1", "--invalid"}},
{testArgs: args{"foo", "test", "-acfi", "not-arg", "arg1", "-invalid"}, expectedErr: nil, expectedArgs: &args{"arg1", "-invalid"}}, {testArgs: args{"foo", "test", "-acfi", "not-arg", "arg1", "-invalid"}, expectedErr: nil, expectedArgs: &args{"arg1", "-invalid"}},
{testArgs: args{"foo", "test", "-i", "ivalue"}, expectedErr: nil, expectedArgs: &args{}}, {testArgs: args{"foo", "test", "-i", "ivalue"}, expectedErr: nil, expectedArgs: &args{}},
{testArgs: args{"foo", "test", "-i", "ivalue", "arg1"}, expectedErr: nil, expectedArgs: &args{"arg1"}}, {testArgs: args{"foo", "test", "-i", "ivalue", "arg1"}, expectedErr: nil, expectedArgs: &args{"arg1"}},
@ -84,7 +89,7 @@ func TestParseAndRunShortOpts(t *testing.T) {
&BoolFlag{Name: "abc", Aliases: []string{"a"}}, &BoolFlag{Name: "abc", Aliases: []string{"a"}},
&BoolFlag{Name: "cde", Aliases: []string{"c"}}, &BoolFlag{Name: "cde", Aliases: []string{"c"}},
&BoolFlag{Name: "fgh", Aliases: []string{"f"}}, &BoolFlag{Name: "fgh", Aliases: []string{"f"}},
&StringFlag{Name: "ijk", Aliases:[]string{"i"}}, &StringFlag{Name: "ijk", Aliases: []string{"i"}},
}, },
} }

@ -22,28 +22,35 @@ func parseIter(set *flag.FlagSet, ip iterativeParser, args []string) error {
} }
errStr := err.Error() errStr := err.Error()
trimmed := strings.TrimPrefix(errStr, "flag provided but not defined: ") trimmed := strings.TrimPrefix(errStr, "flag provided but not defined: -")
if errStr == trimmed { if errStr == trimmed {
return err return err
} }
// regenerate the initial args with the split short opts // regenerate the initial args with the split short opts
newArgs := []string{} argsWereSplit := false
for i, arg := range args { for i, arg := range args {
if arg != trimmed { // skip args that are not part of the error message
newArgs = append(newArgs, arg) if name := strings.TrimLeft(arg, "-"); name != trimmed {
continue continue
} }
shortOpts := splitShortOptions(set, trimmed) // if we can't split, the error was accurate
shortOpts := splitShortOptions(set, arg)
if len(shortOpts) == 1 { if len(shortOpts) == 1 {
return err return err
} }
// add each short option and all remaining arguments // swap current argument with the split version
newArgs = append(newArgs, shortOpts...) args = append(args[:i], append(shortOpts, args[i+1:]...)...)
newArgs = append(newArgs, args[i+1:]...) argsWereSplit = true
args = newArgs break
}
// This should be an impossible to reach code path, but in case the arg
// splitting failed to happen, this will prevent infinite loops
if !argsWereSplit {
return err
} }
// Since custom parsing failed, replace the flag set before retrying // Since custom parsing failed, replace the flag set before retrying

Loading…
Cancel
Save