Fish completion using Go completion (#1048)

Signed-off-by: Marc Khouzam <marc.khouzam@montreal.ca>
This commit is contained in:
Marc Khouzam
2020-04-10 15:56:28 -04:00
committed by GitHub
parent 7fead4bf3b
commit a684a6d7f5
7 changed files with 640 additions and 115 deletions

View File

@ -12,7 +12,7 @@ func validArgsFunc(cmd *Command, args []string, toComplete string) ([]string, Sh
}
var completions []string
for _, comp := range []string{"one", "two"} {
for _, comp := range []string{"one\tThe first", "two\tThe second"} {
if strings.HasPrefix(comp, toComplete) {
completions = append(completions, comp)
}
@ -26,7 +26,7 @@ func validArgsFunc2(cmd *Command, args []string, toComplete string) ([]string, S
}
var completions []string
for _, comp := range []string{"three", "four"} {
for _, comp := range []string{"three\tThe third", "four\tThe fourth"} {
if strings.HasPrefix(comp, toComplete) {
completions = append(completions, comp)
}
@ -42,7 +42,7 @@ func TestValidArgsFuncSingleCmd(t *testing.T) {
}
// Test completing an empty string
output, err := executeCommand(rootCmd, ShellCompRequestCmd, "")
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -58,7 +58,7 @@ func TestValidArgsFuncSingleCmd(t *testing.T) {
}
// Check completing with a prefix
output, err = executeCommand(rootCmd, ShellCompRequestCmd, "t")
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "t")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -86,7 +86,7 @@ func TestValidArgsFuncSingleCmdInvalidArg(t *testing.T) {
}
// Check completing with wrong number of args
output, err := executeCommand(rootCmd, ShellCompRequestCmd, "unexpectedArg", "t")
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "unexpectedArg", "t")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -115,7 +115,7 @@ func TestValidArgsFuncChildCmds(t *testing.T) {
rootCmd.AddCommand(child1Cmd, child2Cmd)
// Test completion of first sub-command with empty argument
output, err := executeCommand(rootCmd, ShellCompRequestCmd, "child1", "")
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "child1", "")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -131,7 +131,7 @@ func TestValidArgsFuncChildCmds(t *testing.T) {
}
// Test completion of first sub-command with a prefix to complete
output, err = executeCommand(rootCmd, ShellCompRequestCmd, "child1", "t")
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "child1", "t")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -145,6 +145,339 @@ func TestValidArgsFuncChildCmds(t *testing.T) {
t.Errorf("expected: %q, got: %q", expected, output)
}
// Check completing with wrong number of args
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "child1", "unexpectedArg", "t")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected = strings.Join([]string{
":4",
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
// Test completion of second sub-command with empty argument
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "child2", "")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected = strings.Join([]string{
"three",
"four",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "child2", "t")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected = strings.Join([]string{
"three",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
// Check completing with wrong number of args
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "child2", "unexpectedArg", "t")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected = strings.Join([]string{
":4",
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
}
func TestValidArgsFuncAliases(t *testing.T) {
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
child := &Command{
Use: "child",
Aliases: []string{"son", "daughter"},
ValidArgsFunction: validArgsFunc,
Run: emptyRun,
}
rootCmd.AddCommand(child)
// Test completion of first sub-command with empty argument
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "son", "")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected := strings.Join([]string{
"one",
"two",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
// Test completion of first sub-command with a prefix to complete
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "daughter", "t")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected = strings.Join([]string{
"two",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
// Check completing with wrong number of args
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "son", "unexpectedArg", "t")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected = strings.Join([]string{
":4",
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
}
func TestValidArgsFuncInBashScript(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.GenBashCompletion(buf)
output := buf.String()
check(t, output, "has_completion_function=1")
}
func TestNoValidArgsFuncInBashScript(t *testing.T) {
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
child := &Command{
Use: "child",
Run: emptyRun,
}
rootCmd.AddCommand(child)
buf := new(bytes.Buffer)
rootCmd.GenBashCompletion(buf)
output := buf.String()
checkOmit(t, output, "has_completion_function=1")
}
func TestCompleteCmdInBashScript(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.GenBashCompletion(buf)
output := buf.String()
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",
Run: emptyRun,
}
rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot")
rootCmd.RegisterFlagCompletionFunc("introot", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
completions := []string{}
for _, comp := range []string{"1\tThe first", "2\tThe second", "10\tThe tenth"} {
if strings.HasPrefix(comp, toComplete) {
completions = append(completions, comp)
}
}
return completions, ShellCompDirectiveDefault
})
rootCmd.Flags().String("filename", "", "Enter a filename")
rootCmd.RegisterFlagCompletionFunc("filename", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
completions := []string{}
for _, comp := range []string{"file.yaml\tYAML format", "myfile.json\tJSON format", "file.xml\tXML format"} {
if strings.HasPrefix(comp, toComplete) {
completions = append(completions, comp)
}
}
return completions, ShellCompDirectiveNoSpace | ShellCompDirectiveNoFileComp
})
// Test completing an empty string
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "--introot", "")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected := strings.Join([]string{
"1",
"2",
"10",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
// Check completing with a prefix
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "--introot", "1")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected = strings.Join([]string{
"1",
"10",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
// Test completing an empty string
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "--filename", "")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected = strings.Join([]string{
"file.yaml",
"myfile.json",
"file.xml",
":6",
"Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
// Check completing with a prefix
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "--filename", "f")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected = strings.Join([]string{
"file.yaml",
"file.xml",
":6",
"Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
}
func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) {
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
child1Cmd := &Command{
Use: "child1",
ValidArgsFunction: validArgsFunc,
Run: emptyRun,
}
child2Cmd := &Command{
Use: "child2",
ValidArgsFunction: validArgsFunc2,
Run: emptyRun,
}
rootCmd.AddCommand(child1Cmd, child2Cmd)
// Test completion of first sub-command with empty argument
output, err := executeCommand(rootCmd, ShellCompRequestCmd, "child1", "")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected := strings.Join([]string{
"one\tThe first",
"two\tThe second",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
// Test completion of first sub-command with a prefix to complete
output, err = executeCommand(rootCmd, ShellCompRequestCmd, "child1", "t")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected = strings.Join([]string{
"two\tThe second",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
// Check completing with wrong number of args
output, err = executeCommand(rootCmd, ShellCompRequestCmd, "child1", "unexpectedArg", "t")
if err != nil {
@ -166,8 +499,8 @@ func TestValidArgsFuncChildCmds(t *testing.T) {
}
expected = strings.Join([]string{
"three",
"four",
"three\tThe third",
"four\tThe fourth",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
@ -181,7 +514,7 @@ func TestValidArgsFuncChildCmds(t *testing.T) {
}
expected = strings.Join([]string{
"three",
"three\tThe third",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
@ -204,94 +537,7 @@ func TestValidArgsFuncChildCmds(t *testing.T) {
}
}
func TestValidArgsFuncAliases(t *testing.T) {
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
child := &Command{
Use: "child",
Aliases: []string{"son", "daughter"},
ValidArgsFunction: validArgsFunc,
Run: emptyRun,
}
rootCmd.AddCommand(child)
// Test completion of first sub-command with empty argument
output, err := executeCommand(rootCmd, ShellCompRequestCmd, "son", "")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected := strings.Join([]string{
"one",
"two",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
// Test completion of first sub-command with a prefix to complete
output, err = executeCommand(rootCmd, ShellCompRequestCmd, "daughter", "t")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected = strings.Join([]string{
"two",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
// Check completing with wrong number of args
output, err = executeCommand(rootCmd, ShellCompRequestCmd, "son", "unexpectedArg", "t")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expected = strings.Join([]string{
":4",
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
if output != expected {
t.Errorf("expected: %q, got: %q", expected, output)
}
}
func TestValidArgsFuncInScript(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.GenBashCompletion(buf)
output := buf.String()
check(t, output, "has_completion_function=1")
}
func TestNoValidArgsFuncInScript(t *testing.T) {
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
child := &Command{
Use: "child",
Run: emptyRun,
}
rootCmd.AddCommand(child)
buf := new(bytes.Buffer)
rootCmd.GenBashCompletion(buf)
output := buf.String()
checkOmit(t, output, "has_completion_function=1")
}
func TestFlagCompletionInGo(t *testing.T) {
func TestFlagCompletionInGoWithDesc(t *testing.T) {
rootCmd := &Command{
Use: "root",
Run: emptyRun,
@ -299,7 +545,7 @@ func TestFlagCompletionInGo(t *testing.T) {
rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot")
rootCmd.RegisterFlagCompletionFunc("introot", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
completions := []string{}
for _, comp := range []string{"1", "2", "10"} {
for _, comp := range []string{"1\tThe first", "2\tThe second", "10\tThe tenth"} {
if strings.HasPrefix(comp, toComplete) {
completions = append(completions, comp)
}
@ -309,7 +555,7 @@ func TestFlagCompletionInGo(t *testing.T) {
rootCmd.Flags().String("filename", "", "Enter a filename")
rootCmd.RegisterFlagCompletionFunc("filename", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
completions := []string{}
for _, comp := range []string{"file.yaml", "myfile.json", "file.xml"} {
for _, comp := range []string{"file.yaml\tYAML format", "myfile.json\tJSON format", "file.xml\tXML format"} {
if strings.HasPrefix(comp, toComplete) {
completions = append(completions, comp)
}
@ -324,9 +570,9 @@ func TestFlagCompletionInGo(t *testing.T) {
}
expected := strings.Join([]string{
"1",
"2",
"10",
"1\tThe first",
"2\tThe second",
"10\tThe tenth",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
@ -341,8 +587,8 @@ func TestFlagCompletionInGo(t *testing.T) {
}
expected = strings.Join([]string{
"1",
"10",
"1\tThe first",
"10\tThe tenth",
":0",
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
@ -357,9 +603,9 @@ func TestFlagCompletionInGo(t *testing.T) {
}
expected = strings.Join([]string{
"file.yaml",
"myfile.json",
"file.xml",
"file.yaml\tYAML format",
"myfile.json\tJSON format",
"file.xml\tXML format",
":6",
"Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n")
@ -374,8 +620,8 @@ func TestFlagCompletionInGo(t *testing.T) {
}
expected = strings.Join([]string{
"file.yaml",
"file.xml",
"file.yaml\tYAML format",
"file.xml\tXML format",
":6",
"Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n")