Commit 98b90475 authored by David Symonds's avatar David Symonds

flag: change Set method Value interface to return error instead of bool.

This yields much better error messages when a bad flag value is given.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5498078
parent 57c9bb4a
...@@ -79,10 +79,10 @@ func newBoolValue(val bool, p *bool) *boolValue { ...@@ -79,10 +79,10 @@ func newBoolValue(val bool, p *bool) *boolValue {
return (*boolValue)(p) return (*boolValue)(p)
} }
func (b *boolValue) Set(s string) bool { func (b *boolValue) Set(s string) error {
v, err := strconv.ParseBool(s) v, err := strconv.ParseBool(s)
*b = boolValue(v) *b = boolValue(v)
return err == nil return err
} }
func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) } func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }
...@@ -95,10 +95,10 @@ func newIntValue(val int, p *int) *intValue { ...@@ -95,10 +95,10 @@ func newIntValue(val int, p *int) *intValue {
return (*intValue)(p) return (*intValue)(p)
} }
func (i *intValue) Set(s string) bool { func (i *intValue) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64) v, err := strconv.ParseInt(s, 0, 64)
*i = intValue(v) *i = intValue(v)
return err == nil return err
} }
func (i *intValue) String() string { return fmt.Sprintf("%v", *i) } func (i *intValue) String() string { return fmt.Sprintf("%v", *i) }
...@@ -111,10 +111,10 @@ func newInt64Value(val int64, p *int64) *int64Value { ...@@ -111,10 +111,10 @@ func newInt64Value(val int64, p *int64) *int64Value {
return (*int64Value)(p) return (*int64Value)(p)
} }
func (i *int64Value) Set(s string) bool { func (i *int64Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64) v, err := strconv.ParseInt(s, 0, 64)
*i = int64Value(v) *i = int64Value(v)
return err == nil return err
} }
func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) } func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) }
...@@ -127,10 +127,10 @@ func newUintValue(val uint, p *uint) *uintValue { ...@@ -127,10 +127,10 @@ func newUintValue(val uint, p *uint) *uintValue {
return (*uintValue)(p) return (*uintValue)(p)
} }
func (i *uintValue) Set(s string) bool { func (i *uintValue) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 64) v, err := strconv.ParseUint(s, 0, 64)
*i = uintValue(v) *i = uintValue(v)
return err == nil return err
} }
func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) } func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) }
...@@ -143,10 +143,10 @@ func newUint64Value(val uint64, p *uint64) *uint64Value { ...@@ -143,10 +143,10 @@ func newUint64Value(val uint64, p *uint64) *uint64Value {
return (*uint64Value)(p) return (*uint64Value)(p)
} }
func (i *uint64Value) Set(s string) bool { func (i *uint64Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 64) v, err := strconv.ParseUint(s, 0, 64)
*i = uint64Value(v) *i = uint64Value(v)
return err == nil return err
} }
func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) } func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) }
...@@ -159,9 +159,9 @@ func newStringValue(val string, p *string) *stringValue { ...@@ -159,9 +159,9 @@ func newStringValue(val string, p *string) *stringValue {
return (*stringValue)(p) return (*stringValue)(p)
} }
func (s *stringValue) Set(val string) bool { func (s *stringValue) Set(val string) error {
*s = stringValue(val) *s = stringValue(val)
return true return nil
} }
func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) } func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) }
...@@ -174,10 +174,10 @@ func newFloat64Value(val float64, p *float64) *float64Value { ...@@ -174,10 +174,10 @@ func newFloat64Value(val float64, p *float64) *float64Value {
return (*float64Value)(p) return (*float64Value)(p)
} }
func (f *float64Value) Set(s string) bool { func (f *float64Value) Set(s string) error {
v, err := strconv.ParseFloat(s, 64) v, err := strconv.ParseFloat(s, 64)
*f = float64Value(v) *f = float64Value(v)
return err == nil return err
} }
func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) } func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) }
...@@ -190,10 +190,10 @@ func newDurationValue(val time.Duration, p *time.Duration) *durationValue { ...@@ -190,10 +190,10 @@ func newDurationValue(val time.Duration, p *time.Duration) *durationValue {
return (*durationValue)(p) return (*durationValue)(p)
} }
func (d *durationValue) Set(s string) bool { func (d *durationValue) Set(s string) error {
v, err := time.ParseDuration(s) v, err := time.ParseDuration(s)
*d = durationValue(v) *d = durationValue(v)
return err == nil return err
} }
func (d *durationValue) String() string { return (*time.Duration)(d).String() } func (d *durationValue) String() string { return (*time.Duration)(d).String() }
...@@ -202,7 +202,7 @@ func (d *durationValue) String() string { return (*time.Duration)(d).String() } ...@@ -202,7 +202,7 @@ func (d *durationValue) String() string { return (*time.Duration)(d).String() }
// (The default value is represented as a string.) // (The default value is represented as a string.)
type Value interface { type Value interface {
String() string String() string
Set(string) bool Set(string) error
} }
// ErrorHandling defines how to handle flag parsing errors. // ErrorHandling defines how to handle flag parsing errors.
...@@ -293,27 +293,25 @@ func Lookup(name string) *Flag { ...@@ -293,27 +293,25 @@ func Lookup(name string) *Flag {
return commandLine.formal[name] return commandLine.formal[name]
} }
// Set sets the value of the named flag. It returns true if the set succeeded; false if // Set sets the value of the named flag.
// there is no such flag defined. func (f *FlagSet) Set(name, value string) error {
func (f *FlagSet) Set(name, value string) bool {
flag, ok := f.formal[name] flag, ok := f.formal[name]
if !ok { if !ok {
return false return fmt.Errorf("no such flag -%v", name)
} }
ok = flag.Value.Set(value) err := flag.Value.Set(value)
if !ok { if err != nil {
return false return err
} }
if f.actual == nil { if f.actual == nil {
f.actual = make(map[string]*Flag) f.actual = make(map[string]*Flag)
} }
f.actual[name] = flag f.actual[name] = flag
return true return nil
} }
// Set sets the value of the named command-line flag. It returns true if the // Set sets the value of the named command-line flag.
// set succeeded; false if there is no such flag defined. func Set(name, value string) error {
func Set(name, value string) bool {
return commandLine.Set(name, value) return commandLine.Set(name, value)
} }
...@@ -688,8 +686,8 @@ func (f *FlagSet) parseOne() (bool, error) { ...@@ -688,8 +686,8 @@ func (f *FlagSet) parseOne() (bool, error) {
} }
if fv, ok := flag.Value.(*boolValue); ok { // special case: doesn't need an arg if fv, ok := flag.Value.(*boolValue); ok { // special case: doesn't need an arg
if has_value { if has_value {
if !fv.Set(value) { if err := fv.Set(value); err != nil {
f.failf("invalid boolean value %q for flag: -%s", value, name) f.failf("invalid boolean value %q for -%s: %v", value, name, err)
} }
} else { } else {
fv.Set("true") fv.Set("true")
...@@ -704,9 +702,8 @@ func (f *FlagSet) parseOne() (bool, error) { ...@@ -704,9 +702,8 @@ func (f *FlagSet) parseOne() (bool, error) {
if !has_value { if !has_value {
return false, f.failf("flag needs an argument: -%s", name) return false, f.failf("flag needs an argument: -%s", name)
} }
ok = flag.Value.Set(value) if err := flag.Value.Set(value); err != nil {
if !ok { return false, f.failf("invalid value %q for flag -%s: %v", value, name, err)
return false, f.failf("invalid value %q for flag: -%s", value, name)
} }
} }
if f.actual == nil { if f.actual == nil {
......
...@@ -184,9 +184,9 @@ func (f *flagVar) String() string { ...@@ -184,9 +184,9 @@ func (f *flagVar) String() string {
return fmt.Sprint([]string(*f)) return fmt.Sprint([]string(*f))
} }
func (f *flagVar) Set(value string) bool { func (f *flagVar) Set(value string) error {
*f = append(*f, value) *f = append(*f, value)
return true return nil
} }
func TestUserDefined(t *testing.T) { func TestUserDefined(t *testing.T) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment