Merge branch 'master' into inconsistent-version-behaviour-v2

This commit is contained in:
Ajitem Sahasrabuddhe 2019-11-28 13:27:52 +05:30 committed by GitHub
commit 286ffd2ccd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 81 additions and 7 deletions

View File

@ -7,12 +7,23 @@ assignees: lynncyrin
--- ---
## my urfave/cli version is
_**( Put the version of urfave/cli that you are using here )**_
## Checklist ## Checklist
* [ ] Are you running the latest v1 release? The list of releases is [here](https://github.com/urfave/cli/releases). * [ ] Are you running the latest v1 release? The list of releases is [here](https://github.com/urfave/cli/releases).
* [ ] Did you check the manual for your release? The v1 manual is [here](https://github.com/urfave/cli/blob/master/docs/v1/manual.md) * [ ] Did you check the manual for your release? The v1 manual is [here](https://github.com/urfave/cli/blob/master/docs/v1/manual.md)
* [ ] Did you perform a search about this problem? Here's the [Github guide](https://help.github.com/en/github/managing-your-work-on-github/using-search-to-filter-issues-and-pull-requests) about searching. * [ ] Did you perform a search about this problem? Here's the [Github guide](https://help.github.com/en/github/managing-your-work-on-github/using-search-to-filter-issues-and-pull-requests) about searching.
## Packaging Setup
- [ ] My project is using go modules.
- [ ] My project is using vendoring.
- [ ] My project is automatically downloading the latest version.
- [ ] I am unsure of what my packaging setup is.
## Describe the bug ## Describe the bug
A clear and concise description of what the bug is. A clear and concise description of what the bug is.

View File

@ -7,12 +7,23 @@ assignees: ''
--- ---
## my urfave/cli version is
_**( Put the version of urfave/cli that you are using here )**_
## Checklist ## Checklist
* [ ] Are you running the latest v2 release? The list of releases is [here](https://github.com/urfave/cli/releases). * [ ] Are you running the latest v2 release? The list of releases is [here](https://github.com/urfave/cli/releases).
* [ ] Did you check the manual for your release? The v2 manual is [here](https://github.com/urfave/cli/blob/master/docs/v2/manual.md) * [ ] Did you check the manual for your release? The v2 manual is [here](https://github.com/urfave/cli/blob/master/docs/v2/manual.md)
* [ ] Did you perform a search about this problem? Here's the [Github guide](https://help.github.com/en/github/managing-your-work-on-github/using-search-to-filter-issues-and-pull-requests) about searching. * [ ] Did you perform a search about this problem? Here's the [Github guide](https://help.github.com/en/github/managing-your-work-on-github/using-search-to-filter-issues-and-pull-requests) about searching.
## Packaging Setup
- [ ] My project is using go modules.
- [ ] My project is using vendoring.
- [ ] My project is automatically downloading the latest version.
- [ ] I am unsure of what my packaging setup is.
## Describe the bug ## Describe the bug
A clear and concise description of what the bug is. A clear and concise description of what the bug is.

4
app.go
View File

@ -222,7 +222,7 @@ func (a *App) Run(arguments []string) (err error) {
return err return err
} }
err = parseIter(set, a, arguments[1:]) err = parseIter(set, a, arguments[1:], shellComplete)
nerr := normalizeFlags(a.Flags, set) nerr := normalizeFlags(a.Flags, set)
context := NewContext(a, set, nil) context := NewContext(a, set, nil)
if nerr != nil { if nerr != nil {
@ -348,7 +348,7 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
return err return err
} }
err = parseIter(set, a, ctx.Args().Tail()) err = parseIter(set, a, ctx.Args().Tail(), ctx.shellComplete)
nerr := normalizeFlags(a.Flags, set) nerr := normalizeFlags(a.Flags, set)
context := NewContext(a, set, ctx) context := NewContext(a, set, ctx)

View File

@ -100,7 +100,7 @@ func (c *Command) Run(ctx *Context) (err error) {
c.UseShortOptionHandling = true c.UseShortOptionHandling = true
} }
set, err := c.parseFlags(ctx.Args()) set, err := c.parseFlags(ctx.Args(), ctx.shellComplete)
context := NewContext(ctx.App, set, ctx) context := NewContext(ctx.App, set, ctx)
context.Command = c context.Command = c
@ -174,7 +174,7 @@ func (c *Command) useShortOptionHandling() bool {
return c.UseShortOptionHandling return c.UseShortOptionHandling
} }
func (c *Command) parseFlags(args Args) (*flag.FlagSet, error) { func (c *Command) parseFlags(args Args, shellComplete bool) (*flag.FlagSet, error) {
set, err := c.newFlagSet() set, err := c.newFlagSet()
if err != nil { if err != nil {
return nil, err return nil, err
@ -184,7 +184,7 @@ func (c *Command) parseFlags(args Args) (*flag.FlagSet, error) {
return set, set.Parse(append([]string{"--"}, args.Tail()...)) return set, set.Parse(append([]string{"--"}, args.Tail()...))
} }
err = parseIter(set, c, args.Tail()) err = parseIter(set, c, args.Tail(), shellComplete)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -1,6 +1,7 @@
package cli package cli
import ( import (
"bytes"
"errors" "errors"
"flag" "flag"
"fmt" "fmt"
@ -329,3 +330,49 @@ func TestCommandSkipFlagParsing(t *testing.T) {
expect(t, args, c.expectedArgs) expect(t, args, c.expectedArgs)
} }
} }
func TestCommand_Run_CustomShellCompleteAcceptsMalformedFlags(t *testing.T) {
cases := []struct {
testArgs args
expectedOut string
}{
{testArgs: args{"--undefined"}, expectedOut: "found 0 args"},
{testArgs: args{"--number"}, expectedOut: "found 0 args"},
{testArgs: args{"--number", "fourty-two"}, expectedOut: "found 0 args"},
{testArgs: args{"--number", "42"}, expectedOut: "found 0 args"},
{testArgs: args{"--number", "42", "newArg"}, expectedOut: "found 1 args"},
}
for _, c := range cases {
var outputBuffer bytes.Buffer
app := &App{
Writer: &outputBuffer,
EnableBashCompletion: true,
Commands: []*Command{
{
Name: "bar",
Usage: "this is for testing",
Flags: []Flag{
&IntFlag{
Name: "number",
Usage: "A number to parse",
},
},
BashComplete: func(c *Context) {
fmt.Fprintf(c.App.Writer, "found %d args", c.NArg())
},
},
},
}
osArgs := args{"foo", "bar"}
osArgs = append(osArgs, c.testArgs...)
osArgs = append(osArgs, "--generate-bash-completion")
err := app.Run(osArgs)
stdout := outputBuffer.String()
expect(t, err, nil)
expect(t, stdout, c.expectedOut)
}
}

View File

@ -11,13 +11,18 @@ type iterativeParser interface {
} }
// To enable short-option handling (e.g., "-it" vs "-i -t") we have to // To enable short-option handling (e.g., "-it" vs "-i -t") we have to
// iteratively catch parsing errors. This way we achieve LR parsing without // iteratively catch parsing errors. This way we achieve LR parsing without
// transforming any arguments. Otherwise, there is no way we can discriminate // transforming any arguments. Otherwise, there is no way we can discriminate
// combined short options from common arguments that should be left untouched. // combined short options from common arguments that should be left untouched.
func parseIter(set *flag.FlagSet, ip iterativeParser, args []string) error { // Pass `shellComplete` to continue parsing options on failure during shell
// completion when, the user-supplied options may be incomplete.
func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComplete bool) error {
for { for {
err := set.Parse(args) err := set.Parse(args)
if !ip.useShortOptionHandling() || err == nil { if !ip.useShortOptionHandling() || err == nil {
if shellComplete {
return nil
}
return err return err
} }