Skip to content

Commit

Permalink
flag: add implicit boolFlag interface
Browse files Browse the repository at this point in the history
Any flag.Value that has an IsBoolFlag method that returns true
will be treated as a bool flag type during parsing.

Fixes golang#4262.

R=bradfitz, rsc
CC=golang-dev
https://golang.org/cl/6944064
  • Loading branch information
rickar authored and rsc committed Dec 22, 2012
1 parent 9aef20e commit a6d986b
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
15 changes: 14 additions & 1 deletion src/pkg/flag/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
41 changes: 41 additions & 0 deletions src/pkg/flag/flag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a6d986b

Please sign in to comment.