summaryrefslogtreecommitdiff
path: root/src/flag
diff options
context:
space:
mode:
authorCarl Johnson <me@carlmjohnson.net>2023-03-14 13:06:20 +0000
committerGopher Robot <gobot@golang.org>2023-03-16 16:44:21 +0000
commit785ab2fa65bec7fc8d244277c8962009d3a83271 (patch)
tree1191842f67eb6c75da6a47c6cc3141d9af4927a8 /src/flag
parentf03fb147d773f3e0cee437e02ac2de5ce1d5e981 (diff)
downloadgo-git-785ab2fa65bec7fc8d244277c8962009d3a83271.tar.gz
flag: add BoolFunc; FlagSet.BoolFunc
Fixes #53747 Based on CL 416514 Change-Id: I1ff79c6290b06dfa8672a473045e8fe80c22afcf GitHub-Last-Rev: 74fba9b3096487c04c8dc1f2237f67f3558212f1 GitHub-Pull-Request: golang/go#59013 Reviewed-on: https://go-review.googlesource.com/c/go/+/476015 Run-TryBot: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@golang.org> Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Rob Pike <r@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
Diffstat (limited to 'src/flag')
-rw-r--r--src/flag/example_func_test.go16
-rw-r--r--src/flag/flag.go23
-rw-r--r--src/flag/flag_test.go51
3 files changed, 88 insertions, 2 deletions
diff --git a/src/flag/example_func_test.go b/src/flag/example_func_test.go
index 7c30c5e713..ac9f9858df 100644
--- a/src/flag/example_func_test.go
+++ b/src/flag/example_func_test.go
@@ -39,3 +39,19 @@ func ExampleFunc() {
// IP address to parse
// {ip: <nil>, loopback: false}
}
+
+func ExampleBoolFunc() {
+ fs := flag.NewFlagSet("ExampleBoolFunc", flag.ContinueOnError)
+ fs.SetOutput(os.Stdout)
+
+ fs.BoolFunc("log", "logs a dummy message", func(s string) error {
+ fmt.Println("dummy message:", s)
+ return nil
+ })
+ fs.Parse([]string{"-log"})
+ fs.Parse([]string{"-log=0"})
+
+ // Output:
+ // dummy message: true
+ // dummy message: 0
+}
diff --git a/src/flag/flag.go b/src/flag/flag.go
index ef3cf29c0c..45928b0190 100644
--- a/src/flag/flag.go
+++ b/src/flag/flag.go
@@ -337,6 +337,15 @@ func (f funcValue) Set(s string) error { return f(s) }
func (f funcValue) String() string { return "" }
+// -- boolFunc Value
+type boolFuncValue func(string) error
+
+func (f boolFuncValue) Set(s string) error { return f(s) }
+
+func (f boolFuncValue) String() string { return "" }
+
+func (f boolFuncValue) IsBoolFlag() bool { return true }
+
// Value is the interface to the dynamic value stored in a flag.
// (The default value is represented as a string.)
//
@@ -955,6 +964,20 @@ func Func(name, usage string, fn func(string) error) {
CommandLine.Func(name, usage, fn)
}
+// BoolFunc defines a flag with the specified name and usage string without requiring values.
+// Each time the flag is seen, fn is called with the value of the flag.
+// If fn returns a non-nil error, it will be treated as a flag value parsing error.
+func (f *FlagSet) BoolFunc(name, usage string, fn func(string) error) {
+ f.Var(boolFuncValue(fn), name, usage)
+}
+
+// BoolFunc defines a flag with the specified name and usage string without requiring values.
+// Each time the flag is seen, fn is called with the value of the flag.
+// If fn returns a non-nil error, it will be treated as a flag value parsing error.
+func BoolFunc(name, usage string, fn func(string) error) {
+ CommandLine.BoolFunc(name, usage, fn)
+}
+
// Var defines a flag with the specified name and usage string. The type and
// value of the flag are represented by the first argument, of type Value, which
// typically holds a user-defined implementation of Value. For instance, the
diff --git a/src/flag/flag_test.go b/src/flag/flag_test.go
index 1755168405..14d199d6e9 100644
--- a/src/flag/flag_test.go
+++ b/src/flag/flag_test.go
@@ -38,6 +38,7 @@ func TestEverything(t *testing.T) {
Float64("test_float64", 0, "float64 value")
Duration("test_duration", 0, "time.Duration value")
Func("test_func", "func value", func(string) error { return nil })
+ BoolFunc("test_boolfunc", "func", func(string) error { return nil })
m := make(map[string]*Flag)
desired := "0"
@@ -54,6 +55,8 @@ func TestEverything(t *testing.T) {
ok = true
case f.Name == "test_func" && f.Value.String() == "":
ok = true
+ case f.Name == "test_boolfunc" && f.Value.String() == "":
+ ok = true
}
if !ok {
t.Error("Visit: bad value", f.Value.String(), "for", f.Name)
@@ -61,7 +64,7 @@ func TestEverything(t *testing.T) {
}
}
VisitAll(visitor)
- if len(m) != 9 {
+ if len(m) != 10 {
t.Error("VisitAll misses some flags")
for k, v := range m {
t.Log(k, *v)
@@ -85,9 +88,10 @@ func TestEverything(t *testing.T) {
Set("test_float64", "1")
Set("test_duration", "1s")
Set("test_func", "1")
+ Set("test_boolfunc", "")
desired = "1"
Visit(visitor)
- if len(m) != 9 {
+ if len(m) != 10 {
t.Error("Visit fails after set")
for k, v := range m {
t.Log(k, *v)
@@ -797,3 +801,46 @@ func TestRedefinedFlags(t *testing.T) {
}
}
}
+
+func TestUserDefinedBoolFunc(t *testing.T) {
+ flags := NewFlagSet("test", ContinueOnError)
+ flags.SetOutput(io.Discard)
+ var ss []string
+ flags.BoolFunc("v", "usage", func(s string) error {
+ ss = append(ss, s)
+ return nil
+ })
+ if err := flags.Parse([]string{"-v", "", "-v", "1", "-v=2"}); err != nil {
+ t.Error(err)
+ }
+ if len(ss) != 1 {
+ t.Fatalf("got %d args; want 1 arg", len(ss))
+ }
+ want := "[true]"
+ if got := fmt.Sprint(ss); got != want {
+ t.Errorf("got %q; want %q", got, want)
+ }
+ // test usage
+ var buf strings.Builder
+ flags.SetOutput(&buf)
+ flags.Parse([]string{"-h"})
+ if usage := buf.String(); !strings.Contains(usage, "usage") {
+ t.Errorf("usage string not included: %q", usage)
+ }
+ // test BoolFunc error
+ flags = NewFlagSet("test", ContinueOnError)
+ flags.SetOutput(io.Discard)
+ flags.BoolFunc("v", "usage", func(s string) error {
+ return fmt.Errorf("test error")
+ })
+ // flag not set, so no error
+ if err := flags.Parse(nil); err != nil {
+ t.Error(err)
+ }
+ // flag set, expect error
+ if err := flags.Parse([]string{"-v", ""}); err == nil {
+ t.Error("got err == nil; want err != nil")
+ } else if errMsg := err.Error(); !strings.Contains(errMsg, "test error") {
+ t.Errorf(`got %q; error should contain "test error"`, errMsg)
+ }
+}