Skip to content

Commit 81378bb

Browse files
mckernChloe Kudryavtsev
and
Chloe Kudryavtsev
authored
Add exported functions to preserve pkg/flag compatibility (#220)
* Rename out() to Output() This brings behavior inline with go's flag library, and allows for printing output directly to whatever the current FlagSet is using for output. This change will make it easier to correctly emit output to stdout or stderr (e.g. a user has requested a help screen, which should emit to stdout since it's the desired outcome). * improve compat. with pkg/flag by adding Name() pkg/flag has a public `Name()` function, which returns the name of the flag set when called. This commit adds that function, as well as a test for it. * Streamline testing Name() Testing `Name()` will move into its own explicit test, instead of running inline during `TestAddFlagSet()`. Co-authored-by: Chloe Kudryavtsev <[email protected]> Co-authored-by: Chloe Kudryavtsev <[email protected]>
1 parent 2e9d26c commit 81378bb

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed

Diff for: flag.go

+18-11
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ type FlagSet struct {
160160
args []string // arguments after flags
161161
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
162162
errorHandling ErrorHandling
163-
output io.Writer // nil means stderr; use out() accessor
163+
output io.Writer // nil means stderr; use Output() accessor
164164
interspersed bool // allow interspersed option/non-option args
165165
normalizeNameFunc func(f *FlagSet, name string) NormalizedName
166166

@@ -255,13 +255,20 @@ func (f *FlagSet) normalizeFlagName(name string) NormalizedName {
255255
return n(f, name)
256256
}
257257

258-
func (f *FlagSet) out() io.Writer {
258+
// Output returns the destination for usage and error messages. os.Stderr is returned if
259+
// output was not set or was set to nil.
260+
func (f *FlagSet) Output() io.Writer {
259261
if f.output == nil {
260262
return os.Stderr
261263
}
262264
return f.output
263265
}
264266

267+
// Name returns the name of the flag set.
268+
func (f *FlagSet) Name() string {
269+
return f.name
270+
}
271+
265272
// SetOutput sets the destination for usage and error messages.
266273
// If output is nil, os.Stderr is used.
267274
func (f *FlagSet) SetOutput(output io.Writer) {
@@ -358,7 +365,7 @@ func (f *FlagSet) ShorthandLookup(name string) *Flag {
358365
}
359366
if len(name) > 1 {
360367
msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
361-
fmt.Fprintf(f.out(), msg)
368+
fmt.Fprintf(f.Output(), msg)
362369
panic(msg)
363370
}
364371
c := name[0]
@@ -482,7 +489,7 @@ func (f *FlagSet) Set(name, value string) error {
482489
}
483490

484491
if flag.Deprecated != "" {
485-
fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
492+
fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
486493
}
487494
return nil
488495
}
@@ -523,7 +530,7 @@ func Set(name, value string) error {
523530
// otherwise, the default values of all defined flags in the set.
524531
func (f *FlagSet) PrintDefaults() {
525532
usages := f.FlagUsages()
526-
fmt.Fprint(f.out(), usages)
533+
fmt.Fprint(f.Output(), usages)
527534
}
528535

529536
// defaultIsZeroValue returns true if the default value for this flag represents
@@ -758,7 +765,7 @@ func PrintDefaults() {
758765

759766
// defaultUsage is the default function to print a usage message.
760767
func defaultUsage(f *FlagSet) {
761-
fmt.Fprintf(f.out(), "Usage of %s:\n", f.name)
768+
fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name)
762769
f.PrintDefaults()
763770
}
764771

@@ -844,7 +851,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
844851
_, alreadyThere := f.formal[normalizedFlagName]
845852
if alreadyThere {
846853
msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)
847-
fmt.Fprintln(f.out(), msg)
854+
fmt.Fprintln(f.Output(), msg)
848855
panic(msg) // Happens only if flags are declared with identical names
849856
}
850857
if f.formal == nil {
@@ -860,7 +867,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
860867
}
861868
if len(flag.Shorthand) > 1 {
862869
msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)
863-
fmt.Fprintf(f.out(), msg)
870+
fmt.Fprintf(f.Output(), msg)
864871
panic(msg)
865872
}
866873
if f.shorthands == nil {
@@ -870,7 +877,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
870877
used, alreadyThere := f.shorthands[c]
871878
if alreadyThere {
872879
msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)
873-
fmt.Fprintf(f.out(), msg)
880+
fmt.Fprintf(f.Output(), msg)
874881
panic(msg)
875882
}
876883
f.shorthands[c] = flag
@@ -909,7 +916,7 @@ func VarP(value Value, name, shorthand, usage string) {
909916
func (f *FlagSet) failf(format string, a ...interface{}) error {
910917
err := fmt.Errorf(format, a...)
911918
if f.errorHandling != ContinueOnError {
912-
fmt.Fprintln(f.out(), err)
919+
fmt.Fprintln(f.Output(), err)
913920
f.usage()
914921
}
915922
return err
@@ -1060,7 +1067,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
10601067
}
10611068

10621069
if flag.ShorthandDeprecated != "" {
1063-
fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
1070+
fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
10641071
}
10651072

10661073
err = fn(flag, value)

Diff for: flag_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,16 @@ func TestAnnotation(t *testing.T) {
159159
}
160160
}
161161

162+
func TestName(t *testing.T) {
163+
flagSetName := "bob"
164+
f := NewFlagSet(flagSetName, ContinueOnError)
165+
166+
givenName := f.Name()
167+
if givenName != flagSetName {
168+
t.Errorf("Unexpected result when retrieving a FlagSet's name: expected %s, but found %s", flagSetName, givenName)
169+
}
170+
}
171+
162172
func testParse(f *FlagSet, t *testing.T) {
163173
if f.Parsed() {
164174
t.Error("f.Parse() = true before Parse")
@@ -854,6 +864,17 @@ func TestSetOutput(t *testing.T) {
854864
}
855865
}
856866

867+
func TestOutput(t *testing.T) {
868+
var flags FlagSet
869+
var buf bytes.Buffer
870+
expect := "an example string"
871+
flags.SetOutput(&buf)
872+
fmt.Fprint(flags.Output(), expect)
873+
if out := buf.String(); !strings.Contains(out, expect) {
874+
t.Errorf("expected output %q; got %q", expect, out)
875+
}
876+
}
877+
857878
// This tests that one can reset the flags. This still works but not well, and is
858879
// superseded by FlagSet.
859880
func TestChangingArgs(t *testing.T) {

0 commit comments

Comments
 (0)