-
Notifications
You must be signed in to change notification settings - Fork 66
fix: --long= should not consume the next argument #139
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
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 |
|---|---|---|
|
|
@@ -241,16 +241,8 @@ func (fs *FlagSet) parseShortFlag(arg string, args []string) ([]string, error) { | |
| } | ||
|
|
||
| func (fs *FlagSet) parseLongFlag(arg string, args []string) ([]string, error) { | ||
| var ( | ||
| name string | ||
| value string | ||
| ) | ||
|
|
||
| if equals := strings.IndexRune(arg, '='); equals > 0 { | ||
| arg, value = arg[:equals], arg[equals+1:] | ||
| } | ||
|
|
||
| name = strings.TrimPrefix(arg, "--") | ||
| name, value, eqFound := strings.Cut(arg, "=") | ||
| name = strings.TrimPrefix(name, "--") | ||
|
|
||
| f := fs.findLongFlag(name) | ||
| if f == nil { | ||
|
|
@@ -264,22 +256,24 @@ func (fs *FlagSet) parseLongFlag(arg string, args []string) ([]string, error) { | |
| } | ||
| } | ||
|
|
||
| if value == "" { | ||
| if eqFound && f.isBoolFlag && value == "" { | ||
| value = "true" // `--debug=` amounts to `--debug=true` | ||
| } | ||
|
|
||
| if value == "" && !eqFound { | ||
| switch { | ||
| case f.isBoolFlag: | ||
| value = "true" // `-b` or `--foo` default to true | ||
| value = "true" // `--foo` defaults to true | ||
| if len(args) > 0 { | ||
| if _, err := strconv.ParseBool(args[0]); err == nil { | ||
| value = args[0] // `-b true` or `--foo false` should also work | ||
| value = args[0] // `--foo false` should also work | ||
| args = args[1:] | ||
| } | ||
| } | ||
|
Comment on lines
267
to
272
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 is also something strange with the code (the code that already exists) Let's assume --foo expects a string --foo leads to an error But if --foo is a boolean --foo false Leads to this --foo=false This behavior is strange to me, but I'm unsure how other libraries parsing flags do
Author
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. The difference between 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. Exactly
Author
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 would be in favor of that here as well, but I think @peterbourgon wants to keep boolean parsing as is. (Also, that would probably be a very breaking API change now. Don't know how that plays with v4 being in beta.)
Author
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. @ccoVeille As a side note, fs := flag.NewFlagSet("whatever", flag.ContinueOnError)
cfg := struct {
config string
// ...
}{}
fs.StringVar(&cfg.config, "config", "", "Use this configuration file")
// ...whatever -config=foo # No error; config is set to "foo"
whatever -config foo # No error; config is set to "foo"
whatever -config "" # No error; config is set to ""
whatever -config="" # No error; config is set to ""
whatever -config # Error, namely "flag needs an argument: -config"
whatever -config= # No error; config is set to ""I think that the last two should return the same error, but they do not. I'm guessing this is because the parser would need to do extra work (not much but some) to detect the difference between 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. For me, the behavior of the stdlib is fine here. I might look a bit odd, but I'm fine with it. It has its logic. About ff lib, I don't know really. You are fixing a bug with the boolean flag after all, so fixing the bug is somehow already breaking something that was broken 😄, by fixing it. While your fix is fine, I think the issue of removing the random behavior of boolean flag with a parameter should be considered, at least to have a library that behave like other libraries. I don't think it was intended, I would remove it. But, except that your PR is fine, you are fixing the behavior with So for me it can be merged as is 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. For record, I randomly found a discussion about the exact same issue with boolean flag |
||
| case !f.isBoolFlag && len(args) > 0: | ||
| case len(args) > 0: | ||
| value, args = args[0], args[1:] | ||
| case !f.isBoolFlag && len(args) <= 0: | ||
| return nil, fmt.Errorf("missing value") | ||
| default: | ||
| panic("unreachable") | ||
| return nil, fmt.Errorf("missing value") | ||
| } | ||
| } | ||
|
|
||
|
|
||
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.
I would move this into the switch, if possible.
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.
I'm happy to look at that, but I'm not going to push any further changes until we hear from @peterbourgon. I'd like to know what he's thinking about this PR before changing it further.