-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Share more code between Traverse and stripFlags #617
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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{} | ||
|
@@ -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 { | ||
|
@@ -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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this func partly copied from pr 615 func hasDefaultShort_s(arg string, c *Command) bool { // should probably return (bool, error)
if strings.HasPrefix(arg, "-") {
if !strings.Contains(arg, "=") {
// needs to change to a range to deal with -abcd goldfish
if len(arg) == 2 {
flag := c.Flags().ShorthandLookup(arg[1:])
if flag == nil {
return false
}
//shortHasNoOptDefVal
return flag.NoOptDefVal != ""
}
}
}
return false
} It's also a good place to solve the I think some of the issues and confusion are created as this code can't be sure if a flag exists and have to choose a default. Is it possible to
A lot of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Sorry, I don't understand why you feel it is confusing. Does the name not reflect the behaviour of the function?
What would be the error case?
This is the code which checks flag, I don't understand what we could do be fore this.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you would rather I omit the refactoring, and only add the test case for now, I'm fine with that. |
||
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 { | ||
|
@@ -576,16 +577,17 @@ func (c *Command) Traverse(args []string) (*Command, []string, error) { | |
flags := []string{} | ||
inFlag := false | ||
|
||
c.mergePersistentFlags() | ||
|
||
for i, arg := range args { | ||
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' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed this TODO because it's actually not an issue. The current behaviour is correct and matches |
||
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()): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I may well be wrong, but my first glance makes me believe this may not be right. For short flags one could do (pseudo code)
and on the command line do: And be perfectly correct. This code will, I think, look only at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yes, that still needs to be solved, however that's not related to the original issue in #615 , right? The bug was that the flags were not in Should we open a new issue for that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function does seem to have a number of unrelated problems. I guess the reason it kinda works is because the call the ParseFlags() near the end does the merge. Merging (like in 615) at least seems to give this function a chance to be better. Can you add a bunch of new _test for Traverse as you try to clean things up here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are already a few tests for this function. I can add more as issues are fixed, but I think it would be good to merge this now, since it does fix one of the issues. I opened #618 to track the other issue you found. |
||
inFlag = true | ||
flags = append(flags, arg) | ||
continue | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really the right name? I know it is shorter/pithier than NoOptDefVal but isn't default value actually the value set at declaration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, true. It's actually checking to see if the
Value
type used by the flag has a default, so maybeflagValueHasDefault
would be more correct.