Skip to content

Commit 600026f

Browse files
authored
Merge pull request #2270 from Maks1mS/feat/dynamic-fish-completion
feat: support dynamic fish completion
2 parents 7f5c797 + 08fd570 commit 600026f

File tree

4 files changed

+78
-3
lines changed

4 files changed

+78
-3
lines changed

autocomplete/fish_autocomplete

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# This is a shell completion script auto-generated by https://github.com/urfave/cli for fish.
2+
3+
function __%[1]_perform_completion
4+
# Extract all args except the last one
5+
set -l args (commandline -opc)
6+
# Extract the last arg (partial input)
7+
set -l lastArg (commandline -ct)
8+
9+
set -l results ($args[1] $args[2..-1] $lastArg --generate-shell-completion 2> /dev/null)
10+
11+
# Remove trailing empty lines
12+
for line in $results[-1..1]
13+
if test (string trim -- $line) = ""
14+
set results $results[1..-2]
15+
else
16+
break
17+
end
18+
end
19+
20+
for line in $results
21+
if not string match -q -- "%[1]*" $line
22+
set -l parts (string split -m 1 ":" -- "$line")
23+
if test (count $parts) -eq 2
24+
printf "%s\t%s\n" "$parts[1]" "$parts[2]"
25+
else
26+
printf "%s\n" "$line"
27+
end
28+
end
29+
end
30+
end
31+
32+
# Clear existing completions for %[1]
33+
complete -c %[1] -e
34+
# Register completion function
35+
complete -c %[1] -f -a '(__%[1]_perform_completion)'

completion.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ var (
3131
return fmt.Sprintf(string(b), appName), err
3232
},
3333
"fish": func(c *Command, appName string) (string, error) {
34-
return c.Root().ToFishCompletion()
34+
b, err := autoCompleteFS.ReadFile("autocomplete/fish_autocomplete")
35+
return fmt.Sprintf(string(b), appName), err
3536
},
3637
"pwsh": func(c *Command, appName string) (string, error) {
3738
b, err := autoCompleteFS.ReadFile("autocomplete/powershell_autocomplete.ps1")

examples_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,43 @@ func ExampleCommand_Run_shellComplete_zsh() {
409409
// help:Shows a list of commands or help for one command
410410
}
411411

412+
func ExampleCommand_Run_shellComplete_fish() {
413+
cmd := &cli.Command{
414+
Name: "greet",
415+
EnableShellCompletion: true,
416+
Commands: []*cli.Command{
417+
{
418+
Name: "describeit",
419+
Aliases: []string{"d"},
420+
Usage: "use it to see a description",
421+
Description: "This is how we describe describeit the function",
422+
Action: func(context.Context, *cli.Command) error {
423+
fmt.Printf("i like to describe things")
424+
return nil
425+
},
426+
}, {
427+
Name: "next",
428+
Usage: "next example",
429+
Description: "more stuff to see when generating bash completion",
430+
Action: func(context.Context, *cli.Command) error {
431+
fmt.Printf("the next example")
432+
return nil
433+
},
434+
},
435+
},
436+
}
437+
438+
// Simulate a fish environment and command line arguments
439+
os.Args = []string{"greet", "--generate-shell-completion"}
440+
os.Setenv("SHELL", "/usr/bin/fish")
441+
442+
_ = cmd.Run(context.Background(), os.Args)
443+
// Output:
444+
// describeit:use it to see a description
445+
// next:next example
446+
// help:Shows a list of commands or help for one command
447+
}
448+
412449
func ExampleCommand_Run_sliceValues() {
413450
cmd := &cli.Command{
414451
Name: "multi_values",

help.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,12 @@ func DefaultRootCommandComplete(ctx context.Context, cmd *Command) {
184184
var DefaultAppComplete = DefaultRootCommandComplete
185185

186186
func printCommandSuggestions(commands []*Command, writer io.Writer) {
187+
shell := os.Getenv("SHELL")
187188
for _, command := range commands {
188189
if command.Hidden {
189190
continue
190191
}
191-
if strings.HasSuffix(os.Getenv("SHELL"), "zsh") && len(command.Usage) > 0 {
192+
if (strings.HasSuffix(shell, "zsh") || strings.HasSuffix(shell, "fish")) && len(command.Usage) > 0 {
192193
_, _ = fmt.Fprintf(writer, "%s:%s\n", command.Name, command.Usage)
193194
} else {
194195
_, _ = fmt.Fprintf(writer, "%s\n", command.Name)
@@ -240,7 +241,8 @@ func printFlagSuggestions(lastArg string, flags []Flag, writer io.Writer) {
240241
// match if last argument matches this flag and it is not repeated
241242
if strings.HasPrefix(name, cur) && cur != name /* && !cliArgContains(name, os.Args)*/ {
242243
flagCompletion := fmt.Sprintf("%s%s", strings.Repeat("-", count), name)
243-
if usage != "" && strings.HasSuffix(os.Getenv("SHELL"), "zsh") {
244+
shell := os.Getenv("SHELL")
245+
if usage != "" && (strings.HasSuffix(shell, "zsh") || strings.HasSuffix(shell, "fish")) {
244246
flagCompletion = fmt.Sprintf("%s:%s", flagCompletion, usage)
245247
}
246248
fmt.Fprintln(writer, flagCompletion)

0 commit comments

Comments
 (0)