Skip to content

Commit af661dd

Browse files
authored
Merge pull request #2256 from marcusramberg/fish
feat: ShellComplete for fish
2 parents 42779d5 + ddf6444 commit af661dd

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

fish.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ func (cmd *Command) writeFishCompletionTemplate(w io.Writer) error {
3434
// Add global flags
3535
completions := prepareFishFlags(cmd.Name, cmd)
3636

37+
if cmd.ShellComplete != nil {
38+
var completion strings.Builder
39+
fmt.Fprintf(&completion,
40+
"complete -c %s -n '%s' -xa '(%s %s 2>/dev/null)'",
41+
cmd.Name,
42+
fishFlagHelper(cmd.Name, cmd),
43+
cmd.Name,
44+
completionFlag,
45+
)
46+
completions = append(completions, completion.String())
47+
}
48+
3749
// Add commands and their flags
3850
completions = append(
3951
completions,
@@ -72,6 +84,26 @@ func prepareFishCommands(binary string, parent *Command) []string {
7284
}
7385
completions = append(completions, completion.String())
7486
}
87+
88+
if command.ShellComplete != nil {
89+
var completion strings.Builder
90+
var path []string
91+
lineage := command.Lineage()
92+
for i := len(lineage) - 2; i >= 0; i-- {
93+
path = append(path, lineage[i].Name)
94+
}
95+
96+
fmt.Fprintf(&completion,
97+
"complete -c %s -n '%s' -xa '(%s %s %s 2>/dev/null)'",
98+
binary,
99+
fishFlagHelper(binary, command),
100+
binary,
101+
strings.Join(path, " "),
102+
completionFlag,
103+
)
104+
completions = append(completions, completion.String())
105+
}
106+
75107
completions = append(
76108
completions,
77109
prepareFishFlags(binary, command)...,

fish_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package cli
22

33
import (
4+
"context"
5+
"fmt"
46
"testing"
57

68
"github.com/stretchr/testify/assert"
@@ -38,3 +40,23 @@ func TestFishCompletion(t *testing.T) {
3840
require.NoError(t, err)
3941
expectFileContent(t, "testdata/expected-fish-full.fish", res)
4042
}
43+
44+
func TestFishCompletionShellComplete(t *testing.T) {
45+
cmd := buildExtendedTestCommand()
46+
cmd.ShellComplete = func(context.Context, *Command) {}
47+
48+
configCmd := cmd.Command("config")
49+
configCmd.ShellComplete = func(context.Context, *Command) {}
50+
51+
subConfigCmd := configCmd.Command("sub-config")
52+
subConfigCmd.ShellComplete = func(context.Context, *Command) {}
53+
54+
cmd.setupCommandGraph()
55+
56+
res, err := cmd.ToFishCompletion()
57+
require.NoError(t, err)
58+
59+
assert.Contains(t, res, fmt.Sprintf("complete -c greet -n '__fish_greet_no_subcommand' -xa '(greet %s 2>/dev/null)'", completionFlag))
60+
assert.Contains(t, res, fmt.Sprintf("complete -c greet -n '__fish_seen_subcommand_from config c' -xa '(greet config %s 2>/dev/null)'", completionFlag))
61+
assert.Contains(t, res, fmt.Sprintf("complete -c greet -n '__fish_seen_subcommand_from config c; and __fish_seen_subcommand_from sub-config s ss' -xa '(greet config sub-config %s 2>/dev/null)'", completionFlag))
62+
}

0 commit comments

Comments
 (0)