Skip to content

Commit

Permalink
Fish does not accept - or : in vars (spf13#1122)
Browse files Browse the repository at this point in the history
Fixes spf13#1121.
This is for programs that may contain a : or - in their name.

Signed-off-by: Marc Khouzam <marc.khouzam@montreal.ca>
  • Loading branch information
marckhouzam committed Jul 10, 2020
1 parent 5d52907 commit 675ae5f
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 46 deletions.
33 changes: 0 additions & 33 deletions custom_completions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1407,39 +1407,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 TestCompleteNoDesCmdInZshScript(t *testing.T) {
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
child := &Command{
Expand Down
32 changes: 19 additions & 13 deletions fish_completions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -38,12 +44,12 @@ function __%[1]s_perform_completion
__%[1]s_debug "emptyArg: $emptyArg"
if not type -q "$args[1]"
# This can happen when "complete --do-complete %[1]s" is called when running this script.
# This can happen when "complete --do-complete %[2]s" is called when running this script.
__%[1]s_debug "Cannot find $args[1]. No completions."
return
end
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)
Expand Down Expand Up @@ -99,11 +105,11 @@ function __%[1]s_prepare_completions
__%[1]s_debug "Completions are: $__%[1]s_comp_results"
__%[1]s_debug "Directive is: $directive"
set shellCompDirectiveError %[3]d
set shellCompDirectiveNoSpace %[4]d
set shellCompDirectiveNoFileComp %[5]d
set shellCompDirectiveFilterFileExt %[6]d
set shellCompDirectiveFilterDirs %[7]d
set shellCompDirectiveError %[4]d
set shellCompDirectiveNoSpace %[5]d
set shellCompDirectiveNoFileComp %[6]d
set shellCompDirectiveFilterFileExt %[7]d
set shellCompDirectiveFilterDirs %[8]d
if test -z "$directive"
set directive 0
Expand Down Expand Up @@ -158,24 +164,24 @@ end
# so we can properly delete any completions provided by another script.
# The space after the the program name is essential to trigger completion for the program
# and not completion of the program name itself.
complete --do-complete "%[1]s " &> /dev/null
complete --do-complete "%[2]s " &> /dev/null
# Remove any pre-existing completions for the program since we will be handling all of them.
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.
# The call to __%[1]s_prepare_completions will setup both __%[1]s_comp_results and __%[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,
`, nameForVar, name, compCmd,
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
}
Expand Down
69 changes: 69 additions & 0 deletions fish_completions_test.go
Original file line number Diff line number Diff line change
@@ -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")
}

0 comments on commit 675ae5f

Please sign in to comment.