Merge pull request #143 from sdomino/feature/hidden-commands
Feature/hidden commands
This commit is contained in:
		@ -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
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user