diff --git a/cobra.go b/cobra.go index 7c8da2b4..7572ddf3 100644 --- a/cobra.go +++ b/cobra.go @@ -27,11 +27,12 @@ import ( ) var templateFuncs template.FuncMap = template.FuncMap{ - "trim": strings.TrimSpace, - "trimRightSpace": trimRightSpace, - "rpad": rpad, - "gt": Gt, - "eq": Eq, + "trim": strings.TrimSpace, + "trimRightSpace": trimRightSpace, + "appendIfNotPresent": appendIfNotPresent, + "rpad": rpad, + "gt": Gt, + "eq": Eq, } var initializers []func() @@ -111,6 +112,14 @@ func trimRightSpace(s string) string { return strings.TrimRightFunc(s, unicode.IsSpace) } +// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s +func appendIfNotPresent(s, stringToAppend string) string { + if strings.Contains(s, stringToAppend) { + return s + } + return s + " " + stringToAppend +} + //rpad adds padding to the right of a string func rpad(s string, padding int) string { template := fmt.Sprintf("%%-%ds", padding) diff --git a/cobra_test.go b/cobra_test.go index e8c770f2..99dafde4 100644 --- a/cobra_test.go +++ b/cobra_test.go @@ -20,7 +20,7 @@ var tp, te, tt, t1, tr []string var rootPersPre, echoPre, echoPersPre, timesPersPre []string var flagb1, flagb2, flagb3, flagbr, flagbp bool var flags1, flags2a, flags2b, flags3, outs string -var flagi1, flagi2, flagi3, flagir int +var flagi1, flagi2, flagi3, flagi4, flagir int var globalFlag1 bool var flagEcho, rootcalled bool var versionUsed int @@ -125,6 +125,14 @@ var cmdSubNoRun = &Command{ Long: "A long output about a subcommand without a Run function", } +var cmdCustomFlags = &Command{ + Use: "customflags [flags] -- REMOTE_COMMAND", + Short: "A command that expects flags in a custom location", + Long: "A long output about a command that expects flags in a custom location", + Run: func(cmd *Command, args []string) { + }, +} + var cmdVersion1 = &Command{ Use: "version", Short: "Print the version number", @@ -157,10 +165,12 @@ func flagInit() { cmdRootSameName.ResetFlags() cmdRootWithRun.ResetFlags() cmdSubNoRun.ResetFlags() + cmdCustomFlags.ResetFlags() cmdRootNoRun.PersistentFlags().StringVarP(&flags2a, "strtwo", "t", "two", strtwoParentHelp) cmdEcho.Flags().IntVarP(&flagi1, "intone", "i", 123, "help message for flag intone") cmdTimes.Flags().IntVarP(&flagi2, "inttwo", "j", 234, "help message for flag inttwo") cmdPrint.Flags().IntVarP(&flagi3, "intthree", "i", 345, "help message for flag intthree") + cmdCustomFlags.Flags().IntVar(&flagi4, "intfour", 456, "help message for flag intfour") cmdEcho.PersistentFlags().StringVarP(&flags1, "strone", "s", "one", "help message for flag strone") cmdEcho.PersistentFlags().BoolVarP(&flagbp, "persistentbool", "p", false, "help message for flag persistentbool") cmdTimes.PersistentFlags().StringVarP(&flags2b, "strtwo", "t", "2", strtwoChildHelp) @@ -180,6 +190,7 @@ func commandInit() { cmdRootSameName.ResetCommands() cmdRootWithRun.ResetCommands() cmdSubNoRun.ResetCommands() + cmdCustomFlags.ResetCommands() } func initialize() *Command { @@ -271,7 +282,7 @@ func fullTester(c *Command, input string) resulter { // Testing flag with invalid input c.SetOutput(buf) cmdEcho.AddCommand(cmdTimes) - c.AddCommand(cmdPrint, cmdEcho, cmdSubNoRun, cmdDeprecated) + c.AddCommand(cmdPrint, cmdEcho, cmdSubNoRun, cmdCustomFlags, cmdDeprecated) c.SetArgs(strings.Split(input, " ")) err := c.Execute() @@ -441,6 +452,14 @@ func TestGrandChildSameName(t *testing.T) { } } +func TestUsage(t *testing.T) { + x := fullSetupTest("help") + checkResultContains(t, x, cmdRootWithRun.Use + " [flags]") + x = fullSetupTest("help customflags") + checkResultContains(t, x, cmdCustomFlags.Use) + checkResultOmits(t, x, cmdCustomFlags.Use + " [flags]") +} + func TestFlagLong(t *testing.T) { noRRSetupTest("echo --intone=13 something -- here") diff --git a/command.go b/command.go index ccc41c38..7671ce50 100644 --- a/command.go +++ b/command.go @@ -263,7 +263,7 @@ func (c *Command) UsageTemplate() string { return c.parent.UsageTemplate() } else { return `Usage:{{if .Runnable}} - {{.UseLine}}{{if .HasFlags}} [flags]{{end}}{{end}}{{if .HasSubCommands}} + {{if .HasFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasSubCommands}} {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}} Aliases: