|
|
414c91d |
From 81378bbcd8a1005f72b1e8d7579e5dd7b2d612ab Mon Sep 17 00:00:00 2001
|
|
|
414c91d |
From: Ryan McKern <344926+mckern@users.noreply.github.com>
|
|
|
414c91d |
Date: Mon, 4 May 2020 07:38:53 -0700
|
|
|
414c91d |
Subject: [PATCH] Add exported functions to preserve `pkg/flag` compatibility
|
|
|
414c91d |
(#220)
|
|
|
414c91d |
|
|
|
414c91d |
* Rename out() to Output()
|
|
|
414c91d |
|
|
|
414c91d |
This brings behavior inline with go's flag library, and allows for
|
|
|
414c91d |
printing output directly to whatever the current FlagSet is using for
|
|
|
414c91d |
output. This change will make it easier to correctly emit output to
|
|
|
414c91d |
stdout or stderr (e.g. a user has requested a help screen, which
|
|
|
414c91d |
should emit to stdout since it's the desired outcome).
|
|
|
414c91d |
|
|
|
414c91d |
* improve compat. with pkg/flag by adding Name()
|
|
|
414c91d |
|
|
|
414c91d |
pkg/flag has a public `Name()` function, which returns the name of the
|
|
|
414c91d |
flag set when called. This commit adds that function, as well as a
|
|
|
414c91d |
test for it.
|
|
|
414c91d |
|
|
|
414c91d |
* Streamline testing Name()
|
|
|
414c91d |
|
|
|
414c91d |
Testing `Name()` will move into its own explicit test, instead of
|
|
|
414c91d |
running inline during `TestAddFlagSet()`.
|
|
|
414c91d |
|
|
|
414c91d |
Co-authored-by: Chloe Kudryavtsev <toast@toast.cafe>
|
|
|
414c91d |
|
|
|
414c91d |
Co-authored-by: Chloe Kudryavtsev <toast@toast.cafe>
|
|
|
414c91d |
---
|
|
|
414c91d |
flag.go | 29 ++++++++++++++++++-----------
|
|
|
414c91d |
flag_test.go | 21 +++++++++++++++++++++
|
|
|
414c91d |
2 files changed, 39 insertions(+), 11 deletions(-)
|
|
|
414c91d |
|
|
|
414c91d |
diff --git a/flag.go b/flag.go
|
|
|
414c91d |
index 24a5036..7c058de 100644
|
|
|
414c91d |
--- a/flag.go
|
|
|
414c91d |
+++ b/flag.go
|
|
|
414c91d |
@@ -160,7 +160,7 @@ type FlagSet struct {
|
|
|
414c91d |
args []string // arguments after flags
|
|
|
414c91d |
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
|
|
|
414c91d |
errorHandling ErrorHandling
|
|
|
414c91d |
- output io.Writer // nil means stderr; use out() accessor
|
|
|
414c91d |
+ output io.Writer // nil means stderr; use Output() accessor
|
|
|
414c91d |
interspersed bool // allow interspersed option/non-option args
|
|
|
414c91d |
normalizeNameFunc func(f *FlagSet, name string) NormalizedName
|
|
|
414c91d |
|
|
|
414c91d |
@@ -255,13 +255,20 @@ func (f *FlagSet) normalizeFlagName(name string) NormalizedName {
|
|
|
414c91d |
return n(f, name)
|
|
|
414c91d |
}
|
|
|
414c91d |
|
|
|
414c91d |
-func (f *FlagSet) out() io.Writer {
|
|
|
414c91d |
+// Output returns the destination for usage and error messages. os.Stderr is returned if
|
|
|
414c91d |
+// output was not set or was set to nil.
|
|
|
414c91d |
+func (f *FlagSet) Output() io.Writer {
|
|
|
414c91d |
if f.output == nil {
|
|
|
414c91d |
return os.Stderr
|
|
|
414c91d |
}
|
|
|
414c91d |
return f.output
|
|
|
414c91d |
}
|
|
|
414c91d |
|
|
|
414c91d |
+// Name returns the name of the flag set.
|
|
|
414c91d |
+func (f *FlagSet) Name() string {
|
|
|
414c91d |
+ return f.name
|
|
|
414c91d |
+}
|
|
|
414c91d |
+
|
|
|
414c91d |
// SetOutput sets the destination for usage and error messages.
|
|
|
414c91d |
// If output is nil, os.Stderr is used.
|
|
|
414c91d |
func (f *FlagSet) SetOutput(output io.Writer) {
|
|
|
414c91d |
@@ -358,7 +365,7 @@ func (f *FlagSet) ShorthandLookup(name string) *Flag {
|
|
|
414c91d |
}
|
|
|
414c91d |
if len(name) > 1 {
|
|
|
414c91d |
msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
|
|
|
414c91d |
- fmt.Fprintf(f.out(), msg)
|
|
|
414c91d |
+ fmt.Fprintf(f.Output(), msg)
|
|
|
414c91d |
panic(msg)
|
|
|
414c91d |
}
|
|
|
414c91d |
c := name[0]
|
|
|
414c91d |
@@ -482,7 +489,7 @@ func (f *FlagSet) Set(name, value string) error {
|
|
|
414c91d |
}
|
|
|
414c91d |
|
|
|
414c91d |
if flag.Deprecated != "" {
|
|
|
414c91d |
- fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
|
|
|
414c91d |
+ fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
|
|
|
414c91d |
}
|
|
|
414c91d |
return nil
|
|
|
414c91d |
}
|
|
|
414c91d |
@@ -523,7 +530,7 @@ func Set(name, value string) error {
|
|
|
414c91d |
// otherwise, the default values of all defined flags in the set.
|
|
|
414c91d |
func (f *FlagSet) PrintDefaults() {
|
|
|
414c91d |
usages := f.FlagUsages()
|
|
|
414c91d |
- fmt.Fprint(f.out(), usages)
|
|
|
414c91d |
+ fmt.Fprint(f.Output(), usages)
|
|
|
414c91d |
}
|
|
|
414c91d |
|
|
|
414c91d |
// defaultIsZeroValue returns true if the default value for this flag represents
|
|
|
414c91d |
@@ -758,7 +765,7 @@ func PrintDefaults() {
|
|
|
414c91d |
|
|
|
414c91d |
// defaultUsage is the default function to print a usage message.
|
|
|
414c91d |
func defaultUsage(f *FlagSet) {
|
|
|
414c91d |
- fmt.Fprintf(f.out(), "Usage of %s:\n", f.name)
|
|
|
414c91d |
+ fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name)
|
|
|
414c91d |
f.PrintDefaults()
|
|
|
414c91d |
}
|
|
|
414c91d |
|
|
|
414c91d |
@@ -844,7 +851,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
|
|
|
414c91d |
_, alreadyThere := f.formal[normalizedFlagName]
|
|
|
414c91d |
if alreadyThere {
|
|
|
414c91d |
msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)
|
|
|
414c91d |
- fmt.Fprintln(f.out(), msg)
|
|
|
414c91d |
+ fmt.Fprintln(f.Output(), msg)
|
|
|
414c91d |
panic(msg) // Happens only if flags are declared with identical names
|
|
|
414c91d |
}
|
|
|
414c91d |
if f.formal == nil {
|
|
|
414c91d |
@@ -860,7 +867,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
|
|
|
414c91d |
}
|
|
|
414c91d |
if len(flag.Shorthand) > 1 {
|
|
|
414c91d |
msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)
|
|
|
414c91d |
- fmt.Fprintf(f.out(), msg)
|
|
|
414c91d |
+ fmt.Fprintf(f.Output(), msg)
|
|
|
414c91d |
panic(msg)
|
|
|
414c91d |
}
|
|
|
414c91d |
if f.shorthands == nil {
|
|
|
414c91d |
@@ -870,7 +877,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
|
|
|
414c91d |
used, alreadyThere := f.shorthands[c]
|
|
|
414c91d |
if alreadyThere {
|
|
|
414c91d |
msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)
|
|
|
414c91d |
- fmt.Fprintf(f.out(), msg)
|
|
|
414c91d |
+ fmt.Fprintf(f.Output(), msg)
|
|
|
414c91d |
panic(msg)
|
|
|
414c91d |
}
|
|
|
414c91d |
f.shorthands[c] = flag
|
|
|
414c91d |
@@ -909,7 +916,7 @@ func VarP(value Value, name, shorthand, usage string) {
|
|
|
414c91d |
func (f *FlagSet) failf(format string, a ...interface{}) error {
|
|
|
414c91d |
err := fmt.Errorf(format, a...)
|
|
|
414c91d |
if f.errorHandling != ContinueOnError {
|
|
|
414c91d |
- fmt.Fprintln(f.out(), err)
|
|
|
414c91d |
+ fmt.Fprintln(f.Output(), err)
|
|
|
414c91d |
f.usage()
|
|
|
414c91d |
}
|
|
|
414c91d |
return err
|
|
|
414c91d |
@@ -1060,7 +1067,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
|
|
|
414c91d |
}
|
|
|
414c91d |
|
|
|
414c91d |
if flag.ShorthandDeprecated != "" {
|
|
|
414c91d |
- fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
|
|
|
414c91d |
+ fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
|
|
|
414c91d |
}
|
|
|
414c91d |
|
|
|
414c91d |
err = fn(flag, value)
|
|
|
414c91d |
diff --git a/flag_test.go b/flag_test.go
|
|
|
414c91d |
index 7d02dbc..58a5d25 100644
|
|
|
414c91d |
--- a/flag_test.go
|
|
|
414c91d |
+++ b/flag_test.go
|
|
|
414c91d |
@@ -159,6 +159,16 @@ func TestAnnotation(t *testing.T) {
|
|
|
414c91d |
}
|
|
|
414c91d |
}
|
|
|
414c91d |
|
|
|
414c91d |
+func TestName(t *testing.T) {
|
|
|
414c91d |
+ flagSetName := "bob"
|
|
|
414c91d |
+ f := NewFlagSet(flagSetName, ContinueOnError)
|
|
|
414c91d |
+
|
|
|
414c91d |
+ givenName := f.Name()
|
|
|
414c91d |
+ if givenName != flagSetName {
|
|
|
414c91d |
+ t.Errorf("Unexpected result when retrieving a FlagSet's name: expected %s, but found %s", flagSetName, givenName)
|
|
|
414c91d |
+ }
|
|
|
414c91d |
+}
|
|
|
414c91d |
+
|
|
|
414c91d |
func testParse(f *FlagSet, t *testing.T) {
|
|
|
414c91d |
if f.Parsed() {
|
|
|
414c91d |
t.Error("f.Parse() = true before Parse")
|
|
|
414c91d |
@@ -854,6 +864,17 @@ func TestSetOutput(t *testing.T) {
|
|
|
414c91d |
}
|
|
|
414c91d |
}
|
|
|
414c91d |
|
|
|
414c91d |
+func TestOutput(t *testing.T) {
|
|
|
414c91d |
+ var flags FlagSet
|
|
|
414c91d |
+ var buf bytes.Buffer
|
|
|
414c91d |
+ expect := "an example string"
|
|
|
414c91d |
+ flags.SetOutput(&buf)
|
|
|
414c91d |
+ fmt.Fprint(flags.Output(), expect)
|
|
|
414c91d |
+ if out := buf.String(); !strings.Contains(out, expect) {
|
|
|
414c91d |
+ t.Errorf("expected output %q; got %q", expect, out)
|
|
|
414c91d |
+ }
|
|
|
414c91d |
+}
|
|
|
414c91d |
+
|
|
|
414c91d |
// This tests that one can reset the flags. This still works but not well, and is
|
|
|
414c91d |
// superseded by FlagSet.
|
|
|
414c91d |
func TestChangingArgs(t *testing.T) {
|