-
Notifications
You must be signed in to change notification settings - Fork 365
Make Value a drop-in replacement for flag.Value #436
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: master
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 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -200,6 +200,15 @@ type Flag struct { | |||||||||||
| type Value interface { | ||||||||||||
| String() string | ||||||||||||
| Set(string) error | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // TypedValue wraps Value but adds an additional Type() string, which | ||||||||||||
| // can be used to special-case things like usage instructions, error | ||||||||||||
| // messages, parsing, etc. | ||||||||||||
| // Its value should be a constant string that identifies the type of | ||||||||||||
| // the underlying flag value. | ||||||||||||
| type TypedValue interface { | ||||||||||||
| Value | ||||||||||||
| Type() string | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
|
|
@@ -398,8 +407,8 @@ func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval stri | |||||||||||
| return nil, err | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| if flag.Value.Type() != ftype { | ||||||||||||
| err := fmt.Errorf("trying to get %s value of flag of type %s", ftype, flag.Value.Type()) | ||||||||||||
| if tvalue, ok := flag.Value.(TypedValue); ok && tvalue.Type() != ftype { | ||||||||||||
| err := fmt.Errorf("trying to get %s value of flag of type %s", ftype, tvalue.Type()) | ||||||||||||
| return nil, err | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
|
|
@@ -597,7 +606,10 @@ func UnquoteUsage(flag *Flag) (name string, usage string) { | |||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| name = flag.Value.Type() | ||||||||||||
| name = "value" | ||||||||||||
| if tvalue, ok := flag.Value.(TypedValue); ok { | ||||||||||||
| name = tvalue.Type() | ||||||||||||
| } | ||||||||||||
| switch name { | ||||||||||||
| case "bool", "boolfunc": | ||||||||||||
| name = "" | ||||||||||||
|
|
@@ -716,8 +728,14 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string { | |||||||||||
| if varname != "" { | ||||||||||||
| line += " " + varname | ||||||||||||
| } | ||||||||||||
| tvalue, tvalueOk := flag.Value.(TypedValue) | ||||||||||||
| if flag.NoOptDefVal != "" { | ||||||||||||
| switch flag.Value.Type() { | ||||||||||||
| if !tvalueOk { | ||||||||||||
| line += fmt.Sprintf(" [=%s]", flag.NoOptDefVal) | ||||||||||||
| return | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| switch tvalue.Type() { | ||||||||||||
| case "string": | ||||||||||||
| line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal) | ||||||||||||
| case "bool", "boolfunc": | ||||||||||||
|
|
@@ -742,7 +760,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string { | |||||||||||
|
|
||||||||||||
| line += usage | ||||||||||||
| if !flag.defaultIsZeroValue() { | ||||||||||||
| if flag.Value.Type() == "string" { | ||||||||||||
|
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. Hm... overlooked this part; this will be tricky, because we're removing the Lines 192 to 196 in 1043857
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. Perhaps this requires a utility to convert/wrap as StdLib value to TypedValue (assign a type), but keeping this Field to implement
Collaborator
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 guess the (philosophical) question is whether the breaking change is introducing this method on the My guess is that there are quite a few instances of people implementing Type because our interface requires it from them, but much fewer (if anyone) actually using the method for anything on their end. |
||||||||||||
| if tvalueOk && tvalue.Type() == "string" { | ||||||||||||
| line += fmt.Sprintf(" (default %q)", flag.DefValue) | ||||||||||||
| } else { | ||||||||||||
| line += fmt.Sprintf(" (default %s)", flag.DefValue) | ||||||||||||
|
|
||||||||||||
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.
This is a tricky one; this change removes the
Type() stringfrom the interface, which means that if someone used this interface for other code, and expect values to have aType()function, they may now end up with a value that doesn't support it.IIUC, the change is meant to make the
Type()optional for functions in this repository, so that they can accept both stdlib Values and spf13/pflag values (which are "richer" as they provide theType()method).An alternative approach would be to;
StdValueinterface, which is the reduced interfaceValueinterface untouched, but (optionally) alias it toTypedValue(mostly to be more expressive in its intent)However, looking at stdlib; it looks like stdlib defines a flag.Value interface (which was already available in go1.12, so safe to use: https://pkg.go.dev/[email protected]#Value); perhaps it's better and more transparent to not define a local interface for that, but to embed the one from stdlib.
spf13/pflag.Valueto useflag.Value(and be more permissive); at a quick glance, none of theFlagSetmethods are part of an interface, so possibly they can be made more permissive. Either that, or new methods to be added (but maybe that's not needed).TypedValueinterface, and make it embed the stdlibflag.Valuespf13/pflag.Valueinterface in favor ofTypedValueorflag.Value("depending on the use-case")So something like;