Skip to content

Commit 84addde

Browse files
committed
fix completion of "--"
Use https://cli.urfave.org/v3/examples/completions/shell-completions as a reference for completions. The previous version completed "-" -> "--" -> "--help,", but the added comma was incorrect, as no such flag exists and the tool does not accept it. A similar issue occurred with "--version", which was shown as "--version,". The root cause was that completion was explicitly disabled for this case: $ greet -- --generate-shell-completion As a result, it printed the default help message: > NAME: > greet - A new cli application > > USAGE: > greet [global options] [command [command options]] > > COMMANDS: > add, a add a task to the list > complete, c complete a task on the list > template, t options for task templates > help, h Shows a list of commands or help for one command > > GLOBAL OPTIONS: > --help, -h show help Bash used "--help," as a flag suggestion, which was incorrect. In this commit, completion is enabled for the "-- --generate-shell-completion" case, and a test is added to verify correct behavior. With this change, both "-" and "--" now complete to "--help", which is correct.
1 parent 19d941b commit 84addde

File tree

3 files changed

+90
-6
lines changed

3 files changed

+90
-6
lines changed

examples_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,57 @@ func ExampleCommand_Run_shellComplete_bash_withShortFlag() {
268268
// --help
269269
}
270270

271+
func ExampleCommand_Run_shellComplete_bash_withDoubleDashFlag() {
272+
cmd := &cli.Command{
273+
Name: "greet",
274+
EnableShellCompletion: true,
275+
Flags: []cli.Flag{
276+
&cli.Int64Flag{
277+
Name: "other",
278+
Aliases: []string{"o"},
279+
},
280+
&cli.StringFlag{
281+
Name: "xyz",
282+
Aliases: []string{"x"},
283+
},
284+
},
285+
}
286+
287+
// Simulate a bash environment and command line arguments
288+
os.Setenv("SHELL", "bash")
289+
os.Args = []string{"greet", "--", "--generate-shell-completion"}
290+
291+
_ = cmd.Run(context.Background(), os.Args)
292+
// Output:
293+
// --other
294+
// --xyz
295+
// --help
296+
}
297+
298+
func ExampleCommand_Run_shellComplete_bash_withDoubleDashFlag_Control() {
299+
cmd := &cli.Command{
300+
Name: "greet",
301+
EnableShellCompletion: true,
302+
Flags: []cli.Flag{
303+
&cli.Int64Flag{
304+
Name: "other",
305+
Aliases: []string{"o"},
306+
},
307+
&cli.StringFlag{
308+
Name: "xyz",
309+
Aliases: []string{"x"},
310+
},
311+
},
312+
}
313+
314+
// Simulate a bash environment and command line arguments
315+
os.Setenv("SHELL", "bash")
316+
os.Args = []string{"greet", "--", "x", "--generate-shell-completion"}
317+
318+
_ = cmd.Run(context.Background(), os.Args)
319+
// Output:
320+
}
321+
271322
func ExampleCommand_Run_shellComplete_bash_withLongFlag() {
272323
cmd := &cli.Command{
273324
Name: "greet",

help.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,16 +251,18 @@ func DefaultCompleteWithFlags(ctx context.Context, cmd *Command) {
251251
tracef("running default complete with os.Args flags[%v]", args)
252252
}
253253
argsLen := len(args)
254-
lastArg := ""
254+
var lastArg, veryLastArg string
255255
// parent command will have --generate-shell-completion so we need
256256
// to account for that
257257
if argsLen > 1 {
258258
lastArg = args[argsLen-2]
259+
veryLastArg = args[argsLen-1]
259260
} else if argsLen > 0 {
260261
lastArg = args[argsLen-1]
262+
veryLastArg = args[argsLen-1]
261263
}
262264

263-
if lastArg == "--" {
265+
if lastArg == "--" && veryLastArg != completionFlag {
264266
tracef("No completions due to termination")
265267
return
266268
}
@@ -489,11 +491,11 @@ func checkShellCompleteFlag(c *Command, arguments []string) (bool, []string) {
489491
return false, arguments
490492
}
491493

492-
for _, arg := range arguments {
493-
// If arguments include "--", shell completion is disabled
494-
// because after "--" only positional arguments are accepted.
494+
for i, arg := range arguments {
495+
// If there is "--" which doesn't go right before
496+
// "--generate-shell-completion", shell completion is disabled.
495497
// https://unix.stackexchange.com/a/11382
496-
if arg == "--" {
498+
if arg == "--" && i != len(arguments)-2 {
497499
return false, arguments[:pos]
498500
}
499501
}

help_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,28 @@ func TestDefaultCompleteWithFlags(t *testing.T) {
12701270
},
12711271
argv: []string{"cmd", "--e", "--", completionFlag},
12721272
env: map[string]string{"SHELL": "bash"},
1273+
expected: "--excitement\n--hat-shape\n",
1274+
},
1275+
{
1276+
name: "double-dash-in-the-middle",
1277+
cmd: &Command{
1278+
Flags: []Flag{
1279+
&BoolFlag{Name: "excitement"},
1280+
&StringFlag{Name: "hat-shape"},
1281+
},
1282+
parent: &Command{
1283+
Name: "cmd",
1284+
Flags: []Flag{
1285+
&BoolFlag{Name: "happiness"},
1286+
&Int64Flag{Name: "everybody-jump-on"},
1287+
},
1288+
Commands: []*Command{
1289+
{Name: "putz"},
1290+
},
1291+
},
1292+
},
1293+
argv: []string{"cmd", "--", "--e"},
1294+
env: map[string]string{"SHELL": "bash"},
12731295
expected: "",
12741296
},
12751297
{
@@ -1825,6 +1847,15 @@ func Test_checkShellCompleteFlag(t *testing.T) {
18251847
wantShellCompletion: false,
18261848
wantArgs: []string{"--", "foo"},
18271849
},
1850+
{
1851+
name: "double dash is just before --generate-shell-completion",
1852+
arguments: []string{"foo", "--", completionFlag},
1853+
cmd: &Command{
1854+
EnableShellCompletion: true,
1855+
},
1856+
wantShellCompletion: true,
1857+
wantArgs: []string{"foo", "--"},
1858+
},
18281859
{
18291860
name: "shell completion",
18301861
arguments: []string{"foo", completionFlag},

0 commit comments

Comments
 (0)