Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,57 @@ func ExampleCommand_Run_shellComplete_bash_withShortFlag() {
// --help
}

func ExampleCommand_Run_shellComplete_bash_withDoubleDashFlag() {
cmd := &cli.Command{
Name: "greet",
EnableShellCompletion: true,
Flags: []cli.Flag{
&cli.Int64Flag{
Name: "other",
Aliases: []string{"o"},
},
&cli.StringFlag{
Name: "xyz",
Aliases: []string{"x"},
},
},
}

// Simulate a bash environment and command line arguments
os.Setenv("SHELL", "bash")
os.Args = []string{"greet", "--", "--generate-shell-completion"}

_ = cmd.Run(context.Background(), os.Args)
// Output:
// --other
// --xyz
// --help
}

func ExampleCommand_Run_shellComplete_bash_withDoubleDashFlag_Control() {
cmd := &cli.Command{
Name: "greet",
EnableShellCompletion: true,
Flags: []cli.Flag{
&cli.Int64Flag{
Name: "other",
Aliases: []string{"o"},
},
&cli.StringFlag{
Name: "xyz",
Aliases: []string{"x"},
},
},
}

// Simulate a bash environment and command line arguments
os.Setenv("SHELL", "bash")
os.Args = []string{"greet", "--", "x", "--generate-shell-completion"}

_ = cmd.Run(context.Background(), os.Args)
// Output:
}

func ExampleCommand_Run_shellComplete_bash_withLongFlag() {
cmd := &cli.Command{
Name: "greet",
Expand Down
26 changes: 14 additions & 12 deletions help.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,27 +251,29 @@ func DefaultCompleteWithFlags(ctx context.Context, cmd *Command) {
tracef("running default complete with os.Args flags[%v]", args)
}
argsLen := len(args)
lastArg := ""
var lastButOneArg, lastArg string
// parent command will have --generate-shell-completion so we need
// to account for that
if argsLen > 1 {
lastArg = args[argsLen-2]
lastButOneArg = args[argsLen-2]
lastArg = args[argsLen-1]
} else if argsLen > 0 {
lastButOneArg = args[argsLen-1]
lastArg = args[argsLen-1]
}

if lastArg == "--" {
if lastButOneArg == "--" && lastArg != completionFlag {
tracef("No completions due to termination")
return
}

if lastArg == completionFlag {
lastArg = ""
if lastButOneArg == completionFlag {
lastButOneArg = ""
}

if strings.HasPrefix(lastArg, "-") {
tracef("printing flag suggestion for flag[%v] on command %[1]q", lastArg, cmd.Name)
printFlagSuggestions(lastArg, cmd.Flags, cmd.Root().Writer)
if strings.HasPrefix(lastButOneArg, "-") {
tracef("printing flag suggestion for flag[%v] on command %[1]q", lastButOneArg, cmd.Name)
printFlagSuggestions(lastButOneArg, cmd.Flags, cmd.Root().Writer)
return
}

Expand Down Expand Up @@ -489,11 +491,11 @@ func checkShellCompleteFlag(c *Command, 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.
for i, arg := range arguments {
// If there is "--" which doesn't go right before
// "--generate-shell-completion", shell completion is disabled.
// https://unix.stackexchange.com/a/11382
if arg == "--" {
if arg == "--" && i != len(arguments)-2 {
return false, arguments[:pos]
}
}
Expand Down
31 changes: 31 additions & 0 deletions help_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1270,6 +1270,28 @@ func TestDefaultCompleteWithFlags(t *testing.T) {
},
argv: []string{"cmd", "--e", "--", completionFlag},
env: map[string]string{"SHELL": "bash"},
expected: "--excitement\n--hat-shape\n",
},
{
name: "double-dash-in-the-middle",
cmd: &Command{
Flags: []Flag{
&BoolFlag{Name: "excitement"},
&StringFlag{Name: "hat-shape"},
},
parent: &Command{
Name: "cmd",
Flags: []Flag{
&BoolFlag{Name: "happiness"},
&Int64Flag{Name: "everybody-jump-on"},
},
Commands: []*Command{
{Name: "putz"},
},
},
},
argv: []string{"cmd", "--", "--e"},
env: map[string]string{"SHELL": "bash"},
expected: "",
},
{
Expand Down Expand Up @@ -1824,6 +1846,15 @@ func Test_checkShellCompleteFlag(t *testing.T) {
wantShellCompletion: false,
wantArgs: []string{"--", "foo"},
},
{
name: "double dash is just before --generate-shell-completion",
arguments: []string{"foo", "--", completionFlag},
cmd: &Command{
EnableShellCompletion: true,
},
wantShellCompletion: true,
wantArgs: []string{"foo", "--"},
},
{
name: "shell completion",
arguments: []string{"foo", completionFlag},
Expand Down