Skip to content

Commit 42528f4

Browse files
authored
feat(cmd): add fish completion (#2517)
Add fish completion for the CLI
1 parent 84175ad commit 42528f4

File tree

5 files changed

+57
-14
lines changed

5 files changed

+57
-14
lines changed

go.sum

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,6 @@ github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2
174174
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
175175
github.com/briandowns/spinner v1.15.0 h1:L0jR0MYN7OAeMwpTzDZWIeqyDLXtTeJFxqoq+sL0VQM=
176176
github.com/briandowns/spinner v1.15.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ=
177-
github.com/briandowns/spinner v1.16.0 h1:DFmp6hEaIx2QXXuqSJmtfSBSAjRmpGiKG6ip2Wm/yOs=
178-
github.com/briandowns/spinner v1.16.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ=
179177
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
180178
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
181179
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
@@ -1327,7 +1325,6 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
13271325
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
13281326
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
13291327
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
1330-
golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA=
13311328
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
13321329
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
13331330
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

internal/pkg/cli/completion.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,28 @@ import (
1717
type shellCompleter interface {
1818
GenBashCompletion(w io.Writer) error
1919
GenZshCompletion(w io.Writer) error
20+
GenFishCompletion(w io.Writer, includeDesc bool) error
2021
}
2122

2223
type completionOpts struct {
23-
Shell string // must be "bash" or "zsh"
24+
Shell string // must be "bash" or "zsh" or "fish"
2425

2526
w io.Writer
2627
completer shellCompleter
2728
}
2829

29-
// Validate returns an error if the shell is not "bash" or "zsh".
30+
// Validate returns an error if the shell is not "bash" or "zsh" or "fish".
3031
func (opts *completionOpts) Validate() error {
3132
if opts.Shell == "bash" {
3233
return nil
3334
}
3435
if opts.Shell == "zsh" {
3536
return nil
3637
}
37-
return errors.New("shell must be bash or zsh")
38+
if opts.Shell == "fish" {
39+
return nil
40+
}
41+
return errors.New("shell must be bash, zsh or fish")
3842
}
3943

4044
// Execute writes the completion code to the writer.
@@ -43,16 +47,19 @@ func (opts *completionOpts) Execute() error {
4347
if opts.Shell == "bash" {
4448
return opts.completer.GenBashCompletion(opts.w)
4549
}
46-
return opts.completer.GenZshCompletion(opts.w)
50+
if opts.Shell == "zsh" {
51+
return opts.completer.GenZshCompletion(opts.w)
52+
}
53+
return opts.completer.GenFishCompletion(opts.w, true)
4754
}
4855

49-
// BuildCompletionCmd returns the command to output shell completion code for the specified shell (bash or zsh).
56+
// BuildCompletionCmd returns the command to output shell completion code for the specified shell (bash or zsh or fish).
5057
func BuildCompletionCmd(rootCmd *cobra.Command) *cobra.Command {
5158
opts := &completionOpts{}
5259
cmd := &cobra.Command{
5360
Use: "completion [shell]",
5461
Short: "Output shell completion code.",
55-
Long: `Output shell completion code for bash or zsh.
62+
Long: `Output shell completion code for bash, zsh or fish.
5663
The code must be evaluated to provide interactive completion of commands.`,
5764
Example: `
5865
Install zsh completion
@@ -67,10 +74,16 @@ The code must be evaluated to provide interactive completion of commands.`,
6774
Install bash completion on linux
6875
/code $ source <(copilot completion bash)
6976
/code $ copilot completion bash > copilot.sh
70-
/code $ sudo mv copilot.sh /etc/bash_completion.d/copilot`,
77+
/code $ sudo mv copilot.sh /etc/bash_completion.d/copilot
78+
79+
Install fish completion
80+
/code$ copilot completion fish | source
81+
82+
To load completions for each session, execute once:
83+
/code$ copilot completion fish > ~/.config/fish/completions/copilot.fish`,
7184
Args: func(cmd *cobra.Command, args []string) error {
7285
if len(args) != 1 {
73-
return errors.New("requires a single shell argument (bash or zsh)")
86+
return errors.New("requires a single shell argument (bash, zsh or fish)")
7487
}
7588
return nil
7689
},

internal/pkg/cli/completion_test.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,13 @@ func TestCompletionOpts_Validate(t *testing.T) {
2525
inputShell: "bash",
2626
wantedError: nil,
2727
},
28+
"fish": {
29+
inputShell: "fish",
30+
wantedError: nil,
31+
},
2832
"invalid shell": {
2933
inputShell: "chicken",
30-
wantedError: errors.New("shell must be bash or zsh"),
34+
wantedError: errors.New("shell must be bash, zsh or fish"),
3135
},
3236
}
3337

@@ -63,13 +67,23 @@ func TestCompletionOpts_Execute(t *testing.T) {
6367
mocking: func(mock *mocks.MockshellCompleter) {
6468
mock.EXPECT().GenBashCompletion(gomock.Any()).Times(1)
6569
mock.EXPECT().GenZshCompletion(gomock.Any()).Times(0)
70+
mock.EXPECT().GenFishCompletion(gomock.Any(), gomock.Any()).Times(0)
6671
},
6772
},
6873
"zsh": {
6974
inputShell: "zsh",
7075
mocking: func(mock *mocks.MockshellCompleter) {
7176
mock.EXPECT().GenBashCompletion(gomock.Any()).Times(0)
7277
mock.EXPECT().GenZshCompletion(gomock.Any()).Times(1)
78+
mock.EXPECT().GenFishCompletion(gomock.Any(), gomock.Any()).Times(0)
79+
},
80+
},
81+
"fish": {
82+
inputShell: "fish",
83+
mocking: func(mock *mocks.MockshellCompleter) {
84+
mock.EXPECT().GenBashCompletion(gomock.Any()).Times(0)
85+
mock.EXPECT().GenZshCompletion(gomock.Any()).Times(0)
86+
mock.EXPECT().GenFishCompletion(gomock.Any(), gomock.Any()).Times(1)
7387
},
7488
},
7589
}

internal/pkg/cli/mocks/mock_completion.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

site/content/docs/commands/completion.en.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ $ copilot completion [shell] [flags]
44
```
55

66
## What does it do?
7-
`copilot completion` prints shell completion code for bash or zsh. The code must be evaluated to provide interactive completion of commands.
7+
`copilot completion` prints shell completion code for bash, zsh or fish. The code must be evaluated to provide interactive completion of commands.
88

99
See the help menu for instructions on how to setup auto-completion for your respective shell.
1010

@@ -30,4 +30,9 @@ Install bash completion on linux
3030
$ source <(copilot completion bash)
3131
$ copilot completion bash > copilot.sh
3232
$ sudo mv copilot.sh /etc/bash_completion.d/copilot
33-
```
33+
```
34+
Install fish completion on linux
35+
```bash
36+
$ source <(copilot completion fish)
37+
$ copilot completion fish > ~/.config/fish/completions/copilot.fish
38+
```

0 commit comments

Comments
 (0)