diff --git a/bash_completions.go b/bash_completions.go index dee95b31..485a9a3a 100644 --- a/bash_completions.go +++ b/bash_completions.go @@ -199,6 +199,9 @@ func postscript(out *bytes.Buffer, name string) { func writeCommands(cmd *Command, out *bytes.Buffer) { fmt.Fprintf(out, " commands=()\n") for _, c := range cmd.Commands() { + if len(c.Deprecated) > 0 { + continue + } fmt.Fprintf(out, " commands+=(%q)\n", c.Name()) } fmt.Fprintf(out, "\n") @@ -291,6 +294,9 @@ func writeRequiredNoun(cmd *Command, out *bytes.Buffer) { func gen(cmd *Command, out *bytes.Buffer) { for _, c := range cmd.Commands() { + if len(c.Deprecated) > 0 { + continue + } gen(c, out) } commandName := cmd.CommandPath() diff --git a/bash_completions_test.go b/bash_completions_test.go index 12dc9604..4b7d06c6 100644 --- a/bash_completions_test.go +++ b/bash_completions_test.go @@ -11,6 +11,12 @@ import ( var _ = fmt.Println var _ = os.Stderr +func checkOmit(t *testing.T, found, unexpected string) { + if strings.Contains(found, unexpected) { + t.Errorf("Unexpected response.\nGot: %q\nBut should not have!\n", unexpected) + } +} + func check(t *testing.T, found, expected string) { if !strings.Contains(found, expected) { t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) @@ -28,7 +34,7 @@ COMPREPLY=( "hello" ) func TestBashCompletions(t *testing.T) { c := initializeWithRootCmd() cmdEcho.AddCommand(cmdTimes) - c.AddCommand(cmdEcho, cmdPrint) + c.AddCommand(cmdEcho, cmdPrint, cmdDeprecated) // custom completion function c.BashCompletionFunction = bash_completion_func @@ -71,4 +77,6 @@ func TestBashCompletions(t *testing.T) { check(t, str, `must_have_one_noun+=("pods")`) // check for filename extention flags check(t, str, `flags_completion+=("_filedir '@(json|yaml|yml)'")`) + + checkOmit(t, str, cmdDeprecated.Name()) } diff --git a/cobra_test.go b/cobra_test.go index 6feb8e56..648fc121 100644 --- a/cobra_test.go +++ b/cobra_test.go @@ -51,6 +51,15 @@ var cmdEchoSub = &Command{ }, } +var cmdDeprecated = &Command{ + Use: "deprecated [can't do anything here]", + Short: "A command which is deprecated", + Long: `an absolutely utterly useless command for testing deprecation!.`, + Deprecated: "Please use echo instead", + Run: func(cmd *Command, args []string) { + }, +} + var cmdTimes = &Command{ Use: "times [# times] [string to echo]", Short: "Echo anything to the screen more times", @@ -205,7 +214,7 @@ func fullTester(c *Command, input string) resulter { // Testing flag with invalid input c.SetOutput(buf) cmdEcho.AddCommand(cmdTimes) - c.AddCommand(cmdPrint, cmdEcho, cmdSubNoRun) + c.AddCommand(cmdPrint, cmdEcho, cmdSubNoRun, cmdDeprecated) c.SetArgs(strings.Split(input, " ")) err := c.Execute() @@ -812,3 +821,9 @@ func TestReplaceCommandWithRemove(t *testing.T) { t.Errorf("Replacing command should have been called but didn't\n") } } + +func TestDeprecatedSub(t *testing.T) { + c := fullSetupTest("deprecated") + + checkResultContains(t, c, cmdDeprecated.Deprecated) +} diff --git a/command.go b/command.go index ef802c67..24165d93 100644 --- a/command.go +++ b/command.go @@ -48,6 +48,8 @@ type Command struct { ValidArgs []string // Custom functions used by the bash autocompletion generator BashCompletionFunction string + // Is this command deprecated and should print this string when used? + Deprecated string // Full set of flags flags *flag.FlagSet // Set of flags childrens of this command will inherit @@ -231,7 +233,7 @@ Examples: {{ .Example }} {{end}}{{ if .HasRunnableSubCommands}} -Available Commands: {{range .Commands}}{{if .Runnable}} +Available Commands: {{range .Commands}}{{if and (.Runnable) (not .Deprecated)}} {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}} {{end}} {{ if .HasLocalFlags}}Flags: @@ -239,7 +241,7 @@ Available Commands: {{range .Commands}}{{if .Runnable}} {{ if .HasInheritedFlags}}Global Flags: {{.InheritedFlags.FlagUsages}}{{end}}{{if or (.HasHelpSubCommands) (.HasRunnableSiblings)}} Additional help topics: -{{if .HasHelpSubCommands}}{{range .Commands}}{{if not .Runnable}} {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasRunnableSiblings }}{{range .Parent.Commands}}{{if .Runnable}}{{if not (eq .Name $cmd.Name) }} +{{if .HasHelpSubCommands}}{{range .Commands}}{{if and (not .Runnable) (not .Deprecated)}} {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasRunnableSiblings }}{{range .Parent.Commands}}{{if and (not .Runnable) (not .Deprecated)}}{{if not (eq .Name $cmd.Name) }} {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{end}} {{end}}{{ if .HasSubCommands }} Use "{{.Root.Name}} help [command]" for more information about a command. @@ -414,6 +416,10 @@ func (c *Command) execute(a []string) (err error) { return fmt.Errorf("Called Execute() on a nil Command") } + if len(c.Deprecated) > 0 { + c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated) + } + err = c.ParseFlags(a) if err == flag.ErrHelp { c.Help() diff --git a/md_docs.go b/md_docs.go index ab5188e7..4a57ebd0 100644 --- a/md_docs.go +++ b/md_docs.go @@ -85,6 +85,9 @@ func GenMarkdown(cmd *Command, out *bytes.Buffer) { sort.Sort(byName(children)) for _, child := range children { + if len(child.Deprecated) > 0 { + continue + } cname := name + " " + child.Name() link := cname + ".md" link = strings.Replace(link, " ", "_", -1) diff --git a/md_docs_test.go b/md_docs_test.go index fd11ad32..defc9411 100644 --- a/md_docs_test.go +++ b/md_docs_test.go @@ -14,7 +14,7 @@ var _ = os.Stderr func TestGenMdDoc(t *testing.T) { c := initializeWithRootCmd() // Need two commands to run the command alphabetical sort - cmdEcho.AddCommand(cmdTimes, cmdEchoSub) + cmdEcho.AddCommand(cmdTimes, cmdEchoSub, cmdDeprecated) c.AddCommand(cmdPrint, cmdEcho) cmdRootWithRun.PersistentFlags().StringVarP(&flags2a, "rootflag", "r", "two", strtwoParentHelp) @@ -59,4 +59,9 @@ func TestGenMdDoc(t *testing.T) { if !strings.Contains(found, expected) { t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) } + + unexpected := cmdDeprecated.Short + if strings.Contains(found, unexpected) { + t.Errorf("Unexpected response.\nFound: %v\nBut should not have!!\n", unexpected) + } }