diff --git a/custom_completions_test.go b/custom_completions_test.go index 8615483929..6087337e7f 100644 --- a/custom_completions_test.go +++ b/custom_completions_test.go @@ -307,39 +307,6 @@ func TestCompleteCmdInBashScript(t *testing.T) { check(t, output, ShellCompNoDescRequestCmd) } -func TestCompleteNoDesCmdInFishScript(t *testing.T) { - rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} - child := &Command{ - Use: "child", - ValidArgsFunction: validArgsFunc, - Run: emptyRun, - } - rootCmd.AddCommand(child) - - buf := new(bytes.Buffer) - rootCmd.GenFishCompletion(buf, false) - output := buf.String() - - check(t, output, ShellCompNoDescRequestCmd) -} - -func TestCompleteCmdInFishScript(t *testing.T) { - rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} - child := &Command{ - Use: "child", - ValidArgsFunction: validArgsFunc, - Run: emptyRun, - } - rootCmd.AddCommand(child) - - buf := new(bytes.Buffer) - rootCmd.GenFishCompletion(buf, true) - output := buf.String() - - check(t, output, ShellCompRequestCmd) - checkOmit(t, output, ShellCompNoDescRequestCmd) -} - func TestFlagCompletionInGo(t *testing.T) { rootCmd := &Command{ Use: "root", diff --git a/fish_completions.go b/fish_completions.go index c83609c83b..a3f6bb4cf7 100644 --- a/fish_completions.go +++ b/fish_completions.go @@ -5,9 +5,15 @@ import ( "fmt" "io" "os" + "strings" ) func genFishComp(buf *bytes.Buffer, name string, includeDesc bool) { + // Variables should not contain a '-' or ':' character + nameForVar := name + nameForVar = strings.Replace(nameForVar, "-", "_", -1) + nameForVar = strings.Replace(nameForVar, ":", "_", -1) + compCmd := ShellCompRequestCmd if !includeDesc { compCmd = ShellCompNoDescRequestCmd @@ -37,7 +43,7 @@ function __%[1]s_perform_completion end __%[1]s_debug "emptyArg: $emptyArg" - set requestComp "$args[1] %[2]s $args[2..-1] $emptyArg" + set requestComp "$args[1] %[3]s $args[2..-1] $emptyArg" __%[1]s_debug "Calling $requestComp" set results (eval $requestComp 2> /dev/null) @@ -96,7 +102,7 @@ function __%[1]s_prepare_completions set directive 0 end - set compErr (math (math --scale 0 $directive / %[3]d) %% 2) + set compErr (math (math --scale 0 $directive / %[4]d) %% 2) if test $compErr -eq 1 __%[1]s_debug "Received error directive: aborting." # Might as well do file completion, in case it helps @@ -104,8 +110,8 @@ function __%[1]s_prepare_completions return 0 end - set nospace (math (math --scale 0 $directive / %[4]d) %% 2) - set nofiles (math (math --scale 0 $directive / %[5]d) %% 2) + set nospace (math (math --scale 0 $directive / %[5]d) %% 2) + set nofiles (math (math --scale 0 $directive / %[6]d) %% 2) __%[1]s_debug "nospace: $nospace, nofiles: $nofiles" @@ -135,21 +141,21 @@ end # Remove any pre-existing completions for the program since we will be handling all of them # TODO this cleanup is not sufficient. Fish completions are only loaded once the user triggers # them, so the below deletion will not work as it is run too early. What else can we do? -complete -c %[1]s -e +complete -c %[2]s -e # The order in which the below two lines are defined is very important so that __%[1]s_prepare_completions # is called first. It is __%[1]s_prepare_completions that sets up the __%[1]s_comp_do_file_comp variable. # # This completion will be run second as complete commands are added FILO. # It triggers file completion choices when __%[1]s_comp_do_file_comp is set. -complete -c %[1]s -n 'set --query __%[1]s_comp_do_file_comp' +complete -c %[2]s -n 'set --query __%[1]s_comp_do_file_comp' # This completion will be run first as complete commands are added FILO. # The call to __%[1]s_prepare_completions will setup both __%[1]s_comp_results abd __%[1]s_comp_do_file_comp. # It provides the program's completion choices. -complete -c %[1]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' +complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' -`, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp)) +`, nameForVar, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp)) } // GenFishCompletion generates fish completion file and writes to the passed writer. diff --git a/fish_completions_test.go b/fish_completions_test.go new file mode 100644 index 0000000000..532b6055a7 --- /dev/null +++ b/fish_completions_test.go @@ -0,0 +1,69 @@ +package cobra + +import ( + "bytes" + "testing" +) + +func TestCompleteNoDesCmdInFishScript(t *testing.T) { + rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} + child := &Command{ + Use: "child", + ValidArgsFunction: validArgsFunc, + Run: emptyRun, + } + rootCmd.AddCommand(child) + + buf := new(bytes.Buffer) + rootCmd.GenFishCompletion(buf, false) + output := buf.String() + + check(t, output, ShellCompNoDescRequestCmd) +} + +func TestCompleteCmdInFishScript(t *testing.T) { + rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} + child := &Command{ + Use: "child", + ValidArgsFunction: validArgsFunc, + Run: emptyRun, + } + rootCmd.AddCommand(child) + + buf := new(bytes.Buffer) + rootCmd.GenFishCompletion(buf, true) + output := buf.String() + + check(t, output, ShellCompRequestCmd) + checkOmit(t, output, ShellCompNoDescRequestCmd) +} + +func TestProgWithDash(t *testing.T) { + rootCmd := &Command{Use: "root-dash", Args: NoArgs, Run: emptyRun} + buf := new(bytes.Buffer) + rootCmd.GenFishCompletion(buf, false) + output := buf.String() + + // Functions name should have replace the '-' + check(t, output, "__root_dash_perform_completion") + checkOmit(t, output, "__root-dash_perform_completion") + + // The command name should not have replaced the '-' + check(t, output, "-c root-dash") + checkOmit(t, output, "-c root_dash") +} + +func TestProgWithColon(t *testing.T) { + rootCmd := &Command{Use: "root:colon", Args: NoArgs, Run: emptyRun} + buf := new(bytes.Buffer) + rootCmd.GenFishCompletion(buf, false) + output := buf.String() + + // Functions name should have replace the ':' + check(t, output, "__root_colon_perform_completion") + checkOmit(t, output, "__root:colon_perform_completion") + + // The command name should not have replaced the ':' + check(t, output, "-c root:colon") + checkOmit(t, output, "-c root_colon") +}