Skip to content

Commit a272c3c

Browse files
authored
Merge pull request #303 from fabianofranz/testing_help_exiting_1
Help command must use Stdout instead of Stderr
2 parents 6a8bd97 + 77530f5 commit a272c3c

File tree

2 files changed

+53
-51
lines changed

2 files changed

+53
-51
lines changed

cobra_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ func TestSubcommandArgEvaluation(t *testing.T) {
646646
second := &Command{
647647
Use: "second",
648648
Run: func(cmd *Command, args []string) {
649-
fmt.Fprintf(cmd.Out(), "%v", args)
649+
fmt.Fprintf(cmd.getOutOrStdout(), "%v", args)
650650
},
651651
}
652652
first.AddCommand(second)

command.go

+52-50
Original file line numberDiff line numberDiff line change
@@ -134,25 +134,6 @@ func (c *Command) SetArgs(a []string) {
134134
c.args = a
135135
}
136136

137-
func (c *Command) getOut(def io.Writer) io.Writer {
138-
if c.output != nil {
139-
return *c.output
140-
}
141-
142-
if c.HasParent() {
143-
return c.parent.Out()
144-
}
145-
return def
146-
}
147-
148-
func (c *Command) Out() io.Writer {
149-
return c.getOut(os.Stderr)
150-
}
151-
152-
func (c *Command) getOutOrStdout() io.Writer {
153-
return c.getOut(os.Stdout)
154-
}
155-
156137
// SetOutput sets the destination for usage and error messages.
157138
// If output is nil, os.Stderr is used.
158139
func (c *Command) SetOutput(output io.Writer) {
@@ -195,6 +176,26 @@ func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string
195176
}
196177
}
197178

179+
func (c *Command) getOutOrStdout() io.Writer {
180+
return c.getOut(os.Stdout)
181+
}
182+
183+
func (c *Command) getOutOrStderr() io.Writer {
184+
return c.getOut(os.Stderr)
185+
}
186+
187+
func (c *Command) getOut(def io.Writer) io.Writer {
188+
if c.output != nil {
189+
return *c.output
190+
}
191+
if c.HasParent() {
192+
return c.parent.getOut(def)
193+
}
194+
return def
195+
}
196+
197+
// UsageFunc returns either the function set by SetUsageFunc for this command
198+
// or a parent, or it returns a default usage function
198199
func (c *Command) UsageFunc() (f func(*Command) error) {
199200
if c.usageFunc != nil {
200201
return c.usageFunc
@@ -204,9 +205,9 @@ func (c *Command) UsageFunc() (f func(*Command) error) {
204205
return c.parent.UsageFunc()
205206
}
206207
return func(c *Command) error {
207-
err := tmpl(c.Out(), c.UsageTemplate(), c)
208+
err := c.Usage()
208209
if err != nil {
209-
fmt.Print(err)
210+
c.Println(err)
210211
}
211212
return err
212213
}
@@ -230,6 +231,33 @@ func (c *Command) HelpFunc() func(*Command, []string) {
230231
}
231232
}
232233

234+
// Output the usage for the command
235+
// Used when a user provides invalid input
236+
// Can be defined by user by overriding UsageFunc
237+
func (c *Command) Usage() error {
238+
c.mergePersistentFlags()
239+
err := tmpl(c.getOutOrStderr(), c.UsageTemplate(), c)
240+
return err
241+
}
242+
243+
// Output the help for the command
244+
// Used when a user calls help [command]
245+
// by the default HelpFunc in the commander
246+
func (c *Command) Help() error {
247+
c.mergePersistentFlags()
248+
err := tmpl(c.getOutOrStdout(), c.HelpTemplate(), c)
249+
return err
250+
}
251+
252+
func (c *Command) UsageString() string {
253+
tmpOutput := c.output
254+
bb := new(bytes.Buffer)
255+
c.SetOutput(bb)
256+
c.Usage()
257+
c.output = tmpOutput
258+
return bb.String()
259+
}
260+
233261
var minUsagePadding = 25
234262

235263
func (c *Command) UsagePadding() int {
@@ -537,6 +565,7 @@ func (c *Command) execute(a []string) (err error) {
537565
c.Println("\"help\" flag declared as non-bool. Please correct your code")
538566
return err
539567
}
568+
540569
if helpVal || !c.Runnable() {
541570
return flag.ErrHelp
542571
}
@@ -734,7 +763,7 @@ func (c commandSorterByName) Less(i, j int) bool { return c[i].Name() < c[j].Nam
734763
// Commands returns a sorted slice of child commands.
735764
func (c *Command) Commands() []*Command {
736765
// do not sort commands if it already sorted or sorting was disabled
737-
if EnableCommandSorting && !c.commandsAreSorted{
766+
if EnableCommandSorting && !c.commandsAreSorted {
738767
sort.Sort(commandSorterByName(c.commands))
739768
c.commandsAreSorted = true
740769
}
@@ -806,7 +835,7 @@ main:
806835

807836
// Print is a convenience method to Print to the defined output
808837
func (c *Command) Print(i ...interface{}) {
809-
fmt.Fprint(c.Out(), i...)
838+
fmt.Fprint(c.getOutOrStderr(), i...)
810839
}
811840

812841
// Println is a convenience method to Println to the defined output
@@ -821,33 +850,6 @@ func (c *Command) Printf(format string, i ...interface{}) {
821850
c.Print(str)
822851
}
823852

824-
// Output the usage for the command
825-
// Used when a user provides invalid input
826-
// Can be defined by user by overriding UsageFunc
827-
func (c *Command) Usage() error {
828-
c.mergePersistentFlags()
829-
err := c.UsageFunc()(c)
830-
return err
831-
}
832-
833-
// Output the help for the command
834-
// Used when a user calls help [command]
835-
// by the default HelpFunc in the commander
836-
func (c *Command) Help() error {
837-
c.mergePersistentFlags()
838-
err := tmpl(c.getOutOrStdout(), c.HelpTemplate(), c)
839-
return err
840-
}
841-
842-
func (c *Command) UsageString() string {
843-
tmpOutput := c.output
844-
bb := new(bytes.Buffer)
845-
c.SetOutput(bb)
846-
c.Usage()
847-
c.output = tmpOutput
848-
return bb.String()
849-
}
850-
851853
// CommandPath returns the full path to this command.
852854
func (c *Command) CommandPath() string {
853855
str := c.Name()

0 commit comments

Comments
 (0)