Skip to content

Commit

Permalink
Refactor to re-use more code between Traverse and stripFlags()
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Nephin <dnephin@gmail.com>
  • Loading branch information
dnephin committed Jan 17, 2018
1 parent b1195d1 commit 46f41fc
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 28 deletions.
56 changes: 28 additions & 28 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,30 +436,7 @@ func (c *Command) VersionTemplate() string {
`
}

func hasNoOptDefVal(name string, fs *flag.FlagSet) bool {
flag := fs.Lookup(name)
if flag == nil {
return false
}
return flag.NoOptDefVal != ""
}

func shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool {
if len(name) == 0 {
return false
}

flag := fs.ShorthandLookup(name[:1])
if flag == nil {
return false
}
return flag.NoOptDefVal != ""
}

func stripFlags(args []string, c *Command) []string {
if len(args) == 0 {
return args
}
c.mergePersistentFlags()

commands := []string{}
Expand All @@ -470,11 +447,11 @@ Loop:
s := args[0]
args = args[1:]
switch {
case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):
case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasDefaultValue(s[2:], flags):
// If '--flag arg' then
// delete arg from args.
fallthrough // (do the same as below)
case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags):
case isShortFlagWithNoDefaultValue(s, flags):
// If '-f arg' then
// delete 'arg' from args or break the loop if len(args) <= 1.
if len(args) <= 1 {
Expand All @@ -491,6 +468,30 @@ Loop:
return commands
}

func hasDefaultValue(name string, fs *flag.FlagSet) bool {
flag := fs.Lookup(name)
if flag == nil {
return false
}
return flag.NoOptDefVal != ""
}

func isShortFlagWithNoDefaultValue(arg string, flags *flag.FlagSet) bool {
return strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") && len(arg) == 2 && !shortFlagHasDefaultValue(arg[1:], flags)
}

func shortFlagHasDefaultValue(name string, fs *flag.FlagSet) bool {
if len(name) == 0 {
return false
}

flag := fs.ShorthandLookup(name[:1])
if flag == nil {
return false
}
return flag.NoOptDefVal != ""
}

// argsMinusFirstX removes only the first x from args. Otherwise, commands that look like
// openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]).
func argsMinusFirstX(args []string, x string) []string {
Expand Down Expand Up @@ -582,12 +583,11 @@ func (c *Command) Traverse(args []string) (*Command, []string, error) {
switch {
// A long flag with a space separated value
case strings.HasPrefix(arg, "--") && !strings.Contains(arg, "="):
// TODO: this isn't quite right, we should really check ahead for 'true' or 'false'
inFlag = !hasNoOptDefVal(arg[2:], c.Flags())
inFlag = !hasDefaultValue(arg[2:], c.Flags())
flags = append(flags, arg)
continue
// A short flag with a space separated value
case strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") && len(arg) == 2 && !shortHasNoOptDefVal(arg[1:], c.Flags()):
case isShortFlagWithNoDefaultValue(arg, c.Flags()):
inFlag = true
flags = append(flags, arg)
continue
Expand Down
21 changes: 21 additions & 0 deletions command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1552,6 +1552,27 @@ func TestTraverseWithTwoSubcommands(t *testing.T) {
}
}

func TestTraversalWithPersistentFlags(t *testing.T) {
rootCmd := &Command{Use: "root", TraverseChildren: true}
rootCmd.PersistentFlags().BoolP("toggle", "t", false, "Help message for toggle")
subCmd := &Command{
Use: "sub",
DisableFlagParsing: true,
}
rootCmd.AddCommand(subCmd)

c, args, err := rootCmd.Traverse([]string{"-t", "sub", "abc"})
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if len(args) != 1 && args[0] != "abc" {
t.Errorf("Wrong args: %v", args)
}
if c.Name() != subCmd.Name() {
t.Errorf("Expected command: %q, got: %q", subCmd.Name(), c.Name())
}
}

// TestUpdateName checks if c.Name() updates on changed c.Use.
// Related to https://github.com/spf13/cobra/pull/422#discussion_r143918343.
func TestUpdateName(t *testing.T) {
Expand Down

0 comments on commit 46f41fc

Please sign in to comment.