Skip to content

Commit

Permalink
Merge pull request #1083 from AkihiroSuda/hide-help-command
Browse files Browse the repository at this point in the history
Add HideHelpCommand
  • Loading branch information
rliebz committed Mar 6, 2020
2 parents 3cc9946 + 75e7c52 commit d648edd
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 15 deletions.
21 changes: 8 additions & 13 deletions app.go
Expand Up @@ -43,8 +43,11 @@ type App struct {
Flags []Flag
// Boolean to enable bash completion commands
EnableBashCompletion bool
// Boolean to hide built-in help command
// Boolean to hide built-in help command and help flag
HideHelp bool
// Boolean to hide built-in help command but keep help flag.
// Ignored if HideHelp is true.
HideHelpCommand bool
// Boolean to hide built-in version flag and the VERSION section of help
HideVersion bool
// categories contains the categorized commands and is populated on app startup
Expand Down Expand Up @@ -170,7 +173,9 @@ func (a *App) Setup() {
a.Commands = newCommands

if a.Command(helpCommand.Name) == nil && !a.HideHelp {
a.appendCommand(helpCommand)
if !a.HideHelpCommand {
a.appendCommand(helpCommand)
}

if HelpFlag != nil {
a.appendFlag(HelpFlag)
Expand Down Expand Up @@ -328,19 +333,9 @@ func (a *App) RunAndExitOnError() {
// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to
// generate command-specific flags
func (a *App) RunAsSubcommand(ctx *Context) (err error) {
// Setup also handles HideHelp and HideHelpCommand
a.Setup()

// append help to commands
if len(a.Commands) > 0 {
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
a.appendCommand(helpCommand)

if HelpFlag != nil {
a.appendFlag(HelpFlag)
}
}
}

var newCmds []*Command
for _, c := range a.Commands {
if c.HelpName == "" {
Expand Down
6 changes: 5 additions & 1 deletion command.go
Expand Up @@ -41,8 +41,11 @@ type Command struct {
Flags []Flag
// Treat all flags as normal arguments if true
SkipFlagParsing bool
// Boolean to hide built-in help command
// Boolean to hide built-in help command and help flag
HideHelp bool
// Boolean to hide built-in help command but keep help flag
// Ignored if HideHelp is true.
HideHelpCommand bool
// Boolean to hide this command from help or completion
Hidden bool
// Boolean to enable short-option handling so user can combine several
Expand Down Expand Up @@ -236,6 +239,7 @@ func (c *Command) startApp(ctx *Context) error {
app.Commands = c.Subcommands
app.Flags = c.Flags
app.HideHelp = c.HideHelp
app.HideHelpCommand = c.HideHelpCommand

app.Version = ctx.App.Version
app.HideVersion = ctx.App.HideVersion
Expand Down
2 changes: 1 addition & 1 deletion flag.go
Expand Up @@ -36,7 +36,7 @@ var VersionFlag Flag = &BoolFlag{

// HelpFlag prints the help for all commands and subcommands.
// Set to nil to disable the flag. The subcommand
// will still be added unless HideHelp is set to true.
// will still be added unless HideHelp or HideHelpCommand is set to true.
var HelpFlag Flag = &BoolFlag{
Name: "help",
Aliases: []string{"h"},
Expand Down
145 changes: 145 additions & 0 deletions help_test.go
Expand Up @@ -5,6 +5,7 @@ import (
"flag"
"fmt"
"io"
"io/ioutil"
"runtime"
"strings"
"testing"
Expand Down Expand Up @@ -762,3 +763,147 @@ VERSION:
t.Errorf("expected output to include \"VERSION:, 2.0.0\"; got: %q", output.String())
}
}

func TestHideHelpCommand(t *testing.T) {
app := &App{
HideHelpCommand: true,
Writer: ioutil.Discard,
}

err := app.Run([]string{"foo", "help"})
if err == nil {
t.Fatalf("expected a non-nil error")
}
if !strings.Contains(err.Error(), "No help topic for 'help'") {
t.Errorf("Run returned unexpected error: %v", err)
}

err = app.Run([]string{"foo", "--help"})
if err != nil {
t.Errorf("Run returned unexpected error: %v", err)
}
}

func TestHideHelpCommand_False(t *testing.T) {
app := &App{
HideHelpCommand: false,
Writer: ioutil.Discard,
}

err := app.Run([]string{"foo", "help"})
if err != nil {
t.Errorf("Run returned unexpected error: %v", err)
}

err = app.Run([]string{"foo", "--help"})
if err != nil {
t.Errorf("Run returned unexpected error: %v", err)
}
}

func TestHideHelpCommand_WithHideHelp(t *testing.T) {
app := &App{
HideHelp: true, // effective (hides both command and flag)
HideHelpCommand: true, // ignored
Writer: ioutil.Discard,
}

err := app.Run([]string{"foo", "help"})
if err == nil {
t.Fatalf("expected a non-nil error")
}
if !strings.Contains(err.Error(), "No help topic for 'help'") {
t.Errorf("Run returned unexpected error: %v", err)
}

err = app.Run([]string{"foo", "--help"})
if err == nil {
t.Fatalf("expected a non-nil error")
}
if !strings.Contains(err.Error(), "flag: help requested") {
t.Errorf("Run returned unexpected error: %v", err)
}
}

func newContextFromStringSlice(ss []string) *Context {
set := flag.NewFlagSet("", flag.ContinueOnError)
_ = set.Parse(ss)
return &Context{flagSet: set}
}

func TestHideHelpCommand_RunAsSubcommand(t *testing.T) {
app := &App{
HideHelpCommand: true,
Writer: ioutil.Discard,
Commands: []*Command{
{
Name: "dummy",
},
},
}

err := app.RunAsSubcommand(newContextFromStringSlice([]string{"", "help"}))
if err == nil {
t.Fatalf("expected a non-nil error")
}
if !strings.Contains(err.Error(), "No help topic for 'help'") {
t.Errorf("Run returned unexpected error: %v", err)
}

err = app.RunAsSubcommand(newContextFromStringSlice([]string{"", "--help"}))
if err != nil {
t.Errorf("Run returned unexpected error: %v", err)
}
}

func TestHideHelpCommand_RunAsSubcommand_False(t *testing.T) {
app := &App{
HideHelpCommand: false,
Writer: ioutil.Discard,
Commands: []*Command{
{
Name: "dummy",
},
},
}

err := app.RunAsSubcommand(newContextFromStringSlice([]string{"", "help"}))
if err != nil {
t.Errorf("Run returned unexpected error: %v", err)
}

err = app.RunAsSubcommand(newContextFromStringSlice([]string{"", "--help"}))
if err != nil {
t.Errorf("Run returned unexpected error: %v", err)
}
}

func TestHideHelpCommand_WithSubcommands(t *testing.T) {
app := &App{
Writer: ioutil.Discard,
Commands: []*Command{
{
Name: "dummy",
Subcommands: []*Command{
{
Name: "dummy2",
},
},
HideHelpCommand: true,
},
},
}

err := app.Run([]string{"foo", "dummy", "help"})
if err == nil {
t.Fatalf("expected a non-nil error")
}
if !strings.Contains(err.Error(), "No help topic for 'help'") {
t.Errorf("Run returned unexpected error: %v", err)
}

err = app.Run([]string{"foo", "dummy", "--help"})
if err != nil {
t.Errorf("Run returned unexpected error: %v", err)
}
}

0 comments on commit d648edd

Please sign in to comment.