Merge pull request #143 from sdomino/feature/hidden-commands

Feature/hidden commands
This commit is contained in:
Eric Paris 2015-09-08 18:19:22 -05:00
commit b625a4db24
3 changed files with 78 additions and 19 deletions

View File

@ -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)
} }

View File

@ -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
} }

View File

@ -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