aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bool.go9
-rw-r--r--bool_test.go163
-rw-r--r--example_test.go4
-rw-r--r--flag.go4
-rw-r--r--flag_test.go4
5 files changed, 182 insertions, 2 deletions
diff --git a/bool.go b/bool.go
index 010576c..70e2e0a 100644
--- a/bool.go
+++ b/bool.go
@@ -5,6 +5,13 @@ import (
"strconv"
)
+// optional interface to indicate boolean flags that can be
+// supplied without "=value" text
+type boolFlag interface {
+ Value
+ IsBoolFlag() bool
+}
+
// -- bool Value
type boolValue bool
@@ -25,6 +32,8 @@ func (b *boolValue) Type() string {
func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }
+func (b *boolValue) IsBoolFlag() bool { return true }
+
// BoolVar defines a bool flag with specified name, default value, and usage string.
// The argument p points to a bool variable in which to store the value of the flag.
func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) {
diff --git a/bool_test.go b/bool_test.go
new file mode 100644
index 0000000..72a12be
--- /dev/null
+++ b/bool_test.go
@@ -0,0 +1,163 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pflag_test
+
+import (
+ "fmt"
+ "strconv"
+ "testing"
+
+ . "github.com/ogier/pflag"
+)
+
+// This value can be a boolean ("true", "false") or "maybe"
+type triStateValue int
+
+const (
+ triStateFalse triStateValue = 0
+ triStateTrue triStateValue = 1
+ triStateMaybe triStateValue = 2
+)
+
+const strTriStateMaybe = "maybe"
+
+func (v *triStateValue) IsBoolFlag() bool {
+ return true
+}
+
+func (v *triStateValue) Get() interface{} {
+ return triStateValue(*v)
+}
+
+func (v *triStateValue) Set(s string) error {
+ if s == strTriStateMaybe {
+ *v = triStateMaybe
+ return nil
+ }
+ boolVal, err := strconv.ParseBool(s)
+ if boolVal {
+ *v = triStateTrue
+ } else {
+ *v = triStateFalse
+ }
+ return err
+}
+
+func (v *triStateValue) String() string {
+ if *v == triStateMaybe {
+ return strTriStateMaybe
+ }
+ return fmt.Sprintf("%v", bool(*v == triStateTrue))
+}
+
+// The type of the flag as requred by the pflag.Value interface
+func (v *triStateValue) Type() string {
+ return "version"
+}
+
+func setUpFlagSet(tristate *triStateValue) *FlagSet {
+ f := NewFlagSet("test", ContinueOnError)
+ *tristate = triStateFalse
+ f.VarP(tristate, "tristate", "t", "tristate value (true, maybe or false)")
+ return f
+}
+
+func TestExplicitTrue(t *testing.T) {
+ var tristate triStateValue
+ f := setUpFlagSet(&tristate)
+ err := f.Parse([]string{"--tristate=true"})
+ if err != nil {
+ t.Fatal("expected no error; got", err)
+ }
+ if tristate != triStateTrue {
+ t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
+ }
+}
+
+func TestImplicitTrue(t *testing.T) {
+ var tristate triStateValue
+ f := setUpFlagSet(&tristate)
+ err := f.Parse([]string{"--tristate"})
+ if err != nil {
+ t.Fatal("expected no error; got", err)
+ }
+ if tristate != triStateTrue {
+ t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
+ }
+}
+
+func TestShortFlag(t *testing.T) {
+ var tristate triStateValue
+ f := setUpFlagSet(&tristate)
+ err := f.Parse([]string{"-t"})
+ if err != nil {
+ t.Fatal("expected no error; got", err)
+ }
+ if tristate != triStateTrue {
+ t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
+ }
+}
+
+func TestShortFlagExtraArgument(t *testing.T) {
+ var tristate triStateValue
+ f := setUpFlagSet(&tristate)
+ // The"maybe"turns into an arg, since short boolean options will only do true/false
+ err := f.Parse([]string{"-t", "maybe"})
+ if err != nil {
+ t.Fatal("expected no error; got", err)
+ }
+ if tristate != triStateTrue {
+ t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
+ }
+ args := f.Args()
+ if len(args) != 1 || args[0] != "maybe" {
+ t.Fatal("expected an extra 'maybe' argument to stick around")
+ }
+}
+
+func TestExplicitMaybe(t *testing.T) {
+ var tristate triStateValue
+ f := setUpFlagSet(&tristate)
+ err := f.Parse([]string{"--tristate=maybe"})
+ if err != nil {
+ t.Fatal("expected no error; got", err)
+ }
+ if tristate != triStateMaybe {
+ t.Fatal("expected", triStateMaybe, "(triStateMaybe) but got", tristate, "instead")
+ }
+}
+
+func TestExplicitFalse(t *testing.T) {
+ var tristate triStateValue
+ f := setUpFlagSet(&tristate)
+ err := f.Parse([]string{"--tristate=false"})
+ if err != nil {
+ t.Fatal("expected no error; got", err)
+ }
+ if tristate != triStateFalse {
+ t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead")
+ }
+}
+
+func TestImplicitFalse(t *testing.T) {
+ var tristate triStateValue
+ f := setUpFlagSet(&tristate)
+ err := f.Parse([]string{})
+ if err != nil {
+ t.Fatal("expected no error; got", err)
+ }
+ if tristate != triStateFalse {
+ t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead")
+ }
+}
+
+func TestInvalidValue(t *testing.T) {
+ var tristate triStateValue
+ f := setUpFlagSet(&tristate)
+ err := f.Parse([]string{"--tristate=invalid"})
+ if err == nil {
+ t.Fatal("expected an error but did not get any, tristate has value", tristate)
+ }
+}
diff --git a/example_test.go b/example_test.go
index 03ebeaa..6aaed3c 100644
--- a/example_test.go
+++ b/example_test.go
@@ -29,6 +29,10 @@ func (i *interval) String() string {
return fmt.Sprint(*i)
}
+func (i *interval) Type() string {
+ return "interval"
+}
+
// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
diff --git a/flag.go b/flag.go
index 47761a0..2e4cac0 100644
--- a/flag.go
+++ b/flag.go
@@ -466,7 +466,7 @@ func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error)
return
}
if len(split) == 1 {
- if _, ok := flag.Value.(*boolValue); !ok {
+ if bv, ok := flag.Value.(boolFlag); !ok || !bv.IsBoolFlag() {
err = f.failf("flag needs an argument: %s", s)
return
}
@@ -500,7 +500,7 @@ func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error)
}
}
if alreadythere {
- if _, ok := flag.Value.(*boolValue); ok {
+ if bv, ok := flag.Value.(boolFlag); ok && bv.IsBoolFlag() {
f.setFlag(flag, "true", s)
continue
}
diff --git a/flag_test.go b/flag_test.go
index 4d95b15..47865bd 100644
--- a/flag_test.go
+++ b/flag_test.go
@@ -245,6 +245,10 @@ func (f *flagVar) Set(value string) error {
return nil
}
+func (f *flagVar) Type() string {
+ return "flagVar"
+}
+
func TestUserDefined(t *testing.T) {
var flags FlagSet
flags.Init("test", ContinueOnError)