Do not allow default tag on boolean flags
Fixes #159.
diff --git a/command_test.go b/command_test.go
index 72d397d..e7e3089 100644
--- a/command_test.go
+++ b/command_test.go
@@ -430,14 +430,14 @@
func TestDefaultOnCommand(t *testing.T) {
var opts = struct {
Command struct {
- G bool `short:"g" default:"true"`
+ G string `short:"g" default:"value"`
} `command:"cmd"`
}{}
assertParseSuccess(t, &opts, "cmd")
- if !opts.Command.G {
- t.Errorf("Expected G to be true")
+ if opts.Command.G != "value" {
+ t.Errorf("Expected G to be \"value\"")
}
}
@@ -470,14 +470,14 @@
func TestCommandAlias(t *testing.T) {
var opts = struct {
Command struct {
- G bool `short:"g" default:"true"`
+ G string `short:"g" default:"value"`
} `command:"cmd" alias:"cm"`
}{}
assertParseSuccess(t, &opts, "cm")
- if !opts.Command.G {
- t.Errorf("Expected G to be true")
+ if opts.Command.G != "value" {
+ t.Errorf("Expected G to be \"value\"")
}
}
diff --git a/error.go b/error.go
index 2f27aee..05528d8 100644
--- a/error.go
+++ b/error.go
@@ -55,6 +55,9 @@
// ErrInvalidChoice indicates an invalid option value which only allows
// a certain number of choices.
ErrInvalidChoice
+
+ // ErrInvalidTag indicates an invalid tag or invalid use of an existing tag
+ ErrInvalidTag
)
func (e ErrorType) String() string {
@@ -87,6 +90,8 @@
return "unknown command"
case ErrInvalidChoice:
return "invalid choice"
+ case ErrInvalidTag:
+ return "invalid tag"
}
return "unrecognized error type"
diff --git a/group.go b/group.go
index debb8de..27d2d72 100644
--- a/group.go
+++ b/group.go
@@ -276,6 +276,12 @@
tag: mtag,
}
+ if option.isBool() && option.Default != nil {
+ return newErrorf(ErrInvalidTag,
+ "boolean flag `%s' may not have default values, they always default to `false' and can only be turned off",
+ option.shortAndLongName())
+ }
+
g.options = append(g.options, option)
}
diff --git a/marshal_test.go b/marshal_test.go
index 59c9cce..095e9e4 100644
--- a/marshal_test.go
+++ b/marshal_test.go
@@ -5,13 +5,13 @@
"testing"
)
-type marshalled bool
+type marshalled string
func (m *marshalled) UnmarshalFlag(value string) error {
if value == "yes" {
- *m = true
+ *m = "true"
} else if value == "no" {
- *m = false
+ *m = "false"
} else {
return fmt.Errorf("`%s' is not a valid value, please specify `yes' or `no'", value)
}
@@ -20,7 +20,7 @@
}
func (m marshalled) MarshalFlag() (string, error) {
- if m {
+ if m == "true" {
return "yes", nil
}
@@ -42,8 +42,8 @@
assertStringArray(t, ret, []string{})
- if !opts.Value {
- t.Errorf("Expected Value to be true")
+ if opts.Value != "true" {
+ t.Errorf("Expected Value to be \"true\"")
}
}
@@ -56,8 +56,8 @@
assertStringArray(t, ret, []string{})
- if !opts.Value {
- t.Errorf("Expected Value to be true")
+ if opts.Value != "true" {
+ t.Errorf("Expected Value to be \"true\"")
}
}
@@ -70,8 +70,8 @@
assertStringArray(t, ret, []string{})
- if !opts.Value {
- t.Errorf("Expected Value to be true")
+ if opts.Value != "true" {
+ t.Errorf("Expected Value to be \"true\"")
}
}
diff --git a/option.go b/option.go
index a7f4f9a..b2a69c7 100644
--- a/option.go
+++ b/option.go
@@ -1,6 +1,7 @@
package flags
import (
+ "bytes"
"fmt"
"reflect"
"strings"
@@ -412,3 +413,22 @@
option.defaultLiteral = def
}
+
+func (option *Option) shortAndLongName() string {
+ ret := &bytes.Buffer{}
+
+ if option.ShortName != 0 {
+ ret.WriteRune(defaultShortOptDelimiter)
+ ret.WriteRune(option.ShortName)
+ }
+
+ if len(option.LongName) != 0 {
+ if option.ShortName != 0 {
+ ret.WriteRune('/')
+ }
+
+ ret.WriteString(option.LongName)
+ }
+
+ return ret.String()
+}
diff --git a/parser_test.go b/parser_test.go
index b57dbee..a81983f 100644
--- a/parser_test.go
+++ b/parser_test.go
@@ -4,6 +4,7 @@
"fmt"
"os"
"reflect"
+ "runtime"
"strconv"
"strings"
"testing"
@@ -17,7 +18,7 @@
Float64 float64 `long:"f"`
Float64Default float64 `long:"fd" default:"-3.14"`
- NumericFlag bool `short:"3" default:"false"`
+ NumericFlag bool `short:"3"`
String string `long:"str"`
StringDefault string `long:"strd" default:"abc"`
@@ -132,6 +133,18 @@
}
}
+func TestNoDefaultsForBools(t *testing.T) {
+ var opts struct {
+ DefaultBool bool `short:"d" default:"true"`
+ }
+
+ if runtime.GOOS == "windows" {
+ assertParseFail(t, ErrInvalidTag, "boolean flag `/d' may not have default values, they always default to `false' and can only be turned off", &opts)
+ } else {
+ assertParseFail(t, ErrInvalidTag, "boolean flag `-d' may not have default values, they always default to `false' and can only be turned off", &opts)
+ }
+}
+
func TestUnquoting(t *testing.T) {
var tests = []struct {
arg string