From a6d986bd8a5db918a92456b4a4c44075c13a20da Mon Sep 17 00:00:00 2001 From: Rick Arnold Date: Sat, 22 Dec 2012 13:34:48 -0500 Subject: [PATCH] flag: add implicit boolFlag interface Any flag.Value that has an IsBoolFlag method that returns true will be treated as a bool flag type during parsing. Fixes #4262. R=bradfitz, rsc CC=golang-dev https://golang.org/cl/6944064 --- src/pkg/flag/flag.go | 15 +++++++++++++- src/pkg/flag/flag_test.go | 41 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/pkg/flag/flag.go b/src/pkg/flag/flag.go index bbabd88c8c..85dd8c3b37 100644 --- a/src/pkg/flag/flag.go +++ b/src/pkg/flag/flag.go @@ -91,6 +91,15 @@ func (b *boolValue) Set(s string) error { func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) } +func (b *boolValue) IsBoolFlag() bool { return true } + +// optional interface to indicate boolean flags that can be +// supplied without "=value" text +type boolFlag interface { + Value + IsBoolFlag() bool +} + // -- int Value type intValue int @@ -204,6 +213,10 @@ func (d *durationValue) String() string { return (*time.Duration)(d).String() } // Value is the interface to the dynamic value stored in a flag. // (The default value is represented as a string.) +// +// If a Value has an IsBoolFlag() bool method returning true, +// the command-line parser makes -name equivalent to -name=true +// rather than using the next command-line argument. type Value interface { String() string Set(string) error @@ -704,7 +717,7 @@ func (f *FlagSet) parseOne() (bool, error) { } return false, f.failf("flag provided but not defined: -%s", name) } - if fv, ok := flag.Value.(*boolValue); ok { // special case: doesn't need an arg + if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg if has_value { if err := fv.Set(value); err != nil { return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err) diff --git a/src/pkg/flag/flag_test.go b/src/pkg/flag/flag_test.go index a9561f269f..7a26fffd8d 100644 --- a/src/pkg/flag/flag_test.go +++ b/src/pkg/flag/flag_test.go @@ -208,6 +208,47 @@ func TestUserDefined(t *testing.T) { } } +// Declare a user-defined boolean flag type. +type boolFlagVar struct { + count int +} + +func (b *boolFlagVar) String() string { + return fmt.Sprintf("%d", b.count) +} + +func (b *boolFlagVar) Set(value string) error { + if value == "true" { + b.count++ + } + return nil +} + +func (b *boolFlagVar) IsBoolFlag() bool { + return b.count < 4 +} + +func TestUserDefinedBool(t *testing.T) { + var flags FlagSet + flags.Init("test", ContinueOnError) + var b boolFlagVar + var err error + flags.Var(&b, "b", "usage") + if err = flags.Parse([]string{"-b", "-b", "-b", "-b=true", "-b=false", "-b", "barg", "-b"}); err != nil { + if b.count < 4 { + t.Error(err) + } + } + + if b.count != 4 { + t.Errorf("want: %d; got: %d", 4, b.count) + } + + if err == nil { + t.Error("expected error; got none") + } +} + func TestSetOutput(t *testing.T) { var flags FlagSet var buf bytes.Buffer -- 2.50.0