Repository: spf13/cobra
Pull request #343 (2016-09-04 11:42:41)

Make SEE ALSO references and generated file names agree with each other.
Fixes  #342.



Patch:
diff --git a/README.md b/README.md
index 5d2504b..2efda59 100644
--- a/README.md
+++ b/README.md
@@ -157,7 +157,12 @@ In a Cobra app, typically the main.go file is very bare. It serves, one purpose,
 ```go
 package main
 
-import "{pathToYourApp}/cmd"
+import (
+	"fmt"
+	"os"
+
+	"{pathToYourApp}/cmd"
+)
 
 func main() {
 	if err := cmd.RootCmd.Execute(); err != nil {
@@ -313,7 +318,12 @@ In a Cobra app, typically the main.go file is very bare. It serves, one purpose,
 ```go
 package main
 
-import "{pathToYourApp}/cmd"
+import (
+	"fmt"
+	"os"
+
+	"{pathToYourApp}/cmd"
+)
 
 func main() {
 	if err := cmd.RootCmd.Execute(); err != nil {
@@ -337,6 +347,7 @@ package cmd
 
 import (
 	"github.com/spf13/cobra"
+	"fmt"
 )
 
 func init() {
diff --git a/command.go b/command.go
index 9ae9836..4988931 100644
--- a/command.go
+++ b/command.go
@@ -109,10 +109,11 @@ type Command struct {
 
 	flagErrorBuf *bytes.Buffer
 
-	args          []string                 // actual args parsed from flags
-	output        *io.Writer               // out writer if set in SetOutput(w)
-	usageFunc     func(*Command) error     // Usage can be defined by application
-	usageTemplate string                   // Can be defined by Application
+	args          []string             // actual args parsed from flags
+	output        *io.Writer           // out writer if set in SetOutput(w)
+	usageFunc     func(*Command) error // Usage can be defined by application
+	usageTemplate string               // Can be defined by Application
+	flagErrorFunc func(*Command, error) error
 	helpTemplate  string                   // Can be defined by Application
 	helpFunc      func(*Command, []string) // Help can be defined by application
 	helpCommand   *Command                 // The help command
@@ -150,7 +151,13 @@ func (c *Command) SetUsageTemplate(s string) {
 	c.usageTemplate = s
 }
 
-// Can be defined by Application.
+// SetFlagErrorFunc sets a function to generate an error when flag parsing
+// fails
+func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) {
+	c.flagErrorFunc = f
+}
+
+// Can be defined by Application
 func (c *Command) SetHelpFunc(f func(*Command, []string)) {
 	c.helpFunc = f
 }
@@ -224,12 +231,8 @@ func (c *Command) Usage() error {
 // HelpFunc returns either the function set by SetHelpFunc for this command
 // or a parent, or it returns a function with default help behavior.
 func (c *Command) HelpFunc() func(*Command, []string) {
-	cmd := c
-	for cmd != nil {
-		if cmd.helpFunc != nil {
-			return cmd.helpFunc
-		}
-		cmd = cmd.parent
+	if helpFunc := c.checkHelpFunc(); helpFunc != nil {
+		return helpFunc
 	}
 	return func(*Command, []string) {
 		c.mergePersistentFlags()
@@ -240,6 +243,20 @@ func (c *Command) HelpFunc() func(*Command, []string) {
 	}
 }
 
+// checkHelpFunc checks if there is helpFunc in ancestors of c.
+func (c *Command) checkHelpFunc() func(*Command, []string) {
+	if c == nil {
+		return nil
+	}
+	if c.helpFunc != nil {
+		return c.helpFunc
+	}
+	if c.HasParent() {
+		return c.parent.checkHelpFunc()
+	}
+	return nil
+}
+
 // Help puts out the help for the command.
 // Used when a user calls help [command].
 // Can be defined by user by overriding HelpFunc.
@@ -257,6 +274,22 @@ func (c *Command) UsageString() string {
 	return bb.String()
 }
 
+// FlagErrorFunc returns either the function set by SetFlagErrorFunc for this
+// command or a parent, or it returns a function which returns the original
+// error.
+func (c *Command) FlagErrorFunc() (f func(*Command, error) error) {
+	if c.flagErrorFunc != nil {
+		return c.flagErrorFunc
+	}
+
+	if c.HasParent() {
+		return c.parent.FlagErrorFunc()
+	}
+	return func(c *Command, err error) error {
+		return err
+	}
+}
+
 var minUsagePadding = 25
 
 func (c *Command) UsagePadding() int {
@@ -553,7 +586,7 @@ func (c *Command) execute(a []string) (err error) {
 
 	err = c.ParseFlags(a)
 	if err != nil {
-		return err
+		return c.FlagErrorFunc()(c, err)
 	}
 	// If help is called, regardless of other flags, return we want help
 	// Also say we need help if the command isn't runnable.
@@ -712,6 +745,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
 }
 
 func (c *Command) initHelpFlag() {
+	c.mergePersistentFlags()
 	if c.Flags().Lookup("help") == nil {
 		c.Flags().BoolP("help", "h", false, "help for "+c.Name())
 	}
diff --git a/doc/man_docs.go b/doc/man_docs.go
index 5798d0f..fd7107c 100644
--- a/doc/man_docs.go
+++ b/doc/man_docs.go
@@ -37,7 +37,7 @@ func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error {
 	return GenManTreeFromOpts(cmd, GenManTreeOptions{
 		Header:           header,
 		Path:             dir,
-		CommandSeparator: "_",
+		CommandSeparator: "-",
 	})
 }
 
diff --git a/doc/man_docs.md b/doc/man_docs.md
index 5fe957a..d568d9a 100644
--- a/doc/man_docs.md
+++ b/doc/man_docs.md
@@ -15,7 +15,7 @@ func main() {
 		Use:   "test",
 		Short: "my test program",
 	}
-	header := &cobra.GenManHeader{
+	header := &doc.GenManHeader{
 		Title: "MINE",
 		Section: "3",
 	}
@@ -23,4 +23,4 @@ func main() {
 }
 ```
 
-That will get you a man page `/tmp/test.1`
+That will get you a man page `/tmp/test.3`
diff --git a/doc/md_docs.md b/doc/md_docs.md
index 0c3b96e..480b152 100644
--- a/doc/md_docs.md
+++ b/doc/md_docs.md
@@ -101,4 +101,3 @@ linkHandler := func(name string) string {
 	return "/commands/" + strings.ToLower(base) + "/"
 }
 ```
-


Test patch:
diff --git a/cobra_test.go b/cobra_test.go
index 699a2f6..46887fd 100644
--- a/cobra_test.go
+++ b/cobra_test.go
@@ -612,7 +612,7 @@ func TestSubcommandExecuteC(t *testing.T) {
 		Use: "echo message",
 		Run: func(c *Command, args []string) {
 			msg := strings.Join(args, " ")
-			c.Println(msg, msg)
+			c.Println(msg)
 		},
 	}
 
diff --git a/command_test.go b/command_test.go
index b0c17e2..7947f6c 100644
--- a/command_test.go
+++ b/command_test.go
@@ -1,6 +1,8 @@
 package cobra
 
 import (
+	"bytes"
+	"fmt"
 	"os"
 	"reflect"
 	"testing"
@@ -134,6 +136,20 @@ func Test_DisableFlagParsing(t *testing.T) {
 	}
 }
 
+func TestInitHelpFlagMergesFlags(t *testing.T) {
+	usage := "custom flag"
+	baseCmd := Command{Use: "testcmd"}
+	baseCmd.PersistentFlags().Bool("help", false, usage)
+	cmd := Command{Use: "do"}
+	baseCmd.AddCommand(&cmd)
+
+	cmd.initHelpFlag()
+	actual := cmd.Flags().Lookup("help").Usage
+	if actual != usage {
+		t.Fatalf("Expected the help flag from the base command with usage '%s', but got the default with usage '%s'", usage, actual)
+	}
+}
+
 func TestCommandsAreSorted(t *testing.T) {
 	EnableCommandSorting = true
 
@@ -174,3 +190,27 @@ func TestEnableCommandSortingIsDisabled(t *testing.T) {
 
 	EnableCommandSorting = true
 }
+
+func TestFlagErrorFunc(t *testing.T) {
+
+	cmd := &Command{
+		Use: "print",
+		RunE: func(cmd *Command, args []string) error {
+			return nil
+		},
+	}
+	expectedFmt := "This is expected: %s"
+
+	cmd.SetFlagErrorFunc(func(c *Command, err error) error {
+		return fmt.Errorf(expectedFmt, err)
+	})
+	cmd.SetArgs([]string{"--bogus-flag"})
+	cmd.SetOutput(new(bytes.Buffer))
+
+	err := cmd.Execute()
+
+	expected := fmt.Sprintf(expectedFmt, "unknown flag: --bogus-flag")
+	if err.Error() != expected {
+		t.Errorf("expected %v, got %v", expected, err.Error())
+	}
+}