Fix:(issue_1500). Fix slice flag value duplication issue

This commit is contained in:
Naveen Gogineni 2022-09-29 10:33:48 -04:00 committed by Dan Buch
parent ea2893084b
commit 924ebdaab2
Signed by: meatballhat
GPG Key ID: A12F782281063434
3 changed files with 59 additions and 4 deletions

View File

@ -956,6 +956,37 @@ func TestApp_UseShortOptionHandlingSubCommand_missing_value(t *testing.T) {
expect(t, err, errors.New("flag needs an argument: -n"))
}
func TestApp_UseShortOptionAfterSliceFlag(t *testing.T) {
var one, two bool
var name string
var sliceValDest StringSlice
var sliceVal []string
expected := "expectedName"
app := newTestApp()
app.UseShortOptionHandling = true
app.Flags = []Flag{
&StringSliceFlag{Name: "env", Aliases: []string{"e"}, Destination: &sliceValDest},
&BoolFlag{Name: "one", Aliases: []string{"o"}},
&BoolFlag{Name: "two", Aliases: []string{"t"}},
&StringFlag{Name: "name", Aliases: []string{"n"}},
}
app.Action = func(c *Context) error {
sliceVal = c.StringSlice("env")
one = c.Bool("one")
two = c.Bool("two")
name = c.String("name")
return nil
}
_ = app.Run([]string{"", "-e", "foo", "-on", expected})
expect(t, sliceVal, []string{"foo"})
expect(t, sliceValDest.Value(), []string{"foo"})
expect(t, one, true)
expect(t, two, false)
expect(t, name, expected)
}
func TestApp_Float64Flag(t *testing.T) {
var meters float64

27
flag.go
View File

@ -126,6 +126,21 @@ type Flag interface {
RunAction(*Context) error
}
// DocGenerationFlag is an interface that allows documentation generation for the flag
type DocGenerationFlag interface {
Flag
// TakesValue returns true if the flag takes a value, otherwise false
TakesValue() bool
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
GetValue() string
// GetEnvVars returns the env vars for this flag
GetEnvVars() []string
}
// DocGenerationSliceFlag extends DocGenerationFlag for slice-based flags.
type DocGenerationSliceFlag interface {
DocGenerationFlag
@ -293,8 +308,14 @@ func formatDefault(format string) string {
}
func stringifyFlag(f Flag) string {
placeholder, usage := unquoteUsage(f.GetUsage())
needsPlaceholder := f.TakesValue()
// enforce DocGeneration interface on flags to avoid reflection
df, ok := f.(DocGenerationFlag)
if !ok {
return ""
}
placeholder, usage := unquoteUsage(df.GetUsage())
needsPlaceholder := df.TakesValue()
if needsPlaceholder && placeholder == "" {
placeholder = defaultPlaceholder
@ -302,7 +323,7 @@ func stringifyFlag(f Flag) string {
defaultValueString := ""
if s := f.GetDefaultText(); s != "" {
if s := df.GetDefaultText(); s != "" {
defaultValueString = fmt.Sprintf(formatDefault("%s"), s)
}

View File

@ -46,7 +46,10 @@ func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComple
}
// swap current argument with the split version
args = append(args[:i], append(shortOpts, args[i+1:]...)...)
// do not include args that parsed correctly so far as it would
// trigger Value.Set() on those args and would result in
// duplicates for slice type flags
args = append(shortOpts, args[i+1:]...)
argsWereSplit = true
break
}