mirror of https://github.com/spf13/cobra.git
Ability to hide commands from usage/help text
Added the ability to have hidden commands that cobra will still run as intended, however they won't show up in any usage/help text adding internal field to command private is a better name hiding private commands in default help/usage opting for 'hidden' over 'private' updating all 'help command' checks to exclude hidden commands updating how commands are displayed in usage/help text by updating/adding some methods. added tests for hidden/deprecated commands making command hidden when testing hidden command execution test now leverage the included suite and are much less custom. also removed deprecation tests, once I discovered them in cobra_test.go updating hidden command test to be more reliable removing unnecessary () when checking len(c.Deprecated) updating command comments to be godoc friendly
This commit is contained in:
parent
68f5a81a72
commit
6d2f1d2fa7
|
@ -19,7 +19,7 @@ var _ = os.Stderr
|
||||||
var tp, te, tt, t1, tr []string
|
var tp, te, tt, t1, tr []string
|
||||||
var rootPersPre, echoPre, echoPersPre, timesPersPre []string
|
var rootPersPre, echoPre, echoPersPre, timesPersPre []string
|
||||||
var flagb1, flagb2, flagb3, flagbr, flagbp bool
|
var flagb1, flagb2, flagb3, flagbr, flagbp bool
|
||||||
var flags1, flags2a, flags2b, flags3 string
|
var flags1, flags2a, flags2b, flags3, outs string
|
||||||
var flagi1, flagi2, flagi3, flagir int
|
var flagi1, flagi2, flagi3, flagir int
|
||||||
var globalFlag1 bool
|
var globalFlag1 bool
|
||||||
var flagEcho, rootcalled bool
|
var flagEcho, rootcalled bool
|
||||||
|
@ -28,6 +28,16 @@ var versionUsed int
|
||||||
const strtwoParentHelp = "help message for parent flag strtwo"
|
const strtwoParentHelp = "help message for parent flag strtwo"
|
||||||
const strtwoChildHelp = "help message for child flag strtwo"
|
const strtwoChildHelp = "help message for child flag strtwo"
|
||||||
|
|
||||||
|
var cmdHidden = &Command{
|
||||||
|
Use: "hide [secret string to print]",
|
||||||
|
Short: "Print anything to screen (if command is known)",
|
||||||
|
Long: `an absolutely utterly useless command for testing.`,
|
||||||
|
Run: func(cmd *Command, args []string) {
|
||||||
|
outs = "hidden"
|
||||||
|
},
|
||||||
|
Hidden: true,
|
||||||
|
}
|
||||||
|
|
||||||
var cmdPrint = &Command{
|
var cmdPrint = &Command{
|
||||||
Use: "print [string to print]",
|
Use: "print [string to print]",
|
||||||
Short: "Print anything to the screen",
|
Short: "Print anything to the screen",
|
||||||
|
@ -976,15 +986,15 @@ func TestFlagOnPflagCommandLine(t *testing.T) {
|
||||||
func TestAddTemplateFunctions(t *testing.T) {
|
func TestAddTemplateFunctions(t *testing.T) {
|
||||||
AddTemplateFunc("t", func() bool { return true })
|
AddTemplateFunc("t", func() bool { return true })
|
||||||
AddTemplateFuncs(template.FuncMap{
|
AddTemplateFuncs(template.FuncMap{
|
||||||
"f": func() bool { return false },
|
"f": func() bool { return false },
|
||||||
"h": func() string { return "Hello," },
|
"h": func() string { return "Hello," },
|
||||||
"w": func() string { return "world." }})
|
"w": func() string { return "world." }})
|
||||||
|
|
||||||
const usage = "Hello, world."
|
const usage = "Hello, world."
|
||||||
|
|
||||||
c := &Command{}
|
c := &Command{}
|
||||||
c.SetUsageTemplate(`{{if t}}{{h}}{{end}}{{if f}}{{h}}{{end}} {{w}}`)
|
c.SetUsageTemplate(`{{if t}}{{h}}{{end}}{{if f}}{{h}}{{end}} {{w}}`)
|
||||||
|
|
||||||
if us := c.UsageString(); us != usage {
|
if us := c.UsageString(); us != usage {
|
||||||
t.Errorf("c.UsageString() != \"%s\", is \"%s\"", usage, us)
|
t.Errorf("c.UsageString() != \"%s\", is \"%s\"", usage, us)
|
||||||
}
|
}
|
||||||
|
|
53
command.go
53
command.go
|
@ -51,6 +51,8 @@ type Command struct {
|
||||||
BashCompletionFunction string
|
BashCompletionFunction string
|
||||||
// Is this command deprecated and should print this string when used?
|
// Is this command deprecated and should print this string when used?
|
||||||
Deprecated string
|
Deprecated string
|
||||||
|
// Is this command hidden and should NOT show up in the list of available commands?
|
||||||
|
Hidden bool
|
||||||
// Full set of flags
|
// Full set of flags
|
||||||
flags *flag.FlagSet
|
flags *flag.FlagSet
|
||||||
// Set of flags childrens of this command will inherit
|
// Set of flags childrens of this command will inherit
|
||||||
|
@ -256,9 +258,9 @@ Aliases:
|
||||||
{{end}}{{if .HasExample}}
|
{{end}}{{if .HasExample}}
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
{{ .Example }}{{end}}{{ if .HasNonHelpSubCommands}}
|
{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}
|
||||||
|
|
||||||
Available Commands: {{range .Commands}}{{if (not .IsHelpCommand)}}
|
Available Commands: {{range .Commands}}{{if .IsAvailableCommand}}
|
||||||
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasLocalFlags}}
|
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasLocalFlags}}
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
|
@ -850,42 +852,65 @@ func (c *Command) HasSubCommands() bool {
|
||||||
return len(c.commands) > 0
|
return len(c.commands) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsAvailableCommand determines if a command is available as a non-help command
|
||||||
|
// (this includes all non deprecated/hidden commands)
|
||||||
|
func (c *Command) IsAvailableCommand() bool {
|
||||||
|
|
||||||
|
// a command is 'available' if it is runnable and is not deprecated/hidden
|
||||||
|
return c.Runnable() && len(c.Deprecated) == 0 && !c.Hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHelpCommand determines if a command is a 'help' command; a help command is
|
||||||
|
// determined by the fact that it is NOT runnable/hidden/deprecated, and has no
|
||||||
|
// sub commands that are runnable/hidden/deprecated
|
||||||
func (c *Command) IsHelpCommand() bool {
|
func (c *Command) IsHelpCommand() bool {
|
||||||
if c.Runnable() {
|
|
||||||
|
// if a command is runnable, deprecated, or hidden it is not a 'help' command
|
||||||
|
if c.Runnable() || len(c.Deprecated) != 0 || c.Hidden {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if any non-help sub commands are found, the command is not a 'help' command
|
||||||
for _, sub := range c.commands {
|
for _, sub := range c.commands {
|
||||||
if len(sub.Deprecated) != 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !sub.IsHelpCommand() {
|
if !sub.IsHelpCommand() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the command either has no sub commands, or no non-help sub commands
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasHelpSubCommands determines if a command has any avilable 'help' sub commands
|
||||||
|
// that need to be shown in the usage/help default template under 'additional help
|
||||||
|
// topics'
|
||||||
func (c *Command) HasHelpSubCommands() bool {
|
func (c *Command) HasHelpSubCommands() bool {
|
||||||
|
|
||||||
|
// return true on the first found available 'help' sub command
|
||||||
for _, sub := range c.commands {
|
for _, sub := range c.commands {
|
||||||
if len(sub.Deprecated) != 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if sub.IsHelpCommand() {
|
if sub.IsHelpCommand() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the command either has no sub commands, or no available 'help' sub commands
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Command) HasNonHelpSubCommands() bool {
|
// HasAvailableSubCommands determines if a command has available sub commands that
|
||||||
|
// need to be shown in the usage/help default template under 'available commands'
|
||||||
|
func (c *Command) HasAvailableSubCommands() bool {
|
||||||
|
|
||||||
|
// return true on the first found available (non deprecated/help/hidden)
|
||||||
|
// sub command
|
||||||
for _, sub := range c.commands {
|
for _, sub := range c.commands {
|
||||||
if len(sub.Deprecated) != 0 {
|
if sub.IsAvailableCommand() {
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !sub.IsHelpCommand() {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the command either has no sub comamnds, or no available (non deprecated/help/hidden)
|
||||||
|
// sub commands
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,30 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// test to ensure hidden commands run as intended
|
||||||
|
func TestHiddenCommandExecutes(t *testing.T) {
|
||||||
|
|
||||||
|
// ensure that outs does not already equal what the command will be setting it
|
||||||
|
// to, if it did this test would not actually be testing anything...
|
||||||
|
if outs == "hidden" {
|
||||||
|
t.Errorf("outs should NOT EQUAL hidden")
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdHidden.Execute()
|
||||||
|
|
||||||
|
// upon running the command, the value of outs should now be 'hidden'
|
||||||
|
if outs != "hidden" {
|
||||||
|
t.Errorf("Hidden command failed to run!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test to ensure hidden commands do not show up in usage/help text
|
||||||
|
func TestHiddenCommandIsHidden(t *testing.T) {
|
||||||
|
if cmdHidden.IsAvailableCommand() {
|
||||||
|
t.Errorf("Hidden command found!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestStripFlags(t *testing.T) {
|
func TestStripFlags(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
input []string
|
input []string
|
||||||
|
|
Loading…
Reference in New Issue