Skip to content

Commit 675ae5f

Browse files
authored
Fish does not accept - or : in vars (#1122)
Fixes #1121. This is for programs that may contain a : or - in their name. Signed-off-by: Marc Khouzam <[email protected]>
1 parent 5d52907 commit 675ae5f

File tree

3 files changed

+88
-46
lines changed

3 files changed

+88
-46
lines changed

custom_completions_test.go

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,39 +1407,6 @@ func TestCompleteCmdInBashScript(t *testing.T) {
14071407
check(t, output, ShellCompNoDescRequestCmd)
14081408
}
14091409

1410-
func TestCompleteNoDesCmdInFishScript(t *testing.T) {
1411-
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
1412-
child := &Command{
1413-
Use: "child",
1414-
ValidArgsFunction: validArgsFunc,
1415-
Run: emptyRun,
1416-
}
1417-
rootCmd.AddCommand(child)
1418-
1419-
buf := new(bytes.Buffer)
1420-
rootCmd.GenFishCompletion(buf, false)
1421-
output := buf.String()
1422-
1423-
check(t, output, ShellCompNoDescRequestCmd)
1424-
}
1425-
1426-
func TestCompleteCmdInFishScript(t *testing.T) {
1427-
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
1428-
child := &Command{
1429-
Use: "child",
1430-
ValidArgsFunction: validArgsFunc,
1431-
Run: emptyRun,
1432-
}
1433-
rootCmd.AddCommand(child)
1434-
1435-
buf := new(bytes.Buffer)
1436-
rootCmd.GenFishCompletion(buf, true)
1437-
output := buf.String()
1438-
1439-
check(t, output, ShellCompRequestCmd)
1440-
checkOmit(t, output, ShellCompNoDescRequestCmd)
1441-
}
1442-
14431410
func TestCompleteNoDesCmdInZshScript(t *testing.T) {
14441411
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
14451412
child := &Command{

fish_completions.go

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@ import (
55
"fmt"
66
"io"
77
"os"
8+
"strings"
89
)
910

1011
func genFishComp(buf *bytes.Buffer, name string, includeDesc bool) {
12+
// Variables should not contain a '-' or ':' character
13+
nameForVar := name
14+
nameForVar = strings.Replace(nameForVar, "-", "_", -1)
15+
nameForVar = strings.Replace(nameForVar, ":", "_", -1)
16+
1117
compCmd := ShellCompRequestCmd
1218
if !includeDesc {
1319
compCmd = ShellCompNoDescRequestCmd
@@ -38,12 +44,12 @@ function __%[1]s_perform_completion
3844
__%[1]s_debug "emptyArg: $emptyArg"
3945
4046
if not type -q "$args[1]"
41-
# This can happen when "complete --do-complete %[1]s" is called when running this script.
47+
# This can happen when "complete --do-complete %[2]s" is called when running this script.
4248
__%[1]s_debug "Cannot find $args[1]. No completions."
4349
return
4450
end
4551
46-
set requestComp "$args[1] %[2]s $args[2..-1] $emptyArg"
52+
set requestComp "$args[1] %[3]s $args[2..-1] $emptyArg"
4753
__%[1]s_debug "Calling $requestComp"
4854
4955
set results (eval $requestComp 2> /dev/null)
@@ -99,11 +105,11 @@ function __%[1]s_prepare_completions
99105
__%[1]s_debug "Completions are: $__%[1]s_comp_results"
100106
__%[1]s_debug "Directive is: $directive"
101107
102-
set shellCompDirectiveError %[3]d
103-
set shellCompDirectiveNoSpace %[4]d
104-
set shellCompDirectiveNoFileComp %[5]d
105-
set shellCompDirectiveFilterFileExt %[6]d
106-
set shellCompDirectiveFilterDirs %[7]d
108+
set shellCompDirectiveError %[4]d
109+
set shellCompDirectiveNoSpace %[5]d
110+
set shellCompDirectiveNoFileComp %[6]d
111+
set shellCompDirectiveFilterFileExt %[7]d
112+
set shellCompDirectiveFilterDirs %[8]d
107113
108114
if test -z "$directive"
109115
set directive 0
@@ -158,24 +164,24 @@ end
158164
# so we can properly delete any completions provided by another script.
159165
# The space after the the program name is essential to trigger completion for the program
160166
# and not completion of the program name itself.
161-
complete --do-complete "%[1]s " &> /dev/null
167+
complete --do-complete "%[2]s " &> /dev/null
162168
163169
# Remove any pre-existing completions for the program since we will be handling all of them.
164-
complete -c %[1]s -e
170+
complete -c %[2]s -e
165171
166172
# The order in which the below two lines are defined is very important so that __%[1]s_prepare_completions
167173
# is called first. It is __%[1]s_prepare_completions that sets up the __%[1]s_comp_do_file_comp variable.
168174
#
169175
# This completion will be run second as complete commands are added FILO.
170176
# It triggers file completion choices when __%[1]s_comp_do_file_comp is set.
171-
complete -c %[1]s -n 'set --query __%[1]s_comp_do_file_comp'
177+
complete -c %[2]s -n 'set --query __%[1]s_comp_do_file_comp'
172178
173179
# This completion will be run first as complete commands are added FILO.
174-
# The call to __%[1]s_prepare_completions will setup both __%[1]s_comp_results abd __%[1]s_comp_do_file_comp.
180+
# The call to __%[1]s_prepare_completions will setup both __%[1]s_comp_results and __%[1]s_comp_do_file_comp.
175181
# It provides the program's completion choices.
176-
complete -c %[1]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
182+
complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
177183
178-
`, name, compCmd,
184+
`, nameForVar, name, compCmd,
179185
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
180186
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
181187
}

fish_completions_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package cobra
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
)
7+
8+
func TestCompleteNoDesCmdInFishScript(t *testing.T) {
9+
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
10+
child := &Command{
11+
Use: "child",
12+
ValidArgsFunction: validArgsFunc,
13+
Run: emptyRun,
14+
}
15+
rootCmd.AddCommand(child)
16+
17+
buf := new(bytes.Buffer)
18+
rootCmd.GenFishCompletion(buf, false)
19+
output := buf.String()
20+
21+
check(t, output, ShellCompNoDescRequestCmd)
22+
}
23+
24+
func TestCompleteCmdInFishScript(t *testing.T) {
25+
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
26+
child := &Command{
27+
Use: "child",
28+
ValidArgsFunction: validArgsFunc,
29+
Run: emptyRun,
30+
}
31+
rootCmd.AddCommand(child)
32+
33+
buf := new(bytes.Buffer)
34+
rootCmd.GenFishCompletion(buf, true)
35+
output := buf.String()
36+
37+
check(t, output, ShellCompRequestCmd)
38+
checkOmit(t, output, ShellCompNoDescRequestCmd)
39+
}
40+
41+
func TestProgWithDash(t *testing.T) {
42+
rootCmd := &Command{Use: "root-dash", Args: NoArgs, Run: emptyRun}
43+
buf := new(bytes.Buffer)
44+
rootCmd.GenFishCompletion(buf, false)
45+
output := buf.String()
46+
47+
// Functions name should have replace the '-'
48+
check(t, output, "__root_dash_perform_completion")
49+
checkOmit(t, output, "__root-dash_perform_completion")
50+
51+
// The command name should not have replaced the '-'
52+
check(t, output, "-c root-dash")
53+
checkOmit(t, output, "-c root_dash")
54+
}
55+
56+
func TestProgWithColon(t *testing.T) {
57+
rootCmd := &Command{Use: "root:colon", Args: NoArgs, Run: emptyRun}
58+
buf := new(bytes.Buffer)
59+
rootCmd.GenFishCompletion(buf, false)
60+
output := buf.String()
61+
62+
// Functions name should have replace the ':'
63+
check(t, output, "__root_colon_perform_completion")
64+
checkOmit(t, output, "__root:colon_perform_completion")
65+
66+
// The command name should not have replaced the ':'
67+
check(t, output, "-c root:colon")
68+
checkOmit(t, output, "-c root_colon")
69+
}

0 commit comments

Comments
 (0)