Merge pull request #283 from codegangsta/really-skip-flag-parsing

Really skip flag parsing
This commit is contained in:
Jesse Szwedko 2015-11-20 13:56:42 -08:00
commit 0302d3914d
3 changed files with 61 additions and 59 deletions

View File

@ -74,34 +74,40 @@ func (c Command) Run(ctx *Context) error {
set := flagSet(c.Name, c.Flags) set := flagSet(c.Name, c.Flags)
set.SetOutput(ioutil.Discard) set.SetOutput(ioutil.Discard)
firstFlagIndex := -1
terminatorIndex := -1
for index, arg := range ctx.Args() {
if arg == "--" {
terminatorIndex = index
break
} else if strings.HasPrefix(arg, "-") && firstFlagIndex == -1 {
firstFlagIndex = index
}
}
var err error var err error
if firstFlagIndex > -1 && !c.SkipFlagParsing { if !c.SkipFlagParsing {
args := ctx.Args() firstFlagIndex := -1
regularArgs := make([]string, len(args[1:firstFlagIndex])) terminatorIndex := -1
copy(regularArgs, args[1:firstFlagIndex]) for index, arg := range ctx.Args() {
if arg == "--" {
var flagArgs []string terminatorIndex = index
if terminatorIndex > -1 { break
flagArgs = args[firstFlagIndex:terminatorIndex] } else if strings.HasPrefix(arg, "-") && firstFlagIndex == -1 {
regularArgs = append(regularArgs, args[terminatorIndex:]...) firstFlagIndex = index
} else { }
flagArgs = args[firstFlagIndex:]
} }
err = set.Parse(append(flagArgs, regularArgs...)) if firstFlagIndex > -1 {
args := ctx.Args()
regularArgs := make([]string, len(args[1:firstFlagIndex]))
copy(regularArgs, args[1:firstFlagIndex])
var flagArgs []string
if terminatorIndex > -1 {
flagArgs = args[firstFlagIndex:terminatorIndex]
regularArgs = append(regularArgs, args[terminatorIndex:]...)
} else {
flagArgs = args[firstFlagIndex:]
}
err = set.Parse(append(flagArgs, regularArgs...))
} else {
err = set.Parse(ctx.Args().Tail())
}
} else { } else {
err = set.Parse(ctx.Args().Tail()) if c.SkipFlagParsing {
err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...))
}
} }
if err != nil { if err != nil {

View File

@ -1,47 +1,43 @@
package cli package cli
import ( import (
"errors"
"flag" "flag"
"testing" "testing"
) )
func TestCommandDoNotIgnoreFlags(t *testing.T) { func TestCommandFlagParsing(t *testing.T) {
app := NewApp() cases := []struct {
set := flag.NewFlagSet("test", 0) testArgs []string
test := []string{"blah", "blah", "-break"} skipFlagParsing bool
set.Parse(test) expectedErr error
}{
c := NewContext(app, set, nil) {[]string{"blah", "blah", "-break"}, false, errors.New("flag provided but not defined: -break")}, // Test normal "not ignoring flags" flow
{[]string{"blah", "blah"}, true, nil}, // Test SkipFlagParsing without any args that look like flags
command := Command{ {[]string{"blah", "-break"}, true, nil}, // Test SkipFlagParsing with random flag arg
Name: "test-cmd", {[]string{"blah", "-help"}, true, nil}, // Test SkipFlagParsing with "special" help flag arg
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(_ *Context) {},
} }
err := command.Run(c)
expect(t, err.Error(), "flag provided but not defined: -break") for _, c := range cases {
} app := NewApp()
set := flag.NewFlagSet("test", 0)
set.Parse(c.testArgs)
func TestCommandIgnoreFlags(t *testing.T) { context := NewContext(app, set, nil)
app := NewApp()
set := flag.NewFlagSet("test", 0)
test := []string{"blah", "blah", "-break"}
set.Parse(test)
c := NewContext(app, set, nil) command := Command{
Name: "test-cmd",
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(_ *Context) {},
}
command := Command{ command.SkipFlagParsing = c.skipFlagParsing
Name: "test-cmd",
Aliases: []string{"tc"}, err := command.Run(context)
Usage: "this is for testing",
Description: "testing", expect(t, err, c.expectedErr)
Action: func(_ *Context) {}, expect(t, []string(context.Args()), c.testArgs)
SkipFlagParsing: true,
} }
err := command.Run(c)
expect(t, err, nil)
} }

View File

@ -7,13 +7,13 @@ import (
/* Test Helpers */ /* Test Helpers */
func expect(t *testing.T, a interface{}, b interface{}) { func expect(t *testing.T, a interface{}, b interface{}) {
if a != b { if !reflect.DeepEqual(a, b) {
t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a)) t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
} }
} }
func refute(t *testing.T, a interface{}, b interface{}) { func refute(t *testing.T, a interface{}, b interface{}) {
if a == b { if reflect.DeepEqual(a, b) {
t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a)) t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
} }
} }