diff --git a/help.go b/help.go index 640e290452..874be941c0 100644 --- a/help.go +++ b/help.go @@ -248,7 +248,6 @@ func ShowCommandHelpAndExit(c *Context, command string, code int) { // ShowCommandHelp prints help for the given command func ShowCommandHelp(ctx *Context, command string) error { - commands := ctx.App.Commands if ctx.Command.Subcommands != nil { commands = ctx.Command.Subcommands @@ -337,7 +336,6 @@ func ShowCommandCompletions(ctx *Context, command string) { DefaultCompleteWithFlags(c)(ctx) } } - } // printHelpCustom is the default implementation of HelpPrinterCustom. @@ -345,7 +343,6 @@ func ShowCommandCompletions(ctx *Context, command string) { // The customFuncs map will be combined with a default template.FuncMap to // allow using arbitrary functions in template rendering. func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs map[string]interface{}) { - const maxLineLength = 10000 funcMap := template.FuncMap{ @@ -450,6 +447,15 @@ func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) { return false, arguments } + for _, arg := range arguments { + // If arguments include "--", shell completion is disabled + // because after "--" only positional arguments are accepted. + // https://unix.stackexchange.com/a/11382 + if arg == "--" { + return false, arguments + } + } + return true, arguments[:pos] } @@ -499,7 +505,6 @@ func wrap(input string, offset int, wrapAt int) string { ss = append(ss, wrapped) } else { ss = append(ss, padding+wrapped) - } } diff --git a/help_test.go b/help_test.go index a39f818798..8a856258ae 100644 --- a/help_test.go +++ b/help_test.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "os" + "reflect" "runtime" "strings" "testing" @@ -1349,7 +1350,6 @@ func TestWrap(t *testing.T) { } func TestWrappedHelp(t *testing.T) { - // Reset HelpPrinter after this test. defer func(old helpPrinter) { HelpPrinter = old @@ -1359,7 +1359,8 @@ func TestWrappedHelp(t *testing.T) { app := &App{ Writer: output, Flags: []Flag{ - &BoolFlag{Name: "foo", + &BoolFlag{ + Name: "foo", Aliases: []string{"h"}, Usage: "here's a really long help text line, let's see where it wraps. blah blah blah and so on.", }, @@ -1443,7 +1444,6 @@ COPYRIGHT: } func TestWrappedCommandHelp(t *testing.T) { - // Reset HelpPrinter after this test. defer func(old helpPrinter) { HelpPrinter = old @@ -1504,7 +1504,6 @@ OPTIONS: } func TestWrappedSubcommandHelp(t *testing.T) { - // Reset HelpPrinter after this test. defer func(old helpPrinter) { HelpPrinter = old @@ -1573,7 +1572,6 @@ OPTIONS: } func TestWrappedHelpSubcommand(t *testing.T) { - // Reset HelpPrinter after this test. defer func(old helpPrinter) { HelpPrinter = old @@ -1714,3 +1712,65 @@ GLOBAL OPTIONS: output.String(), expected) } } + +func Test_checkShellCompleteFlag(t *testing.T) { + t.Parallel() + tests := []struct { + name string + app *App + arguments []string + wantShellCompletion bool + wantArgs []string + }{ + { + name: "disable bash completion", + arguments: []string{"--generate-bash-completion"}, + app: &App{}, + wantShellCompletion: false, + wantArgs: []string{"--generate-bash-completion"}, + }, + { + name: "--generate-bash-completion isn't used", + arguments: []string{"foo"}, + app: &App{ + EnableBashCompletion: true, + }, + wantShellCompletion: false, + wantArgs: []string{"foo"}, + }, + { + name: "arguments include double dash", + arguments: []string{"--", "foo", "--generate-bash-completion"}, + app: &App{ + EnableBashCompletion: true, + }, + wantShellCompletion: false, + wantArgs: []string{"--", "foo", "--generate-bash-completion"}, + }, + { + name: "--generate-bash-completion", + arguments: []string{"foo", "--generate-bash-completion"}, + app: &App{ + EnableBashCompletion: true, + }, + wantShellCompletion: true, + wantArgs: []string{"foo"}, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + shellCompletion, args := checkShellCompleteFlag(tt.app, tt.arguments) + if tt.wantShellCompletion != shellCompletion { + t.Errorf("Unexpected shell completion, got:\n%v\nexpected: %v", + shellCompletion, tt.wantShellCompletion) + } + if !reflect.DeepEqual(tt.wantArgs, args) { + t.Errorf("Unexpected arguments, got:\n%v\nexpected: %v", + args, tt.wantArgs) + } + }) + } +}