From a1431b2c574c3e4aeaa54d03888722cb1e045a23 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Fri, 11 Nov 2022 18:05:24 -0800 Subject: [PATCH 01/35] 'Completions for nushell' --- nushell_completions.go | 124 +++++++++++++++++++++++++ nushell_completions.md | 4 + nushell_completions_test.go | 141 +++++++++++++++++++++++++++++ site/content/completions/_index.md | 14 ++- 4 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 nushell_completions.go create mode 100644 nushell_completions.md create mode 100644 nushell_completions_test.go diff --git a/nushell_completions.go b/nushell_completions.go new file mode 100644 index 00000000..6b944bd9 --- /dev/null +++ b/nushell_completions.go @@ -0,0 +1,124 @@ +// Copyright 2013-2022 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cobra + +import ( + "bytes" + "fmt" + "io" + "os" + "regexp" + "strings" + + "github.com/spf13/pflag" +) + +var carrageReturnRE = regexp.MustCompile(`\r?\n`) + +func descriptionString(desc string) string { + // Remove any carriage returns, this will break the extern + desc = carrageReturnRE.ReplaceAllString(desc, " ") + + // Lets keep the descriptions short-ish + if len(desc) > 100 { + desc = desc[0:97] + "..." + } + return desc +} + +func GenNushellComp(c *Command, buf io.StringWriter, nameBuilder *strings.Builder, isRoot bool, includeDesc bool) { + processFlags := func(flags *pflag.FlagSet) { + flags.VisitAll(func(f *pflag.Flag) { + WriteStringAndCheck(buf, fmt.Sprintf("\t--%[1]s", f.Name)) + + if f.Shorthand != "" { + WriteStringAndCheck(buf, fmt.Sprintf("(-%[1]s)", f.Shorthand)) + } + + if includeDesc && f.Usage != "" { + desc := descriptionString(f.Usage) + WriteStringAndCheck(buf, fmt.Sprintf("\t# %[1]s", desc)) + } + + WriteStringAndCheck(buf, "\n") + + }) + } + + cmdName := c.Name() + // commands after root name will be like "git pull" + if !isRoot { + nameBuilder.WriteString(" ") + } + nameBuilder.WriteString(cmdName) + + // only create an extern block if there is something to put in it + if len(c.ValidArgs) > 0 || c.HasAvailableFlags() { + builderString := nameBuilder.String() + + // ensure there is a space before any previous content + // otherwise it will break descriptions + WriteStringAndCheck(buf, "\n") + + funcName := builderString + if !isRoot { + funcName = fmt.Sprintf("\"%[1]s\"", builderString) + } + + if includeDesc && c.Short != "" { + desc := descriptionString(c.Short) + WriteStringAndCheck(buf, fmt.Sprintf("# %[1]s\n", desc)) + } + WriteStringAndCheck(buf, fmt.Sprintf("export extern %[1]s [\n", funcName)) + + // valid args + for _, arg := range c.ValidArgs { + WriteStringAndCheck(buf, fmt.Sprintf("\t%[1]s?\n", arg)) + } + + processFlags(c.InheritedFlags()) + processFlags(c.LocalFlags()) + + // End extern statement + WriteStringAndCheck(buf, "]\n") + } + + // process sub commands + for _, child := range c.Commands() { + childBuilder := strings.Builder{} + childBuilder.WriteString(nameBuilder.String()) + GenNushellComp(child, buf, &childBuilder, false, includeDesc) + } + +} + +func (c *Command) GenNushellCompletion(w io.Writer, includeDesc bool) error { + var nameBuilder strings.Builder + buf := new(bytes.Buffer) + GenNushellComp(c, buf, &nameBuilder, true, includeDesc) + + _, err := buf.WriteTo(w) + return err +} + +func (c *Command) GenNushellCompletionFile(filename string, includeDesc bool) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() + + return c.GenNushellCompletion(outFile, includeDesc) +} diff --git a/nushell_completions.md b/nushell_completions.md new file mode 100644 index 00000000..e0e94eb1 --- /dev/null +++ b/nushell_completions.md @@ -0,0 +1,4 @@ +## Generating Nushell Completions For Your cobra.Command + +Please refer to [Shell Completions](shell_completions.md) for details. + diff --git a/nushell_completions_test.go b/nushell_completions_test.go new file mode 100644 index 00000000..77bb00d5 --- /dev/null +++ b/nushell_completions_test.go @@ -0,0 +1,141 @@ +// Copyright 2013-2022 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cobra + +import ( + "bytes" + "log" + "os" + "testing" +) + +func TestGenNushellCompletion(t *testing.T) { + rootCmd := &Command{ + Use: "kubectl", + Run: emptyRun, + } + rootCmd.PersistentFlags().String("server", "s", "The address and port of the Kubernetes API server") + rootCmd.PersistentFlags().BoolP("skip-headers", "", false, "The address and port of the Kubernetes API serverIf true, avoid header prefixes in the log messages") + + getCmd := &Command{ + Use: "get", + Short: "Display one or many resources", + ArgAliases: []string{"pods", "nodes", "services", "replicationcontrollers", "po", "no", "svc", "rc"}, + ValidArgs: []string{"pod", "node", "service", "replicationcontroller"}, + Run: emptyRun, + } + + rootCmd.AddCommand(getCmd) + + buf := new(bytes.Buffer) + assertNoErr(t, rootCmd.GenNushellCompletion(buf, true)) + output := buf.String() + + // root command has no local options, it should not be displayed + checkOmit(t, output, "export extern kubectl") + + check(t, output, "export extern \"kubectl get\"") + check(t, output, "--server") + check(t, output, "--skip-headers") + check(t, output, "pod?") + check(t, output, "node?") + check(t, output, "service?") + check(t, output, "replicationcontroller?") + + check(t, output, "The address and port of the Kubernetes API serverIf true, avoid header prefixes in the log messages") + check(t, output, "The address and port of the Kubernetes API server") + check(t, output, "Display one or many resources") +} + +func TestGenNushellCompletionWithoutDesc(t *testing.T) { + rootCmd := &Command{ + Use: "kubectl", + Run: emptyRun, + } + rootCmd.PersistentFlags().String("server", "s", "The address and port of the Kubernetes API server") + rootCmd.PersistentFlags().BoolP("skip-headers", "", false, "The address and port of the Kubernetes API serverIf true, avoid header prefixes in the log messages") + + getCmd := &Command{ + Use: "get", + Short: "Display one or many resources", + ArgAliases: []string{"pods", "nodes", "services", "replicationcontrollers", "po", "no", "svc", "rc"}, + ValidArgs: []string{"pod", "node", "service", "replicationcontroller"}, + Run: emptyRun, + } + + rootCmd.AddCommand(getCmd) + + buf := new(bytes.Buffer) + assertNoErr(t, rootCmd.GenNushellCompletion(buf, false)) + output := buf.String() + + checkOmit(t, output, "The address and port of the Kubernetes API server") + checkOmit(t, output, "The address and port of the Kubernetes API serverIf true, avoid header prefixes in the log messages") + checkOmit(t, output, "Display one or many resources") +} + +func TestGenNushellCompletionFile(t *testing.T) { + err := os.Mkdir("./tmp", 0755) + if err != nil { + log.Fatal(err.Error()) + } + + defer os.RemoveAll("./tmp") + + rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} + child := &Command{ + Use: "child", + ValidArgsFunction: validArgsFunc, + Run: emptyRun, + } + rootCmd.AddCommand(child) + + assertNoErr(t, rootCmd.GenNushellCompletionFile("./tmp/test", false)) +} + +func TestFailGenNushellCompletionFile(t *testing.T) { + err := os.Mkdir("./tmp", 0755) + if err != nil { + log.Fatal(err.Error()) + } + + defer os.RemoveAll("./tmp") + + f, _ := os.OpenFile("./tmp/test", os.O_CREATE, 0400) + defer f.Close() + + rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} + child := &Command{ + Use: "child", + ValidArgsFunction: validArgsFunc, + Run: emptyRun, + } + rootCmd.AddCommand(child) + + got := rootCmd.GenNushellCompletionFile("./tmp/test", false) + if got == nil { + t.Error("should raise permission denied error") + } + + if os.Getenv("MSYSTEM") == "MINGW64" { + if got.Error() != "open ./tmp/test: Access is denied." { + t.Errorf("got: %s, want: %s", got.Error(), "open ./tmp/test: Access is denied.") + } + } else { + if got.Error() != "open ./tmp/test: permission denied" { + t.Errorf("got: %s, want: %s", got.Error(), "open ./tmp/test: permission denied") + } + } +} diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md index 02257ade..9cbde8e1 100644 --- a/site/content/completions/_index.md +++ b/site/content/completions/_index.md @@ -6,6 +6,7 @@ The currently supported shells are: - Zsh - fish - PowerShell +- Nushell Cobra will automatically provide your program with a fully functional `completion` command, similarly to how it provides the `help` command. @@ -68,9 +69,18 @@ PowerShell: # To load completions for every new session, run: PS> %[1]s completion powershell > %[1]s.ps1 # and source this file from your PowerShell profile. + +Nushell: + + # To generate completions (replace YOUR_COMPLETION_DIR with actual path to save) + > %[1]s completion nushell | save /YOUR_COMPLETION_DIR/%[1]s-completions.nu + + # To load completions for each session, execute once (replace YOUR_COMPLETION_DIR with actual path): + > echo "use /YOUR_COMPLETION_DIR/%[1]s-completions.nu *" | save --append $nu.config-path + `,cmd.Root().Name()), DisableFlagsInUseLine: true, - ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, + ValidArgs: []string{"bash", "zsh", "fish", "powershell", "nushell"}, Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), Run: func(cmd *cobra.Command, args []string) { switch args[0] { @@ -82,6 +92,8 @@ PowerShell: cmd.Root().GenFishCompletion(os.Stdout, true) case "powershell": cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout) + case "nushell": + cmd.Root().GenNushellCompletion(os.Stdout, true) } }, } From 594faef23fa9b46685a50570bfd15c2175d440f1 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sat, 26 Nov 2022 14:39:29 -0800 Subject: [PATCH 02/35] Changed the nushell completion implementation to be a nushell external completer --- nushell_completions.go | 128 +++++++++-------------------- nushell_completions_test.go | 61 ++------------ site/content/completions/_index.md | 15 +++- 3 files changed, 58 insertions(+), 146 deletions(-) diff --git a/nushell_completions.go b/nushell_completions.go index 6b944bd9..4363946f 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -16,109 +16,59 @@ package cobra import ( "bytes" - "fmt" "io" "os" - "regexp" - "strings" - - "github.com/spf13/pflag" ) -var carrageReturnRE = regexp.MustCompile(`\r?\n`) - -func descriptionString(desc string) string { - // Remove any carriage returns, this will break the extern - desc = carrageReturnRE.ReplaceAllString(desc, " ") - - // Lets keep the descriptions short-ish - if len(desc) > 100 { - desc = desc[0:97] + "..." - } - return desc -} - -func GenNushellComp(c *Command, buf io.StringWriter, nameBuilder *strings.Builder, isRoot bool, includeDesc bool) { - processFlags := func(flags *pflag.FlagSet) { - flags.VisitAll(func(f *pflag.Flag) { - WriteStringAndCheck(buf, fmt.Sprintf("\t--%[1]s", f.Name)) - - if f.Shorthand != "" { - WriteStringAndCheck(buf, fmt.Sprintf("(-%[1]s)", f.Shorthand)) - } - - if includeDesc && f.Usage != "" { - desc := descriptionString(f.Usage) - WriteStringAndCheck(buf, fmt.Sprintf("\t# %[1]s", desc)) - } - - WriteStringAndCheck(buf, "\n") - - }) - } - - cmdName := c.Name() - // commands after root name will be like "git pull" - if !isRoot { - nameBuilder.WriteString(" ") - } - nameBuilder.WriteString(cmdName) - - // only create an extern block if there is something to put in it - if len(c.ValidArgs) > 0 || c.HasAvailableFlags() { - builderString := nameBuilder.String() - - // ensure there is a space before any previous content - // otherwise it will break descriptions - WriteStringAndCheck(buf, "\n") - - funcName := builderString - if !isRoot { - funcName = fmt.Sprintf("\"%[1]s\"", builderString) - } - - if includeDesc && c.Short != "" { - desc := descriptionString(c.Short) - WriteStringAndCheck(buf, fmt.Sprintf("# %[1]s\n", desc)) - } - WriteStringAndCheck(buf, fmt.Sprintf("export extern %[1]s [\n", funcName)) - - // valid args - for _, arg := range c.ValidArgs { - WriteStringAndCheck(buf, fmt.Sprintf("\t%[1]s?\n", arg)) - } - - processFlags(c.InheritedFlags()) - processFlags(c.LocalFlags()) - - // End extern statement - WriteStringAndCheck(buf, "]\n") - } - - // process sub commands - for _, child := range c.Commands() { - childBuilder := strings.Builder{} - childBuilder.WriteString(nameBuilder.String()) - GenNushellComp(child, buf, &childBuilder, false, includeDesc) - } - -} - -func (c *Command) GenNushellCompletion(w io.Writer, includeDesc bool) error { - var nameBuilder strings.Builder +func (c *Command) GenNushellCompletion(w io.Writer) error { buf := new(bytes.Buffer) - GenNushellComp(c, buf, &nameBuilder, true, includeDesc) + WriteStringAndCheck(buf, ` +# An external configurator that works with any cobra based +# command line application (e.g. kubectl, minikube) +let cobra_configurator = {|spans| + + let cmd = $spans.0 + + # skip the first entry in the span (the command) and join the rest of the span to create __complete args + let cmd_args = ($spans | skip 1 | str join ' ') + + # If the last span entry was empty add "" to the end of the command args + let cmd_args = if ($spans | last | str trim | is-empty) { + $'($cmd_args) ""' + } else { + $cmd_args + } + + # The full command to be executed + let full_cmd = $'($cmd) __complete ($cmd_args)' + + # Since nushell doesn't have anything like eval, execute in a subshell + let result = (do -i { nu -c $"'($full_cmd)'" } | complete) + + # Create a record with all completion related info. + # directive and directive_str are for posterity + let stdout_lines = ($result.stdout | lines) + let $completions = ($stdout_lines | drop | parse -r '([\w\-\.:\+]*)\t?(.*)' | rename value description) + + let result = ({ + completions: $completions + directive_str: ($result.stderr) + directive: ($stdout_lines | last) + }) + + $result.completions +}`) _, err := buf.WriteTo(w) return err } -func (c *Command) GenNushellCompletionFile(filename string, includeDesc bool) error { +func (c *Command) GenNushellCompletionFile(filename string) error { outFile, err := os.Create(filename) if err != nil { return err } defer outFile.Close() - return c.GenNushellCompletion(outFile, includeDesc) + return c.GenNushellCompletion(outFile) } diff --git a/nushell_completions_test.go b/nushell_completions_test.go index 77bb00d5..3e3c36de 100644 --- a/nushell_completions_test.go +++ b/nushell_completions_test.go @@ -22,13 +22,9 @@ import ( ) func TestGenNushellCompletion(t *testing.T) { - rootCmd := &Command{ - Use: "kubectl", - Run: emptyRun, - } + rootCmd := &Command{Use: "kubectl", Run: emptyRun} rootCmd.PersistentFlags().String("server", "s", "The address and port of the Kubernetes API server") rootCmd.PersistentFlags().BoolP("skip-headers", "", false, "The address and port of the Kubernetes API serverIf true, avoid header prefixes in the log messages") - getCmd := &Command{ Use: "get", Short: "Display one or many resources", @@ -36,58 +32,17 @@ func TestGenNushellCompletion(t *testing.T) { ValidArgs: []string{"pod", "node", "service", "replicationcontroller"}, Run: emptyRun, } - rootCmd.AddCommand(getCmd) buf := new(bytes.Buffer) - assertNoErr(t, rootCmd.GenNushellCompletion(buf, true)) + assertNoErr(t, rootCmd.GenNushellCompletion(buf)) output := buf.String() - // root command has no local options, it should not be displayed - checkOmit(t, output, "export extern kubectl") - - check(t, output, "export extern \"kubectl get\"") - check(t, output, "--server") - check(t, output, "--skip-headers") - check(t, output, "pod?") - check(t, output, "node?") - check(t, output, "service?") - check(t, output, "replicationcontroller?") - - check(t, output, "The address and port of the Kubernetes API serverIf true, avoid header prefixes in the log messages") - check(t, output, "The address and port of the Kubernetes API server") - check(t, output, "Display one or many resources") -} - -func TestGenNushellCompletionWithoutDesc(t *testing.T) { - rootCmd := &Command{ - Use: "kubectl", - Run: emptyRun, - } - rootCmd.PersistentFlags().String("server", "s", "The address and port of the Kubernetes API server") - rootCmd.PersistentFlags().BoolP("skip-headers", "", false, "The address and port of the Kubernetes API serverIf true, avoid header prefixes in the log messages") - - getCmd := &Command{ - Use: "get", - Short: "Display one or many resources", - ArgAliases: []string{"pods", "nodes", "services", "replicationcontrollers", "po", "no", "svc", "rc"}, - ValidArgs: []string{"pod", "node", "service", "replicationcontroller"}, - Run: emptyRun, - } - - rootCmd.AddCommand(getCmd) - - buf := new(bytes.Buffer) - assertNoErr(t, rootCmd.GenNushellCompletion(buf, false)) - output := buf.String() - - checkOmit(t, output, "The address and port of the Kubernetes API server") - checkOmit(t, output, "The address and port of the Kubernetes API serverIf true, avoid header prefixes in the log messages") - checkOmit(t, output, "Display one or many resources") + check(t, output, "let full_cmd = $'($cmd) __complete ($cmd_args)'") } func TestGenNushellCompletionFile(t *testing.T) { - err := os.Mkdir("./tmp", 0755) + err := os.Mkdir("./tmp", 0o755) if err != nil { log.Fatal(err.Error()) } @@ -102,18 +57,18 @@ func TestGenNushellCompletionFile(t *testing.T) { } rootCmd.AddCommand(child) - assertNoErr(t, rootCmd.GenNushellCompletionFile("./tmp/test", false)) + assertNoErr(t, rootCmd.GenNushellCompletionFile("./tmp/test")) } func TestFailGenNushellCompletionFile(t *testing.T) { - err := os.Mkdir("./tmp", 0755) + err := os.Mkdir("./tmp", 0o755) if err != nil { log.Fatal(err.Error()) } defer os.RemoveAll("./tmp") - f, _ := os.OpenFile("./tmp/test", os.O_CREATE, 0400) + f, _ := os.OpenFile("./tmp/test", os.O_CREATE, 0o400) defer f.Close() rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} @@ -124,7 +79,7 @@ func TestFailGenNushellCompletionFile(t *testing.T) { } rootCmd.AddCommand(child) - got := rootCmd.GenNushellCompletionFile("./tmp/test", false) + got := rootCmd.GenNushellCompletionFile("./tmp/test") if got == nil { t.Error("should raise permission denied error") } diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md index 9cbde8e1..b8a56d4f 100644 --- a/site/content/completions/_index.md +++ b/site/content/completions/_index.md @@ -72,11 +72,18 @@ PowerShell: Nushell: - # To generate completions (replace YOUR_COMPLETION_DIR with actual path to save) - > %[1]s completion nushell | save /YOUR_COMPLETION_DIR/%[1]s-completions.nu + # 1. Copy the output of the command below: + > %[1]s completion nushell - # To load completions for each session, execute once (replace YOUR_COMPLETION_DIR with actual path): - > echo "use /YOUR_COMPLETION_DIR/%[1]s-completions.nu *" | save --append $nu.config-path + # 2. Edit the nushell config file: + > config nu + + # 3. Paste above the "let-env config" line. + + # 4. Change the config block's external_completer line to be + external_completer: $cobra_completer + + # 5. You will need to start a new shell for this setup to take effect. `,cmd.Root().Name()), DisableFlagsInUseLine: true, From 2f276e301446093e63850fbfef3c81d8f9ed7461 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sun, 27 Nov 2022 13:46:13 -0800 Subject: [PATCH 03/35] Incorporating pull request feedback. - Renamed completer to be cobra_completer to match docs - Added whitespace after each completion - Implemented ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp - Disabled active help as it isn't supported by nushell - Added nushell to the default completion command --- completions.go | 39 +++- completions_test.go | 425 ++++++++++++++++++++++++------------ nushell_completions.go | 51 +++-- nushell_completions_test.go | 2 +- 4 files changed, 358 insertions(+), 159 deletions(-) diff --git a/completions.go b/completions.go index 8fccdaf2..fee40e11 100644 --- a/completions.go +++ b/completions.go @@ -836,14 +836,47 @@ to your powershell profile. return cmd.Root().GenPowerShellCompletion(out) } return cmd.Root().GenPowerShellCompletionWithDesc(out) - }, } if haveNoDescFlag { powershell.Flags().BoolVar(&noDesc, compCmdNoDescFlagName, compCmdNoDescFlagDefault, compCmdNoDescFlagDesc) } - completionCmd.AddCommand(bash, zsh, fish, powershell) + nushell := &Command{ + Use: "nushell", + Short: fmt.Sprintf(shortDesc, "nushell"), + Long: fmt.Sprintf(`Generate the autocompletion script for nushell. + +To configure completions: + + # 1. Copy the output of the command below: + > %[1]s completion nushell + + # 2. Edit the nushell config file: + > config nu + + # 3. Paste above the "let-env config" line. + + # 4. Change the config block's external_completer line to be + external_completer: $cobra_completer + + # 5. You will need to start a new shell for this setup to take effect. + +`, c.Root().Name()), + Args: NoArgs, + ValidArgsFunction: NoFileCompletions, + RunE: func(cmd *Command, args []string) error { + if noDesc { + return cmd.Root().GenPowerShellCompletion(out) + } + return cmd.Root().GenPowerShellCompletionWithDesc(out) + }, + } + if haveNoDescFlag { + nushell.Flags().BoolVar(&noDesc, compCmdNoDescFlagName, compCmdNoDescFlagDefault, compCmdNoDescFlagDesc) + } + + completionCmd.AddCommand(bash, zsh, fish, powershell, nushell) } func findFlag(cmd *Command, name string) *pflag.Flag { @@ -876,7 +909,7 @@ func CompDebug(msg string, printToStdErr bool) { // variable BASH_COMP_DEBUG_FILE to the path of some file to be used. if path := os.Getenv("BASH_COMP_DEBUG_FILE"); path != "" { f, err := os.OpenFile(path, - os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) if err == nil { defer f.Close() WriteStringAndCheck(f, msg) diff --git a/completions_test.go b/completions_test.go index df153fcf..5ee3a00f 100644 --- a/completions_test.go +++ b/completions_test.go @@ -98,7 +98,8 @@ func TestCmdNameCompletionInGo(t *testing.T) { "help", "secondChild", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -113,7 +114,8 @@ func TestCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "secondChild", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -128,7 +130,8 @@ func TestCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -147,7 +150,8 @@ func TestCmdNameCompletionInGo(t *testing.T) { "help\tHelp about any command", "secondChild", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -187,7 +191,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected := strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -203,7 +208,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -225,7 +231,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -247,7 +254,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "childCmd2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -262,7 +270,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -278,7 +287,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -295,7 +305,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "childCmd2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -312,7 +323,8 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "childCmd2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -337,7 +349,8 @@ func TestValidArgsCompletionInGo(t *testing.T) { "two", "three", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -352,7 +365,8 @@ func TestValidArgsCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "one", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -366,7 +380,8 @@ func TestValidArgsCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -400,7 +415,8 @@ func TestValidArgsAndCmdCompletionInGo(t *testing.T) { "one", "two", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -416,7 +432,8 @@ func TestValidArgsAndCmdCompletionInGo(t *testing.T) { "thechild", "two", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -451,7 +468,8 @@ func TestValidArgsFuncAndCmdCompletionInGo(t *testing.T) { "one", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -467,7 +485,8 @@ func TestValidArgsFuncAndCmdCompletionInGo(t *testing.T) { "thechild", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -483,7 +502,8 @@ func TestValidArgsFuncAndCmdCompletionInGo(t *testing.T) { "thechild\tThe child command", "two\tThe second", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -517,7 +537,8 @@ func TestFlagNameCompletionInGo(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -537,7 +558,8 @@ func TestFlagNameCompletionInGo(t *testing.T) { "--second", "-s", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -552,7 +574,8 @@ func TestFlagNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "--first", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -573,7 +596,8 @@ func TestFlagNameCompletionInGo(t *testing.T) { "--version", "-v", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -608,7 +632,8 @@ func TestFlagNameCompletionInGoWithDesc(t *testing.T) { "completion\tGenerate the autocompletion script for the specified shell", "help\tHelp about any command", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -628,7 +653,8 @@ func TestFlagNameCompletionInGoWithDesc(t *testing.T) { "--second\tsecond flag", "-s\tsecond flag", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -643,7 +669,8 @@ func TestFlagNameCompletionInGoWithDesc(t *testing.T) { expected = strings.Join([]string{ "--first\tfirst flag", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -664,7 +691,8 @@ func TestFlagNameCompletionInGoWithDesc(t *testing.T) { "--version\tversion for childCmd", "-v\tversion for childCmd", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -709,7 +737,8 @@ func TestFlagNameCompletionRepeat(t *testing.T) { "--second", "--slice", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -730,7 +759,8 @@ func TestFlagNameCompletionRepeat(t *testing.T) { "--help", "--slice", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -754,7 +784,8 @@ func TestFlagNameCompletionRepeat(t *testing.T) { "--second", "--slice", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -783,7 +814,8 @@ func TestFlagNameCompletionRepeat(t *testing.T) { "--slice", "-l", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -801,7 +833,8 @@ func TestFlagNameCompletionRepeat(t *testing.T) { expected = strings.Join([]string{ "-a", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -853,7 +886,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "-p", "realArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -871,7 +905,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "--requiredPersistent", "-p", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -886,7 +921,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "--release", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -905,7 +941,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "-s", "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -922,7 +959,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "--subRequired", "-s", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -936,7 +974,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "--subNotRequired", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -955,7 +994,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "-p", "realArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -977,7 +1017,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "-r", "realArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -995,7 +1036,8 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "realArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1033,7 +1075,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected := strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1047,7 +1090,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "log", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1061,7 +1105,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "yaml", "yml", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1075,7 +1120,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "yaml", "yml", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1089,7 +1135,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "yaml", "yml", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1103,7 +1150,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "yaml", "yml", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1117,7 +1165,8 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "txt", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1151,7 +1200,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected := strings.Join([]string{ ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1164,7 +1214,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1178,7 +1229,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "themes", ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1192,7 +1244,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "themes", ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1206,7 +1259,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "themes", ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1220,7 +1274,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "themes", ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1233,7 +1288,8 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1275,7 +1331,8 @@ func TestValidArgsFuncCmdContext(t *testing.T) { expected := strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1299,7 +1356,8 @@ func TestValidArgsFuncSingleCmd(t *testing.T) { "one", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1314,7 +1372,8 @@ func TestValidArgsFuncSingleCmd(t *testing.T) { expected = strings.Join([]string{ "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1341,7 +1400,8 @@ func TestValidArgsFuncSingleCmdInvalidArg(t *testing.T) { expected := strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1372,7 +1432,8 @@ func TestValidArgsFuncChildCmds(t *testing.T) { "one", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1387,7 +1448,8 @@ func TestValidArgsFuncChildCmds(t *testing.T) { expected = strings.Join([]string{ "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1401,7 +1463,8 @@ func TestValidArgsFuncChildCmds(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1417,7 +1480,8 @@ func TestValidArgsFuncChildCmds(t *testing.T) { "three", "four", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1431,7 +1495,8 @@ func TestValidArgsFuncChildCmds(t *testing.T) { expected = strings.Join([]string{ "three", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1445,7 +1510,8 @@ func TestValidArgsFuncChildCmds(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1472,7 +1538,8 @@ func TestValidArgsFuncAliases(t *testing.T) { "one", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1487,7 +1554,8 @@ func TestValidArgsFuncAliases(t *testing.T) { expected = strings.Join([]string{ "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1501,7 +1569,8 @@ func TestValidArgsFuncAliases(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1625,7 +1694,8 @@ func TestFlagCompletionInGo(t *testing.T) { "2", "10", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1641,7 +1711,8 @@ func TestFlagCompletionInGo(t *testing.T) { "1", "10", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1658,7 +1729,8 @@ func TestFlagCompletionInGo(t *testing.T) { "myfile.json", "file.xml", ":6", - "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1674,7 +1746,8 @@ func TestFlagCompletionInGo(t *testing.T) { "file.yaml", "file.xml", ":6", - "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1705,7 +1778,8 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { "one\tThe first", "two\tThe second", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1720,7 +1794,8 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { expected = strings.Join([]string{ "two\tThe second", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1734,7 +1809,8 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1750,7 +1826,8 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { "three\tThe third", "four\tThe fourth", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1764,7 +1841,8 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { expected = strings.Join([]string{ "three\tThe third", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1778,7 +1856,8 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1817,7 +1896,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--help\thelp for child", "--string\ttest string flag", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1833,7 +1913,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1849,7 +1930,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1868,7 +1950,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1884,7 +1967,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1900,7 +1984,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1916,7 +2001,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1932,7 +2018,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "arg1", "arg2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1948,7 +2035,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1964,7 +2052,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1982,7 +2071,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { expected = strings.Join([]string{ "--validarg", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2001,7 +2091,8 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "--toComp=ab", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2036,7 +2127,8 @@ func TestFlagCompletionWorksRootCommandAddedAfterFlags(t *testing.T) { expected := strings.Join([]string{ "myval", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2188,7 +2280,8 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { "2\tThe second", "10\tThe tenth", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2204,7 +2297,8 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { "1\tThe first", "10\tThe tenth", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2221,7 +2315,8 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { "myfile.json\tJSON format", "file.xml\tXML format", ":6", - "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2237,7 +2332,8 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { "file.yaml\tYAML format", "file.xml\tXML format", ":6", - "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2265,7 +2361,8 @@ func TestValidArgsNotValidArgsFunc(t *testing.T) { "one", "two", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2280,7 +2377,8 @@ func TestValidArgsNotValidArgsFunc(t *testing.T) { expected = strings.Join([]string{ "two", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2307,7 +2405,8 @@ func TestArgAliasesCompletionInGo(t *testing.T) { "two", "three", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2323,7 +2422,8 @@ func TestArgAliasesCompletionInGo(t *testing.T) { "two", "three", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2338,7 +2438,8 @@ func TestArgAliasesCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "trois", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2375,7 +2476,8 @@ func TestCompleteHelp(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2393,7 +2495,8 @@ func TestCompleteHelp(t *testing.T) { "completion", "help", // "<program> help help" is a valid command, so should be completed ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2408,7 +2511,8 @@ func TestCompleteHelp(t *testing.T) { expected = strings.Join([]string{ "child3", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2577,10 +2681,12 @@ func TestCompleteCompletion(t *testing.T) { expected := strings.Join([]string{ "bash", "fish", + "nushell", "powershell", "zsh", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2603,7 +2709,8 @@ func TestCompleteCompletion(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2635,7 +2742,8 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { "foo", "bar", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2651,7 +2759,8 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { "foo", "bar", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2666,7 +2775,8 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { expected = strings.Join([]string{ "works", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2681,7 +2791,8 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { expected = strings.Join([]string{ "works", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2697,7 +2808,8 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { "foo", "bar", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2705,7 +2817,6 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { } func TestCompleteWithDisableFlagParsing(t *testing.T) { - flagValidArgs := func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { return []string{"--flag", "-f"}, ShellCompDirectiveNoFileComp } @@ -2738,7 +2849,8 @@ func TestCompleteWithDisableFlagParsing(t *testing.T) { "--flag", "-f", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2760,7 +2872,8 @@ func TestCompleteWithDisableFlagParsing(t *testing.T) { "--nonPersistent", "-n", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2789,7 +2902,8 @@ func TestCompleteWithRootAndLegacyArgs(t *testing.T) { "arg1", "arg2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2805,7 +2919,8 @@ func TestCompleteWithRootAndLegacyArgs(t *testing.T) { "arg1", "arg2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2832,7 +2947,8 @@ func TestFixedCompletions(t *testing.T) { "banana", "orange", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2878,7 +2994,8 @@ func TestCompletionForGroupedFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "flags in group suggested with - prefix", @@ -2891,7 +3008,8 @@ func TestCompletionForGroupedFlags(t *testing.T) { "--ingroup3", "--nogroup", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "when flag in group present, other flags in group suggested even without - prefix", @@ -2901,7 +3019,8 @@ func TestCompletionForGroupedFlags(t *testing.T) { "--ingroup3", "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "when all flags in group present, flags not suggested without - prefix", @@ -2909,7 +3028,8 @@ func TestCompletionForGroupedFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "group ignored if some flags not applicable", @@ -2919,7 +3039,8 @@ func TestCompletionForGroupedFlags(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, } @@ -3076,7 +3197,8 @@ func TestCompletionForMutuallyExclusiveFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "flags in mutually exclusive group suggested with the - prefix", @@ -3089,7 +3211,8 @@ func TestCompletionForMutuallyExclusiveFlags(t *testing.T) { "--ingroup3", "--nogroup", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "when flag in mutually exclusive group present, other flags in group not suggested even with the - prefix", @@ -3100,7 +3223,8 @@ func TestCompletionForMutuallyExclusiveFlags(t *testing.T) { "-h", "--nogroup", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "group ignored if some flags not applicable", @@ -3111,7 +3235,8 @@ func TestCompletionForMutuallyExclusiveFlags(t *testing.T) { "--ingroup1", "--ingroup2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, } @@ -3215,70 +3340,80 @@ func TestCompletionCobraFlags(t *testing.T) { "--version", "-v", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after --help flag", args: []string{"--help", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after -h flag", args: []string{"-h", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after --version flag", args: []string{"--version", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after -v flag", args: []string{"-v", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after --help flag even with other completions", args: []string{"child", "--help", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after -h flag even with other completions", args: []string{"child", "-h", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after --version flag even with other completions", args: []string{"child", "--version", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after -v flag even with other completions", args: []string{"child", "-v", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion after -v flag even with other flag completions", args: []string{"child", "-v", "-"}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "completion after --help flag when created by program", @@ -3286,7 +3421,8 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "completion after -h flag when created by program", @@ -3294,7 +3430,8 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "completion after --version flag when created by program", @@ -3302,7 +3439,8 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "completion after -v flag when created by program", @@ -3310,14 +3448,16 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "completion after --version when only -v flag was created by program", args: []string{"child3", "--version", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "completion after -v flag when only -v flag was created by program", @@ -3325,7 +3465,8 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra3", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", "", + }, "\n"), }, { desc: "no completion for --help/-h and --version/-v flags when DisableFlagParsing=true", diff --git a/nushell_completions.go b/nushell_completions.go index 4363946f..3b4e2c67 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -16,31 +16,39 @@ package cobra import ( "bytes" + "fmt" "io" "os" ) func (c *Command) GenNushellCompletion(w io.Writer) error { buf := new(bytes.Buffer) - WriteStringAndCheck(buf, ` + WriteStringAndCheck(buf, fmt.Sprintf(` # An external configurator that works with any cobra based # command line application (e.g. kubectl, minikube) -let cobra_configurator = {|spans| +let cobra_completer = {|spans| + + let ShellCompDirectiveError = %[1]d + let ShellCompDirectiveNoSpace = %[2]d + let ShellCompDirectiveNoFileComp = %[3]d + let ShellCompDirectiveFilterFileExt = %[4]d + let ShellCompDirectiveFilterDirs = %[5]d let cmd = $spans.0 + let last_span = ($spans | last | str trim) # skip the first entry in the span (the command) and join the rest of the span to create __complete args let cmd_args = ($spans | skip 1 | str join ' ') # If the last span entry was empty add "" to the end of the command args - let cmd_args = if ($spans | last | str trim | is-empty) { + let cmd_args = if ($last_span | is-empty) { $'($cmd_args) ""' } else { $cmd_args } - # The full command to be executed - let full_cmd = $'($cmd) __complete ($cmd_args)' + # The full command to be executed with active help disable (Nushell does not support active help) + let full_cmd = $'($cmd)_ACTIVE_HELP=0 ($cmd) __complete ($cmd_args)' # Since nushell doesn't have anything like eval, execute in a subshell let result = (do -i { nu -c $"'($full_cmd)'" } | complete) @@ -48,16 +56,33 @@ let cobra_configurator = {|spans| # Create a record with all completion related info. # directive and directive_str are for posterity let stdout_lines = ($result.stdout | lines) - let $completions = ($stdout_lines | drop | parse -r '([\w\-\.:\+]*)\t?(.*)' | rename value description) + let directive = ($stdout_lines | last | str trim | str replace ":" "" | into int) + let completions = ($stdout_lines | drop | parse -r '([\w\-\.:\+\=]*)\t?(.*)' | rename value description) - let result = ({ - completions: $completions - directive_str: ($result.stderr) - directive: ($stdout_lines | last) - }) + # Add space at the end of each completion + let completions = if $directive != $ShellCompDirectiveNoSpace { + ($completions | each {|it| {value: $"($it.value) ", description: $it.description}}) + } else { + $completions + } - $result.completions -}`) + if $last_span =~ '=$' { + # return flag as part of the completion so that it doesn't get replaced + $completions | each {|it| $"($last_span)($it.value)" } + } else if $directive == $ShellCompDirectiveNoFileComp { + # Allow empty results as this will stop file completion + $completions + } else if ($completions | is-empty) or $directive == $ShellCompDirectiveError { + # Not returning null causes file completions to break + # Return null if there are no completions or ShellCompDirectiveError + null + } else { + $completions + } + +} +`, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) _, err := buf.WriteTo(w) return err diff --git a/nushell_completions_test.go b/nushell_completions_test.go index 3e3c36de..b82898aa 100644 --- a/nushell_completions_test.go +++ b/nushell_completions_test.go @@ -38,7 +38,7 @@ func TestGenNushellCompletion(t *testing.T) { assertNoErr(t, rootCmd.GenNushellCompletion(buf)) output := buf.String() - check(t, output, "let full_cmd = $'($cmd) __complete ($cmd_args)'") + check(t, output, "let full_cmd = $'($cmd)_ACTIVE_HELP=0 ($cmd) __complete ($cmd_args)'") } func TestGenNushellCompletionFile(t *testing.T) { From 1324e0c3160764624058582d7bf0a1995b055143 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sun, 27 Nov 2022 13:55:50 -0800 Subject: [PATCH 04/35] Added nushell to the Use: line --- site/content/completions/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md index b8a56d4f..dc4515a0 100644 --- a/site/content/completions/_index.md +++ b/site/content/completions/_index.md @@ -29,7 +29,7 @@ and then modifying the generated `cmd/completion.go` file to look something like ```go var completionCmd = &cobra.Command{ - Use: "completion [bash|zsh|fish|powershell]", + Use: "completion [bash|zsh|fish|powershell|nushell]", Short: "Generate completion script", Long: fmt.Sprintf(`To load completions: From 37ac7454fb5d5f5a785783faa27cdf8723b4e6a5 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sun, 27 Nov 2022 15:06:59 -0800 Subject: [PATCH 05/35] Added a whitelist to add cobra apps to to prevent non-cobra apps from being excuted --- completions.go | 14 +++- nushell_completions.go | 104 ++++++++++++++++------------- site/content/completions/_index.md | 14 +++- 3 files changed, 81 insertions(+), 51 deletions(-) diff --git a/completions.go b/completions.go index fee40e11..55a23fad 100644 --- a/completions.go +++ b/completions.go @@ -847,7 +847,7 @@ to your powershell profile. Short: fmt.Sprintf(shortDesc, "nushell"), Long: fmt.Sprintf(`Generate the autocompletion script for nushell. -To configure completions: +To configure the Nushell cobra external configurator for the first time: # 1. Copy the output of the command below: > %[1]s completion nushell @@ -860,7 +860,17 @@ To configure completions: # 4. Change the config block's external_completer line to be external_completer: $cobra_completer - # 5. You will need to start a new shell for this setup to take effect. + # 5. You will need to start a new shell or for this setup to take effect. + +If you have already setup the cobra external configurator: + + # 1. Edit the nushell config file: + > config nu + + # 2. Modify the cobra_apps varible to contain this application: + > let cobra_apps = [ "othercobraapp", "%[1]s" ] + + # 3. You will need to start a new shell or for this setup to take effect. `, c.Root().Name()), Args: NoArgs, diff --git a/nushell_completions.go b/nushell_completions.go index 3b4e2c67..568d3cb5 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -24,64 +24,72 @@ import ( func (c *Command) GenNushellCompletion(w io.Writer) error { buf := new(bytes.Buffer) WriteStringAndCheck(buf, fmt.Sprintf(` + +# A list of cobra that completion will be attempted for. +# Add new apps to this list to enable completion for them. +let cobra_apps = ["%[1]s"] + # An external configurator that works with any cobra based # command line application (e.g. kubectl, minikube) let cobra_completer = {|spans| - - let ShellCompDirectiveError = %[1]d - let ShellCompDirectiveNoSpace = %[2]d - let ShellCompDirectiveNoFileComp = %[3]d - let ShellCompDirectiveFilterFileExt = %[4]d - let ShellCompDirectiveFilterDirs = %[5]d - let cmd = $spans.0 - let last_span = ($spans | last | str trim) - # skip the first entry in the span (the command) and join the rest of the span to create __complete args - let cmd_args = ($spans | skip 1 | str join ' ') + if not ($cobra_apps | where $it == $cmd | is-empty) { + let ShellCompDirectiveError = %[2]d + let ShellCompDirectiveNoSpace = %[3]d + let ShellCompDirectiveNoFileComp = %[4]d + let ShellCompDirectiveFilterFileExt = %[5]d + let ShellCompDirectiveFilterDirs = %[6]d + + let last_span = ($spans | last | str trim) - # If the last span entry was empty add "" to the end of the command args - let cmd_args = if ($last_span | is-empty) { - $'($cmd_args) ""' + # skip the first entry in the span (the command) and join the rest of the span to create __complete args + let cmd_args = ($spans | skip 1 | str join ' ') + + # If the last span entry was empty add "" to the end of the command args + let cmd_args = if ($last_span | is-empty) { + $'($cmd_args) ""' + } else { + $cmd_args + } + + # The full command to be executed with active help disable (Nushell does not support active help) + let full_cmd = $'($cmd)_ACTIVE_HELP=0 ($cmd) __complete ($cmd_args)' + + # Since nushell doesn't have anything like eval, execute in a subshell + let result = (do -i { nu -c $"'($full_cmd)'" } | complete) + + # Create a record with all completion related info. + # directive and directive_str are for posterity + let stdout_lines = ($result.stdout | lines) + let directive = ($stdout_lines | last | str trim | str replace ":" "" | into int) + let completions = ($stdout_lines | drop | parse -r '([\w\-\.:\+\=]*)\t?(.*)' | rename value description) + + # Add space at the end of each completion + let completions = if $directive != $ShellCompDirectiveNoSpace { + ($completions | each {|it| {value: $"($it.value) ", description: $it.description}}) + } else { + $completions + } + + if $last_span =~ '=$' { + # return flag as part of the completion so that it doesn't get replaced + $completions | each {|it| $"($last_span)($it.value)" } + } else if $directive == $ShellCompDirectiveNoFileComp { + # Allow empty results as this will stop file completion + $completions + } else if ($completions | is-empty) or $directive == $ShellCompDirectiveError { + # Not returning null causes file completions to break + # Return null if there are no completions or ShellCompDirectiveError + null + } else { + $completions + } } else { - $cmd_args - } - - # The full command to be executed with active help disable (Nushell does not support active help) - let full_cmd = $'($cmd)_ACTIVE_HELP=0 ($cmd) __complete ($cmd_args)' - - # Since nushell doesn't have anything like eval, execute in a subshell - let result = (do -i { nu -c $"'($full_cmd)'" } | complete) - - # Create a record with all completion related info. - # directive and directive_str are for posterity - let stdout_lines = ($result.stdout | lines) - let directive = ($stdout_lines | last | str trim | str replace ":" "" | into int) - let completions = ($stdout_lines | drop | parse -r '([\w\-\.:\+\=]*)\t?(.*)' | rename value description) - - # Add space at the end of each completion - let completions = if $directive != $ShellCompDirectiveNoSpace { - ($completions | each {|it| {value: $"($it.value) ", description: $it.description}}) - } else { - $completions - } - - if $last_span =~ '=$' { - # return flag as part of the completion so that it doesn't get replaced - $completions | each {|it| $"($last_span)($it.value)" } - } else if $directive == $ShellCompDirectiveNoFileComp { - # Allow empty results as this will stop file completion - $completions - } else if ($completions | is-empty) or $directive == $ShellCompDirectiveError { - # Not returning null causes file completions to break - # Return null if there are no completions or ShellCompDirectiveError null - } else { - $completions } - } -`, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, +`, c.Name(), ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) _, err := buf.WriteTo(w) diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md index dc4515a0..f03ae6c9 100644 --- a/site/content/completions/_index.md +++ b/site/content/completions/_index.md @@ -72,6 +72,8 @@ PowerShell: Nushell: + # To configure the Nushell cobra external configurator for the first time: + # 1. Copy the output of the command below: > %[1]s completion nushell @@ -83,7 +85,17 @@ Nushell: # 4. Change the config block's external_completer line to be external_completer: $cobra_completer - # 5. You will need to start a new shell for this setup to take effect. + # 5. You will need to start a new shell or for this setup to take effect. + + # If you have already setup the cobra external configurator: + + # 1. Edit the nushell config file: + > config nu + + # 2. Modify the cobra_apps varible to contain this application: + > let cobra_apps = [ "othercobraapp", "%[1]s" ] + + # 3. You will need to start a new shell for this setup to take effect. `,cmd.Root().Name()), DisableFlagsInUseLine: true, From fa746d4d5a3915cca2f7746d723af4d0f3f706fa Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Mon, 28 Nov 2022 13:39:12 -0800 Subject: [PATCH 06/35] Incorporating pull request feedback - Fixing completion on full paths - Fixing completion with equals in flags - Fixing fuzzy search - Typos --- completions.go | 25 ++++++---------------- nushell_completions.go | 34 ++++++++++++++++++------------ nushell_completions_test.go | 9 ++++---- site/content/completions/_index.md | 12 ++--------- 4 files changed, 34 insertions(+), 46 deletions(-) diff --git a/completions.go b/completions.go index 55a23fad..f53e164f 100644 --- a/completions.go +++ b/completions.go @@ -847,39 +847,26 @@ to your powershell profile. Short: fmt.Sprintf(shortDesc, "nushell"), Long: fmt.Sprintf(`Generate the autocompletion script for nushell. -To configure the Nushell cobra external configurator for the first time: - +To configure the Nushell cobra external completer for the first time: # 1. Copy the output of the command below: - > %[1]s completion nushell - + > %[1]s completion nushell # 2. Edit the nushell config file: > config nu - # 3. Paste above the "let-env config" line. - - # 4. Change the config block's external_completer line to be - external_completer: $cobra_completer - + # 4. Change the config block's external_completer line to be external_completer: $cobra_completer # 5. You will need to start a new shell or for this setup to take effect. -If you have already setup the cobra external configurator: - +If you have already setup the cobra external completer: # 1. Edit the nushell config file: > config nu - # 2. Modify the cobra_apps varible to contain this application: > let cobra_apps = [ "othercobraapp", "%[1]s" ] - - # 3. You will need to start a new shell or for this setup to take effect. - + # 3. You will need to start a new shell for this setup to take effect. `, c.Root().Name()), Args: NoArgs, ValidArgsFunction: NoFileCompletions, RunE: func(cmd *Command, args []string) error { - if noDesc { - return cmd.Root().GenPowerShellCompletion(out) - } - return cmd.Root().GenPowerShellCompletionWithDesc(out) + return cmd.Root().GenNushellCompletion(out, !noDesc) }, } if haveNoDescFlag { diff --git a/nushell_completions.go b/nushell_completions.go index 568d3cb5..87c34a73 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -21,20 +21,20 @@ import ( "os" ) -func (c *Command) GenNushellCompletion(w io.Writer) error { +func (c *Command) GenNushellCompletion(w io.Writer, includeDesc bool) error { buf := new(bytes.Buffer) + name := c.Name() WriteStringAndCheck(buf, fmt.Sprintf(` - -# A list of cobra that completion will be attempted for. +# A list of cobra apps that completion will be attempted for. # Add new apps to this list to enable completion for them. let cobra_apps = ["%[1]s"] -# An external configurator that works with any cobra based +# An external completer that works with any cobra based # command line application (e.g. kubectl, minikube) let cobra_completer = {|spans| let cmd = $spans.0 - if not ($cobra_apps | where $it == $cmd | is-empty) { + if not ($cobra_apps | where $cmd =~ $it | is-empty) { let ShellCompDirectiveError = %[2]d let ShellCompDirectiveNoSpace = %[3]d let ShellCompDirectiveNoFileComp = %[4]d @@ -54,7 +54,7 @@ let cobra_completer = {|spans| } # The full command to be executed with active help disable (Nushell does not support active help) - let full_cmd = $'($cmd)_ACTIVE_HELP=0 ($cmd) __complete ($cmd_args)' + let full_cmd = $'%[7]s=0 ($cmd) __complete ($cmd_args)' # Since nushell doesn't have anything like eval, execute in a subshell let result = (do -i { nu -c $"'($full_cmd)'" } | complete) @@ -65,6 +65,14 @@ let cobra_completer = {|spans| let directive = ($stdout_lines | last | str trim | str replace ":" "" | into int) let completions = ($stdout_lines | drop | parse -r '([\w\-\.:\+\=]*)\t?(.*)' | rename value description) + # filter completions that don't contain the last span, for fuzzy searches + let filtered = ($completions | where $it.value =~ $last_span) + let completions = if not ($filtered | is-empty) { + $filtered + } else { + $completions + } + # Add space at the end of each completion let completions = if $directive != $ShellCompDirectiveNoSpace { ($completions | each {|it| {value: $"($it.value) ", description: $it.description}}) @@ -72,9 +80,9 @@ let cobra_completer = {|spans| $completions } - if $last_span =~ '=$' { - # return flag as part of the completion so that it doesn't get replaced - $completions | each {|it| $"($last_span)($it.value)" } + if $last_span =~ '=' { + # if the completion is of the form -n= return flag as part of the completion so that it doesn't get replaced + $completions | each {|it| $"($last_span | split row '=' | first)=($it.value)" } } else if $directive == $ShellCompDirectiveNoFileComp { # Allow empty results as this will stop file completion $completions @@ -89,19 +97,19 @@ let cobra_completer = {|spans| null } } -`, c.Name(), ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) +`, name, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) _, err := buf.WriteTo(w) return err } -func (c *Command) GenNushellCompletionFile(filename string) error { +func (c *Command) GenNushellCompletionFile(filename string, includeDesc bool) error { outFile, err := os.Create(filename) if err != nil { return err } defer outFile.Close() - return c.GenNushellCompletion(outFile) + return c.GenNushellCompletion(outFile, includeDesc) } diff --git a/nushell_completions_test.go b/nushell_completions_test.go index b82898aa..73fedd07 100644 --- a/nushell_completions_test.go +++ b/nushell_completions_test.go @@ -16,6 +16,7 @@ package cobra import ( "bytes" + "fmt" "log" "os" "testing" @@ -35,10 +36,10 @@ func TestGenNushellCompletion(t *testing.T) { rootCmd.AddCommand(getCmd) buf := new(bytes.Buffer) - assertNoErr(t, rootCmd.GenNushellCompletion(buf)) + assertNoErr(t, rootCmd.GenNushellCompletion(buf, true)) output := buf.String() - check(t, output, "let full_cmd = $'($cmd)_ACTIVE_HELP=0 ($cmd) __complete ($cmd_args)'") + check(t, output, fmt.Sprintf("let cobra_apps = [\"%[1]s\"]", rootCmd.Name())) } func TestGenNushellCompletionFile(t *testing.T) { @@ -57,7 +58,7 @@ func TestGenNushellCompletionFile(t *testing.T) { } rootCmd.AddCommand(child) - assertNoErr(t, rootCmd.GenNushellCompletionFile("./tmp/test")) + assertNoErr(t, rootCmd.GenNushellCompletionFile("./tmp/test", true)) } func TestFailGenNushellCompletionFile(t *testing.T) { @@ -79,7 +80,7 @@ func TestFailGenNushellCompletionFile(t *testing.T) { } rootCmd.AddCommand(child) - got := rootCmd.GenNushellCompletionFile("./tmp/test") + got := rootCmd.GenNushellCompletionFile("./tmp/test", true) if got == nil { t.Error("should raise permission denied error") } diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md index f03ae6c9..2f598c7c 100644 --- a/site/content/completions/_index.md +++ b/site/content/completions/_index.md @@ -72,29 +72,21 @@ PowerShell: Nushell: - # To configure the Nushell cobra external configurator for the first time: - + # To configure the Nushell cobra external completer for the first time: # 1. Copy the output of the command below: > %[1]s completion nushell - # 2. Edit the nushell config file: > config nu - # 3. Paste above the "let-env config" line. - # 4. Change the config block's external_completer line to be external_completer: $cobra_completer - # 5. You will need to start a new shell or for this setup to take effect. - # If you have already setup the cobra external configurator: - + # If you have already setup the cobra external completer: # 1. Edit the nushell config file: > config nu - # 2. Modify the cobra_apps varible to contain this application: > let cobra_apps = [ "othercobraapp", "%[1]s" ] - # 3. You will need to start a new shell for this setup to take effect. `,cmd.Root().Name()), From d86bac4e347bed145414216f883af83d5c66aad1 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Thu, 15 Dec 2022 13:21:37 -0800 Subject: [PATCH 07/35] "fixing oddities with fuzzy searching and bug with active help" --- nushell_completions.go | 116 +++++++++++++++++++++++++++++++---------- 1 file changed, 88 insertions(+), 28 deletions(-) diff --git a/nushell_completions.go b/nushell_completions.go index 87c34a73..8f7c8568 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -31,7 +31,7 @@ let cobra_apps = ["%[1]s"] # An external completer that works with any cobra based # command line application (e.g. kubectl, minikube) -let cobra_completer = {|spans| +let-env cobra_completer = {|spans| let cmd = $spans.0 if not ($cobra_apps | where $cmd =~ $it | is-empty) { @@ -43,44 +43,96 @@ let cobra_completer = {|spans| let last_span = ($spans | last | str trim) - # skip the first entry in the span (the command) and join the rest of the span to create __complete args - let cmd_args = ($spans | skip 1 | str join ' ') + def exec_complete [ + --fuzzy, + spans: list + ] { + let params = { + last_span: ($spans | last | str trim), + spans: $spans + } + + # If there is an equals in the last span + # parse the span into two + let params = if $last_span =~ '=' { + let split = ($last_span | split row '=') + if ($split | length) > 1 { + { + last_span: ($split | last), + spans: ($spans | drop | append ($split | first) | append ($split | last)) + } + } else { + { + last_span: '', + spans: ($spans | drop | append ($split | first) | append '') + } + } + } else { + $params + } - # If the last span entry was empty add "" to the end of the command args - let cmd_args = if ($last_span | is-empty) { - $'($cmd_args) ""' - } else { - $cmd_args + let last_span = $params.last_span + let spans = $params.spans + + # Drop the last param so we can fuzzy search on it + let spans = if $fuzzy { + $spans | drop + } else { + $spans + } + + # skip the first entry in the span (the command) and join the rest of the span to create __complete args + let cmd_args = ($spans | skip 1 | str join ' ') + + # If the last span entry was empty add "" to the end of the command args + let cmd_args = if ($last_span | is-empty) or $fuzzy { + $'($cmd_args) ""' + } else { + $cmd_args + } + + # The full command to be executed with active help disable (Nushell does not support active help) + let full_cmd = $'COBRA_ACTIVE_HELP=0 ($cmd) __complete ($cmd_args)' + + # Since nushell doesn't have anything like eval, execute in a subshell + let result = (do -i { nu -c $"'($full_cmd)'" } | complete) + + # Create a record with all completion related info. + # directive and directive_str are for posterity + let stdout_lines = ($result.stdout | lines) + let directive = ($stdout_lines | last | str trim | str replace ":" "" | into int) + let completions = ($stdout_lines | drop | parse -r '([\w\-\.:\+\=]*)\t?(.*)' | rename value description) + let completions = if $fuzzy { + $completions | where $it.value =~ $last_span + + } else { + ($completions | where {|it| $it.value | str starts-with $last_span }) + } + + { + directive: $directive, + completions: $completions + } } - # The full command to be executed with active help disable (Nushell does not support active help) - let full_cmd = $'%[7]s=0 ($cmd) __complete ($cmd_args)' - - # Since nushell doesn't have anything like eval, execute in a subshell - let result = (do -i { nu -c $"'($full_cmd)'" } | complete) - - # Create a record with all completion related info. - # directive and directive_str are for posterity - let stdout_lines = ($result.stdout | lines) - let directive = ($stdout_lines | last | str trim | str replace ":" "" | into int) - let completions = ($stdout_lines | drop | parse -r '([\w\-\.:\+\=]*)\t?(.*)' | rename value description) - - # filter completions that don't contain the last span, for fuzzy searches - let filtered = ($completions | where $it.value =~ $last_span) - let completions = if not ($filtered | is-empty) { - $filtered + let result = (exec_complete $spans) + let result = if (not ($last_span | is-empty)) and ($result.completions | is-empty) { + exec_complete --fuzzy $spans } else { - $completions + $result } + let directive = $result.directive + let completions = $result.completions + # Add space at the end of each completion let completions = if $directive != $ShellCompDirectiveNoSpace { - ($completions | each {|it| {value: $"($it.value) ", description: $it.description}}) + $completions | each {|it| {value: $"($it.value) ", description: $it.description}} } else { $completions } - if $last_span =~ '=' { + let return_val = if $last_span =~ '=' { # if the completion is of the form -n= return flag as part of the completion so that it doesn't get replaced $completions | each {|it| $"($last_span | split row '=' | first)=($it.value)" } } else if $directive == $ShellCompDirectiveNoFileComp { @@ -93,12 +145,20 @@ let cobra_completer = {|spans| } else { $completions } + + $return_val } else { null } } + + + + + + `, name, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) _, err := buf.WriteTo(w) return err From 247e8e6b55e341dc50169d9968cb1645da67955c Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Fri, 16 Dec 2022 09:32:22 -0800 Subject: [PATCH 08/35] "ignoring return value when directive is ShellComp#directiveFilterFileExt" --- nushell_completions.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/nushell_completions.go b/nushell_completions.go index 8f7c8568..c03ea8df 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -31,7 +31,7 @@ let cobra_apps = ["%[1]s"] # An external completer that works with any cobra based # command line application (e.g. kubectl, minikube) -let-env cobra_completer = {|spans| +let cobra_completer = {|spans| let cmd = $spans.0 if not ($cobra_apps | where $cmd =~ $it | is-empty) { @@ -132,6 +132,14 @@ let-env cobra_completer = {|spans| $completions } + # Cobra returns a list of completions that are supported with this directive + # There is no way to currently support this in a nushell external completer + let completions = if $directive == $ShellCompDirectiveFilterFileExt { + [] + } else { + $completions + } + let return_val = if $last_span =~ '=' { # if the completion is of the form -n= return flag as part of the completion so that it doesn't get replaced $completions | each {|it| $"($last_span | split row '=' | first)=($it.value)" } From 3b016843b92be4440241751e24722117fecca57a Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Fri, 16 Dec 2022 09:50:05 -0800 Subject: [PATCH 09/35] "fixing completions that contain a /" --- nushell_completions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nushell_completions.go b/nushell_completions.go index c03ea8df..fe9782d5 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -101,7 +101,7 @@ let cobra_completer = {|spans| # directive and directive_str are for posterity let stdout_lines = ($result.stdout | lines) let directive = ($stdout_lines | last | str trim | str replace ":" "" | into int) - let completions = ($stdout_lines | drop | parse -r '([\w\-\.:\+\=]*)\t?(.*)' | rename value description) + let completions = ($stdout_lines | drop | parse -r '([\w\-\.:\+\=\/]*)\t?(.*)' | rename value description) let completions = if $fuzzy { $completions | where $it.value =~ $last_span From 4c4bde658648de59a25b1a0700804b2d6e0ea5b8 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Fri, 23 Dec 2022 20:30:18 -0800 Subject: [PATCH 10/35] "removing extra lines/whitespace" --- nushell_completions.go | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/nushell_completions.go b/nushell_completions.go index fe9782d5..fb3c1156 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -31,7 +31,7 @@ let cobra_apps = ["%[1]s"] # An external completer that works with any cobra based # command line application (e.g. kubectl, minikube) -let cobra_completer = {|spans| +let cobra_completer = {|spans| let cmd = $spans.0 if not ($cobra_apps | where $cmd =~ $it | is-empty) { @@ -40,7 +40,6 @@ let cobra_completer = {|spans| let ShellCompDirectiveNoFileComp = %[4]d let ShellCompDirectiveFilterFileExt = %[5]d let ShellCompDirectiveFilterDirs = %[6]d - let last_span = ($spans | last | str trim) def exec_complete [ @@ -51,7 +50,6 @@ let cobra_completer = {|spans| last_span: ($spans | last | str trim), spans: $spans } - # If there is an equals in the last span # parse the span into two let params = if $last_span =~ '=' { @@ -66,7 +64,7 @@ let cobra_completer = {|spans| last_span: '', spans: ($spans | drop | append ($split | first) | append '') } - } + } } else { $params } @@ -82,7 +80,7 @@ let cobra_completer = {|spans| } # skip the first entry in the span (the command) and join the rest of the span to create __complete args - let cmd_args = ($spans | skip 1 | str join ' ') + let cmd_args = ($spans | skip 1 | str join ' ') # If the last span entry was empty add "" to the end of the command args let cmd_args = if ($last_span | is-empty) or $fuzzy { @@ -97,7 +95,7 @@ let cobra_completer = {|spans| # Since nushell doesn't have anything like eval, execute in a subshell let result = (do -i { nu -c $"'($full_cmd)'" } | complete) - # Create a record with all completion related info. + # Create a record with all completion related info. # directive and directive_str are for posterity let stdout_lines = ($result.stdout | lines) let directive = ($stdout_lines | last | str trim | str replace ":" "" | into int) @@ -110,7 +108,7 @@ let cobra_completer = {|spans| } { - directive: $directive, + directive: $directive, completions: $completions } } @@ -148,7 +146,7 @@ let cobra_completer = {|spans| $completions } else if ($completions | is-empty) or $directive == $ShellCompDirectiveError { # Not returning null causes file completions to break - # Return null if there are no completions or ShellCompDirectiveError + # Return null if there are no completions or ShellCompDirectiveError null } else { $completions @@ -159,12 +157,6 @@ let cobra_completer = {|spans| null } } - - - - - - `, name, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) From 3bfdd6421fd61838db3b9630cfe2379416fcc0bf Mon Sep 17 00:00:00 2001 From: Jack Wright <56345+ayax79@users.noreply.github.com> Date: Fri, 23 Dec 2022 20:31:30 -0800 Subject: [PATCH 11/35] Update completions.go Co-authored-by: Marc Khouzam <marc.khouzam@gmail.com> --- completions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/completions.go b/completions.go index f53e164f..5e4dc262 100644 --- a/completions.go +++ b/completions.go @@ -854,7 +854,7 @@ To configure the Nushell cobra external completer for the first time: > config nu # 3. Paste above the "let-env config" line. # 4. Change the config block's external_completer line to be external_completer: $cobra_completer - # 5. You will need to start a new shell or for this setup to take effect. + # 5. You will need to start a new shel for this setup to take effect. If you have already setup the cobra external completer: # 1. Edit the nushell config file: From ead0ff3e53f67d6e13cc40841b31573534a7a6a6 Mon Sep 17 00:00:00 2001 From: Jack Wright <56345+ayax79@users.noreply.github.com> Date: Fri, 23 Dec 2022 20:31:38 -0800 Subject: [PATCH 12/35] Update completions.go Co-authored-by: Marc Khouzam <marc.khouzam@gmail.com> --- completions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/completions.go b/completions.go index 5e4dc262..6a81cd51 100644 --- a/completions.go +++ b/completions.go @@ -859,7 +859,7 @@ To configure the Nushell cobra external completer for the first time: If you have already setup the cobra external completer: # 1. Edit the nushell config file: > config nu - # 2. Modify the cobra_apps varible to contain this application: + # 2. Modify the cobra_apps variable to contain this new application: > let cobra_apps = [ "othercobraapp", "%[1]s" ] # 3. You will need to start a new shell for this setup to take effect. `, c.Root().Name()), From 8cb972847673951daf5aa09377d108ca4ab8af19 Mon Sep 17 00:00:00 2001 From: Jack Wright <56345+ayax79@users.noreply.github.com> Date: Fri, 23 Dec 2022 20:31:48 -0800 Subject: [PATCH 13/35] Update completions.go Co-authored-by: Marc Khouzam <marc.khouzam@gmail.com> --- completions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/completions.go b/completions.go index 6a81cd51..f6924ba7 100644 --- a/completions.go +++ b/completions.go @@ -856,7 +856,7 @@ To configure the Nushell cobra external completer for the first time: # 4. Change the config block's external_completer line to be external_completer: $cobra_completer # 5. You will need to start a new shel for this setup to take effect. -If you have already setup the cobra external completer: +If you have already setup the cobra external completer for other Cobra-based applications: # 1. Edit the nushell config file: > config nu # 2. Modify the cobra_apps variable to contain this new application: From 1a69a83abcae278ed9bd54cb7420b21111dc3492 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Fri, 23 Dec 2022 20:39:54 -0800 Subject: [PATCH 14/35] "Added nushell to list of shell autompletes" --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0fb0373c..6ffa0cfb 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Cobra provides: * Automatic help generation for commands and flags * Grouping help for subcommands * Automatic help flag recognition of `-h`, `--help`, etc. -* Automatically generated shell autocomplete for your application (bash, zsh, fish, powershell) +* Automatically generated shell autocomplete for your application (bash, zsh, fish, powershell, nushell) * Automatically generated man pages for your application * Command aliases so you can change things without breaking them * The flexibility to define your own help, usage, etc. From f963733c4e903a77f648a7bf9af5708a21e01be7 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Fri, 23 Dec 2022 20:40:17 -0800 Subject: [PATCH 15/35] "Reverted to old version without formatting changes and readded nushell" --- completions_test.go | 426 +++++++++++++++----------------------------- 1 file changed, 143 insertions(+), 283 deletions(-) diff --git a/completions_test.go b/completions_test.go index 5ee3a00f..d423b162 100644 --- a/completions_test.go +++ b/completions_test.go @@ -98,8 +98,7 @@ func TestCmdNameCompletionInGo(t *testing.T) { "help", "secondChild", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -114,8 +113,7 @@ func TestCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "secondChild", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -130,8 +128,7 @@ func TestCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -150,8 +147,7 @@ func TestCmdNameCompletionInGo(t *testing.T) { "help\tHelp about any command", "secondChild", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -191,8 +187,7 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected := strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -208,8 +203,7 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -231,8 +225,7 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -254,8 +247,7 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "childCmd2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -270,8 +262,7 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -287,8 +278,7 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -305,8 +295,7 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "childCmd2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -323,8 +312,7 @@ func TestNoCmdNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "childCmd2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -349,8 +337,7 @@ func TestValidArgsCompletionInGo(t *testing.T) { "two", "three", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -365,8 +352,7 @@ func TestValidArgsCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "one", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -380,8 +366,7 @@ func TestValidArgsCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -415,8 +400,7 @@ func TestValidArgsAndCmdCompletionInGo(t *testing.T) { "one", "two", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -432,8 +416,7 @@ func TestValidArgsAndCmdCompletionInGo(t *testing.T) { "thechild", "two", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -468,8 +451,7 @@ func TestValidArgsFuncAndCmdCompletionInGo(t *testing.T) { "one", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -485,8 +467,7 @@ func TestValidArgsFuncAndCmdCompletionInGo(t *testing.T) { "thechild", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -502,8 +483,7 @@ func TestValidArgsFuncAndCmdCompletionInGo(t *testing.T) { "thechild\tThe child command", "two\tThe second", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -537,8 +517,7 @@ func TestFlagNameCompletionInGo(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -558,8 +537,7 @@ func TestFlagNameCompletionInGo(t *testing.T) { "--second", "-s", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -574,8 +552,7 @@ func TestFlagNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "--first", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -596,8 +573,7 @@ func TestFlagNameCompletionInGo(t *testing.T) { "--version", "-v", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -632,8 +608,7 @@ func TestFlagNameCompletionInGoWithDesc(t *testing.T) { "completion\tGenerate the autocompletion script for the specified shell", "help\tHelp about any command", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -653,8 +628,7 @@ func TestFlagNameCompletionInGoWithDesc(t *testing.T) { "--second\tsecond flag", "-s\tsecond flag", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -669,8 +643,7 @@ func TestFlagNameCompletionInGoWithDesc(t *testing.T) { expected = strings.Join([]string{ "--first\tfirst flag", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -691,8 +664,7 @@ func TestFlagNameCompletionInGoWithDesc(t *testing.T) { "--version\tversion for childCmd", "-v\tversion for childCmd", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -737,8 +709,7 @@ func TestFlagNameCompletionRepeat(t *testing.T) { "--second", "--slice", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -759,8 +730,7 @@ func TestFlagNameCompletionRepeat(t *testing.T) { "--help", "--slice", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -784,8 +754,7 @@ func TestFlagNameCompletionRepeat(t *testing.T) { "--second", "--slice", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -814,8 +783,7 @@ func TestFlagNameCompletionRepeat(t *testing.T) { "--slice", "-l", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -833,8 +801,7 @@ func TestFlagNameCompletionRepeat(t *testing.T) { expected = strings.Join([]string{ "-a", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -886,8 +853,7 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "-p", "realArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -905,8 +871,7 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "--requiredPersistent", "-p", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -921,8 +886,7 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "--release", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -941,8 +905,7 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "-s", "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -959,8 +922,7 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "--subRequired", "-s", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -974,8 +936,7 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "--subNotRequired", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -994,8 +955,7 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "-p", "realArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1017,8 +977,7 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { "-r", "realArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1036,8 +995,7 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "realArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1075,8 +1033,7 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected := strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1090,8 +1047,7 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "log", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1105,8 +1061,7 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "yaml", "yml", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1120,8 +1075,7 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "yaml", "yml", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1135,8 +1089,7 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "yaml", "yml", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1150,8 +1103,7 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "yaml", "yml", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1165,8 +1117,7 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "txt", ":8", - "Completion ended with directive: ShellCompDirectiveFilterFileExt", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveFilterFileExt", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1200,8 +1151,7 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected := strings.Join([]string{ ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1214,8 +1164,7 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1229,8 +1178,7 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "themes", ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1244,8 +1192,7 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "themes", ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1259,8 +1206,7 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "themes", ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1274,8 +1220,7 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "themes", ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1288,8 +1233,7 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) { expected = strings.Join([]string{ ":16", - "Completion ended with directive: ShellCompDirectiveFilterDirs", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveFilterDirs", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1331,8 +1275,7 @@ func TestValidArgsFuncCmdContext(t *testing.T) { expected := strings.Join([]string{ ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1356,8 +1299,7 @@ func TestValidArgsFuncSingleCmd(t *testing.T) { "one", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1372,8 +1314,7 @@ func TestValidArgsFuncSingleCmd(t *testing.T) { expected = strings.Join([]string{ "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1400,8 +1341,7 @@ func TestValidArgsFuncSingleCmdInvalidArg(t *testing.T) { expected := strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1432,8 +1372,7 @@ func TestValidArgsFuncChildCmds(t *testing.T) { "one", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1448,8 +1387,7 @@ func TestValidArgsFuncChildCmds(t *testing.T) { expected = strings.Join([]string{ "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1463,8 +1401,7 @@ func TestValidArgsFuncChildCmds(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1480,8 +1417,7 @@ func TestValidArgsFuncChildCmds(t *testing.T) { "three", "four", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1495,8 +1431,7 @@ func TestValidArgsFuncChildCmds(t *testing.T) { expected = strings.Join([]string{ "three", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1510,8 +1445,7 @@ func TestValidArgsFuncChildCmds(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1538,8 +1472,7 @@ func TestValidArgsFuncAliases(t *testing.T) { "one", "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1554,8 +1487,7 @@ func TestValidArgsFuncAliases(t *testing.T) { expected = strings.Join([]string{ "two", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1569,8 +1501,7 @@ func TestValidArgsFuncAliases(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1694,8 +1625,7 @@ func TestFlagCompletionInGo(t *testing.T) { "2", "10", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1711,8 +1641,7 @@ func TestFlagCompletionInGo(t *testing.T) { "1", "10", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1729,8 +1658,7 @@ func TestFlagCompletionInGo(t *testing.T) { "myfile.json", "file.xml", ":6", - "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1746,8 +1674,7 @@ func TestFlagCompletionInGo(t *testing.T) { "file.yaml", "file.xml", ":6", - "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1778,8 +1705,7 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { "one\tThe first", "two\tThe second", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1794,8 +1720,7 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { expected = strings.Join([]string{ "two\tThe second", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1809,8 +1734,7 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1826,8 +1750,7 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { "three\tThe third", "four\tThe fourth", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1841,8 +1764,7 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { expected = strings.Join([]string{ "three\tThe third", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1856,8 +1778,7 @@ func TestValidArgsFuncChildCmdsWithDesc(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1896,8 +1817,7 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--help\thelp for child", "--string\ttest string flag", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1913,8 +1833,7 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1930,8 +1849,7 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1950,8 +1868,7 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1967,8 +1884,7 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -1984,8 +1900,7 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2001,8 +1916,7 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2018,8 +1932,7 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "arg1", "arg2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2035,8 +1948,7 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2052,8 +1964,7 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "test", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2071,8 +1982,7 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { expected = strings.Join([]string{ "--validarg", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2091,8 +2001,7 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) { "--validarg", "--toComp=ab", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2127,8 +2036,7 @@ func TestFlagCompletionWorksRootCommandAddedAfterFlags(t *testing.T) { expected := strings.Join([]string{ "myval", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2280,8 +2188,7 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { "2\tThe second", "10\tThe tenth", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2297,8 +2204,7 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { "1\tThe first", "10\tThe tenth", ":0", - "Completion ended with directive: ShellCompDirectiveDefault", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2315,8 +2221,7 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { "myfile.json\tJSON format", "file.xml\tXML format", ":6", - "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2332,8 +2237,7 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) { "file.yaml\tYAML format", "file.xml\tXML format", ":6", - "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2361,8 +2265,7 @@ func TestValidArgsNotValidArgsFunc(t *testing.T) { "one", "two", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2377,8 +2280,7 @@ func TestValidArgsNotValidArgsFunc(t *testing.T) { expected = strings.Join([]string{ "two", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2405,8 +2307,7 @@ func TestArgAliasesCompletionInGo(t *testing.T) { "two", "three", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2422,8 +2323,7 @@ func TestArgAliasesCompletionInGo(t *testing.T) { "two", "three", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2438,8 +2338,7 @@ func TestArgAliasesCompletionInGo(t *testing.T) { expected = strings.Join([]string{ "trois", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2476,8 +2375,7 @@ func TestCompleteHelp(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2495,8 +2393,7 @@ func TestCompleteHelp(t *testing.T) { "completion", "help", // "<program> help help" is a valid command, so should be completed ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2511,8 +2408,7 @@ func TestCompleteHelp(t *testing.T) { expected = strings.Join([]string{ "child3", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2681,12 +2577,11 @@ func TestCompleteCompletion(t *testing.T) { expected := strings.Join([]string{ "bash", "fish", - "nushell", + "nushell", "powershell", "zsh", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2709,8 +2604,7 @@ func TestCompleteCompletion(t *testing.T) { expected = strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2742,8 +2636,7 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { "foo", "bar", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2759,8 +2652,7 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { "foo", "bar", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2775,8 +2667,7 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { expected = strings.Join([]string{ "works", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2791,8 +2682,7 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { expected = strings.Join([]string{ "works", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2808,8 +2698,7 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { "foo", "bar", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2817,6 +2706,7 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) { } func TestCompleteWithDisableFlagParsing(t *testing.T) { + flagValidArgs := func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { return []string{"--flag", "-f"}, ShellCompDirectiveNoFileComp } @@ -2849,8 +2739,7 @@ func TestCompleteWithDisableFlagParsing(t *testing.T) { "--flag", "-f", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2872,8 +2761,7 @@ func TestCompleteWithDisableFlagParsing(t *testing.T) { "--nonPersistent", "-n", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2902,8 +2790,7 @@ func TestCompleteWithRootAndLegacyArgs(t *testing.T) { "arg1", "arg2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2919,8 +2806,7 @@ func TestCompleteWithRootAndLegacyArgs(t *testing.T) { "arg1", "arg2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2947,8 +2833,7 @@ func TestFixedCompletions(t *testing.T) { "banana", "orange", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n") + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) @@ -2994,8 +2879,7 @@ func TestCompletionForGroupedFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "flags in group suggested with - prefix", @@ -3008,8 +2892,7 @@ func TestCompletionForGroupedFlags(t *testing.T) { "--ingroup3", "--nogroup", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "when flag in group present, other flags in group suggested even without - prefix", @@ -3019,8 +2902,7 @@ func TestCompletionForGroupedFlags(t *testing.T) { "--ingroup3", "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "when all flags in group present, flags not suggested without - prefix", @@ -3028,8 +2910,7 @@ func TestCompletionForGroupedFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "group ignored if some flags not applicable", @@ -3039,8 +2920,7 @@ func TestCompletionForGroupedFlags(t *testing.T) { "completion", "help", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, } @@ -3197,8 +3077,7 @@ func TestCompletionForMutuallyExclusiveFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "subArg", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "flags in mutually exclusive group suggested with the - prefix", @@ -3211,8 +3090,7 @@ func TestCompletionForMutuallyExclusiveFlags(t *testing.T) { "--ingroup3", "--nogroup", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "when flag in mutually exclusive group present, other flags in group not suggested even with the - prefix", @@ -3223,8 +3101,7 @@ func TestCompletionForMutuallyExclusiveFlags(t *testing.T) { "-h", "--nogroup", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "group ignored if some flags not applicable", @@ -3235,8 +3112,7 @@ func TestCompletionForMutuallyExclusiveFlags(t *testing.T) { "--ingroup1", "--ingroup2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, } @@ -3340,80 +3216,70 @@ func TestCompletionCobraFlags(t *testing.T) { "--version", "-v", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "no completion after --help flag", args: []string{"--help", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "no completion after -h flag", args: []string{"-h", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "no completion after --version flag", args: []string{"--version", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "no completion after -v flag", args: []string{"-v", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "no completion after --help flag even with other completions", args: []string{"child", "--help", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "no completion after -h flag even with other completions", args: []string{"child", "-h", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "no completion after --version flag even with other completions", args: []string{"child", "--version", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "no completion after -v flag even with other completions", args: []string{"child", "-v", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "no completion after -v flag even with other flag completions", args: []string{"child", "-v", "-"}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "completion after --help flag when created by program", @@ -3421,8 +3287,7 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "completion after -h flag when created by program", @@ -3430,8 +3295,7 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "completion after --version flag when created by program", @@ -3439,8 +3303,7 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "completion after -v flag when created by program", @@ -3448,16 +3311,14 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra2", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "completion after --version when only -v flag was created by program", args: []string{"child3", "--version", ""}, expectedOutput: strings.Join([]string{ ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "completion after -v flag when only -v flag was created by program", @@ -3465,8 +3326,7 @@ func TestCompletionCobraFlags(t *testing.T) { expectedOutput: strings.Join([]string{ "extra3", ":4", - "Completion ended with directive: ShellCompDirectiveNoFileComp", "", - }, "\n"), + "Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n"), }, { desc: "no completion for --help/-h and --version/-v flags when DisableFlagParsing=true", From 29af015b5749d98e9d5b4f4896f6229e72b1c933 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Tue, 27 Dec 2022 12:17:42 -0800 Subject: [PATCH 16/35] "fixed whitespace" --- completions_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/completions_test.go b/completions_test.go index d423b162..718f55d8 100644 --- a/completions_test.go +++ b/completions_test.go @@ -2577,7 +2577,7 @@ func TestCompleteCompletion(t *testing.T) { expected := strings.Join([]string{ "bash", "fish", - "nushell", + "nushell", "powershell", "zsh", ":4", From e7abbf39a39676e2745c099a99e9c52c1fdcfdae Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Wed, 27 Nov 2024 21:05:56 -0800 Subject: [PATCH 17/35] rewriting nushell implementation --- nushell_completions.go | 189 ++++++++++++++++------------------------- 1 file changed, 71 insertions(+), 118 deletions(-) diff --git a/nushell_completions.go b/nushell_completions.go index fb3c1156..7df265d4 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -23,141 +23,94 @@ import ( func (c *Command) GenNushellCompletion(w io.Writer, includeDesc bool) error { buf := new(bytes.Buffer) - name := c.Name() WriteStringAndCheck(buf, fmt.Sprintf(` -# A list of cobra apps that completion will be attempted for. -# Add new apps to this list to enable completion for them. -let cobra_apps = ["%[1]s"] - # An external completer that works with any cobra based # command line application (e.g. kubectl, minikube) let cobra_completer = {|spans| - let cmd = $spans.0 + let ShellCompDirectiveError = %[1]d + let ShellCompDirectiveNoSpace = %[2]d + let ShellCompDirectiveNoFileComp = %[3]d + let ShellCompDirectiveFilterFileExt = %[4]d + let ShellCompDirectiveFilterDirs = %[5]d - if not ($cobra_apps | where $cmd =~ $it | is-empty) { - let ShellCompDirectiveError = %[2]d - let ShellCompDirectiveNoSpace = %[3]d - let ShellCompDirectiveNoFileComp = %[4]d - let ShellCompDirectiveFilterFileExt = %[5]d - let ShellCompDirectiveFilterDirs = %[6]d - let last_span = ($spans | last | str trim) + let cmd = $spans | first + let rest = $spans | skip - def exec_complete [ - --fuzzy, - spans: list - ] { - let params = { - last_span: ($spans | last | str trim), - spans: $spans - } - # If there is an equals in the last span - # parse the span into two - let params = if $last_span =~ '=' { - let split = ($last_span | split row '=') - if ($split | length) > 1 { - { - last_span: ($split | last), - spans: ($spans | drop | append ($split | first) | append ($split | last)) - } - } else { - { - last_span: '', - spans: ($spans | drop | append ($split | first) | append '') - } - } - } else { - $params - } + def exec_complete [ + spans: list<string> + ] { + # This will catch the stderr message related to the directive and any other errors, + # such as the command not being a cobra based command + let result = do --ignore-errors { cobra_active_help=0 run-external $cmd "__complete" ...$spans | complete } - let last_span = $params.last_span - let spans = $params.spans + if $result != null and $result.exit_code == 0 { + let completions = $result.stdout | lines - # Drop the last param so we can fuzzy search on it - let spans = if $fuzzy { - $spans | drop - } else { - $spans - } + # the directive is the last line + let directive = do -i { $completions | last | str replace ':' '' | into int } - # skip the first entry in the span (the command) and join the rest of the span to create __complete args - let cmd_args = ($spans | skip 1 | str join ' ') + let completions = $completions | drop | each { |it| + # the first word is the command, the rest is the description + let words = $it | split row -r '\s{1}' - # If the last span entry was empty add "" to the end of the command args - let cmd_args = if ($last_span | is-empty) or $fuzzy { - $'($cmd_args) ""' - } else { - $cmd_args - } + # If the last span contains a hypen and equals, attach it to the name + let last_span = $spans | last + let words = if ($last_span =~ '^-') and ($last_span =~ '=$') { + $words | each {|it| $"($last_span)($it)" } + } else { + $words + } - # The full command to be executed with active help disable (Nushell does not support active help) - let full_cmd = $'COBRA_ACTIVE_HELP=0 ($cmd) __complete ($cmd_args)' + {value: ($words | first | str trim), description: ($words | skip | str join ' ')} + } - # Since nushell doesn't have anything like eval, execute in a subshell - let result = (do -i { nu -c $"'($full_cmd)'" } | complete) + {completions: $completions, directive: $directive} + } else { + {completions: [], directive: -1} + } + } - # Create a record with all completion related info. - # directive and directive_str are for posterity - let stdout_lines = ($result.stdout | lines) - let directive = ($stdout_lines | last | str trim | str replace ":" "" | into int) - let completions = ($stdout_lines | drop | parse -r '([\w\-\.:\+\=\/]*)\t?(.*)' | rename value description) - let completions = if $fuzzy { - $completions | where $it.value =~ $last_span + if (not ($rest | is-empty)) { + let result = exec_complete $rest + let completions = $result.completions + let directive = $result.directive - } else { - ($completions | where {|it| $it.value | str starts-with $last_span }) - } + # Add space at the end of each completion + let completions = if $directive != $ShellCompDirectiveNoSpace { + $completions | each {|it| {value: $"($it.value) ", description: $it.description}} + } else { + $completions + } - { - directive: $directive, - completions: $completions - } - } + # Cobra returns a list of completions that are supported with this directive + # There is no way to currently support this in a nushell external completer + let completions = if $directive == $ShellCompDirectiveFilterFileExt { + [] + } else { + $completions + } - let result = (exec_complete $spans) - let result = if (not ($last_span | is-empty)) and ($result.completions | is-empty) { - exec_complete --fuzzy $spans - } else { - $result - } - - let directive = $result.directive - let completions = $result.completions - - # Add space at the end of each completion - let completions = if $directive != $ShellCompDirectiveNoSpace { - $completions | each {|it| {value: $"($it.value) ", description: $it.description}} - } else { - $completions - } - - # Cobra returns a list of completions that are supported with this directive - # There is no way to currently support this in a nushell external completer - let completions = if $directive == $ShellCompDirectiveFilterFileExt { - [] - } else { - $completions - } - - let return_val = if $last_span =~ '=' { - # if the completion is of the form -n= return flag as part of the completion so that it doesn't get replaced - $completions | each {|it| $"($last_span | split row '=' | first)=($it.value)" } - } else if $directive == $ShellCompDirectiveNoFileComp { - # Allow empty results as this will stop file completion - $completions - } else if ($completions | is-empty) or $directive == $ShellCompDirectiveError { - # Not returning null causes file completions to break - # Return null if there are no completions or ShellCompDirectiveError - null - } else { - $completions - } - - $return_val - } else { - null - } + if $directive == $ShellCompDirectiveNoFileComp { + # Allow empty results as this will stop file completion + $completions + } else if ($completions | is-empty) or $directive == $ShellCompDirectiveError { + # Not returning null causes file completions to break + # Return null if there are no completions or ShellCompDirectiveError + null + } else { + $completions + } + + if ($completions | is-empty) { + null + } else { + $completions + } + } else { + null + } } -`, name, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, +`, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) _, err := buf.WriteTo(w) From 7eac0e11ae2a70b3f5463377b7b96980fff694a3 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sat, 30 Nov 2024 13:32:05 -0800 Subject: [PATCH 18/35] Format with spaces instead of tabs --- nushell_completions.go | 172 ++++++++++++++++++++--------------------- 1 file changed, 85 insertions(+), 87 deletions(-) diff --git a/nushell_completions.go b/nushell_completions.go index 7df265d4..702f0b26 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -15,114 +15,112 @@ package cobra import ( - "bytes" - "fmt" - "io" - "os" + "bytes" + "fmt" + "io" + "os" ) func (c *Command) GenNushellCompletion(w io.Writer, includeDesc bool) error { - buf := new(bytes.Buffer) - WriteStringAndCheck(buf, fmt.Sprintf(` -# An external completer that works with any cobra based -# command line application (e.g. kubectl, minikube) + buf := new(bytes.Buffer) + WriteStringAndCheck(buf, fmt.Sprintf(` let cobra_completer = {|spans| - let ShellCompDirectiveError = %[1]d - let ShellCompDirectiveNoSpace = %[2]d - let ShellCompDirectiveNoFileComp = %[3]d - let ShellCompDirectiveFilterFileExt = %[4]d - let ShellCompDirectiveFilterDirs = %[5]d + let ShellCompDirectiveError = %[1]d + let ShellCompDirectiveNoSpace = %[2]d + let ShellCompDirectiveNoFileComp = %[3]d + let ShellCompDirectiveFilterFileExt = %[4]d + let ShellCompDirectiveFilterDirs = %[5]d - let cmd = $spans | first - let rest = $spans | skip + let cmd = $spans | first + let rest = $spans | skip - def exec_complete [ - spans: list<string> - ] { - # This will catch the stderr message related to the directive and any other errors, - # such as the command not being a cobra based command - let result = do --ignore-errors { cobra_active_help=0 run-external $cmd "__complete" ...$spans | complete } + def exec_complete [ + spans: list<string> + ] { + # This will catch the stderr message related to the directive and any other errors, + # such as the command not being a cobra based command + let result = do --ignore-errors { cobra_active_help=0 run-external $cmd "__complete" ...$spans | complete } - if $result != null and $result.exit_code == 0 { - let completions = $result.stdout | lines + if $result != null and $result.exit_code == 0 { + let completions = $result.stdout | lines - # the directive is the last line - let directive = do -i { $completions | last | str replace ':' '' | into int } + # the directive is the last line + let directive = do -i { $completions | last | str replace ':' '' | into int } - let completions = $completions | drop | each { |it| - # the first word is the command, the rest is the description - let words = $it | split row -r '\s{1}' + let completions = $completions | drop | each { |it| + # the first word is the command, the rest is the description + let words = $it | split row -r '\s{1}' - # If the last span contains a hypen and equals, attach it to the name - let last_span = $spans | last - let words = if ($last_span =~ '^-') and ($last_span =~ '=$') { - $words | each {|it| $"($last_span)($it)" } - } else { - $words - } + # If the last span contains a hypen and equals, attach it to the name + let last_span = $spans | last + let words = if ($last_span =~ '^-') and ($last_span =~ '=$') { + $words | each {|it| $"($last_span)($it)" } + } else { + $words + } - {value: ($words | first | str trim), description: ($words | skip | str join ' ')} - } + {value: ($words | first | str trim), description: ($words | skip | str join ' ')} + } - {completions: $completions, directive: $directive} - } else { - {completions: [], directive: -1} - } - } + {completions: $completions, directive: $directive} + } else { + {completions: [], directive: -1} + } + } - if (not ($rest | is-empty)) { - let result = exec_complete $rest - let completions = $result.completions - let directive = $result.directive + if (not ($rest | is-empty)) { + let result = exec_complete $rest + let completions = $result.completions + let directive = $result.directive - # Add space at the end of each completion - let completions = if $directive != $ShellCompDirectiveNoSpace { - $completions | each {|it| {value: $"($it.value) ", description: $it.description}} - } else { - $completions - } + # Add space at the end of each completion + let completions = if $directive != $ShellCompDirectiveNoSpace { + $completions | each {|it| {value: $"($it.value) ", description: $it.description}} + } else { + $completions + } - # Cobra returns a list of completions that are supported with this directive - # There is no way to currently support this in a nushell external completer - let completions = if $directive == $ShellCompDirectiveFilterFileExt { - [] - } else { - $completions - } + # Cobra returns a list of completions that are supported with this directive + # There is no way to currently support this in a nushell external completer + let completions = if $directive == $ShellCompDirectiveFilterFileExt { + [] + } else { + $completions + } - if $directive == $ShellCompDirectiveNoFileComp { - # Allow empty results as this will stop file completion - $completions - } else if ($completions | is-empty) or $directive == $ShellCompDirectiveError { - # Not returning null causes file completions to break - # Return null if there are no completions or ShellCompDirectiveError - null - } else { - $completions - } - - if ($completions | is-empty) { - null - } else { - $completions - } - } else { - null - } + if $directive == $ShellCompDirectiveNoFileComp { + # Allow empty results as this will stop file completion + $completions + } else if ($completions | is-empty) or $directive == $ShellCompDirectiveError { + # Not returning null causes file completions to break + # Return null if there are no completions or ShellCompDirectiveError + null + } else { + $completions + } + + if ($completions | is-empty) { + null + } else { + $completions + } + } else { + null + } } `, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) - _, err := buf.WriteTo(w) - return err + _, err := buf.WriteTo(w) + return err } func (c *Command) GenNushellCompletionFile(filename string, includeDesc bool) error { - outFile, err := os.Create(filename) - if err != nil { - return err - } - defer outFile.Close() + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() - return c.GenNushellCompletion(outFile, includeDesc) + return c.GenNushellCompletion(outFile, includeDesc) } From 8b4aa590bbde4d231f28e3d3fe45443c804b07bb Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sat, 30 Nov 2024 13:34:39 -0800 Subject: [PATCH 19/35] Added new directive to the list of directives for posterity. --- nushell_completions.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nushell_completions.go b/nushell_completions.go index 702f0b26..e908fc6a 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -30,6 +30,7 @@ let cobra_completer = {|spans| let ShellCompDirectiveNoFileComp = %[3]d let ShellCompDirectiveFilterFileExt = %[4]d let ShellCompDirectiveFilterDirs = %[5]d + let ShellCompDirectiveKeepOrder = %[6]d let cmd = $spans | first let rest = $spans | skip @@ -109,7 +110,7 @@ let cobra_completer = {|spans| } } `, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder)) _, err := buf.WriteTo(w) return err From 70067196037b693592732beaebbf1ae25f60bb22 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sat, 30 Nov 2024 13:57:31 -0800 Subject: [PATCH 20/35] fixing formatting --- nushell_completions.go | 32 +++++++++++++++--------------- nushell_completions_test.go | 12 +++++++++++ site/content/completions/_index.md | 22 +++++++++----------- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/nushell_completions.go b/nushell_completions.go index e908fc6a..d6cc274f 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -15,15 +15,15 @@ package cobra import ( - "bytes" - "fmt" - "io" - "os" + "bytes" + "fmt" + "io" + "os" ) func (c *Command) GenNushellCompletion(w io.Writer, includeDesc bool) error { - buf := new(bytes.Buffer) - WriteStringAndCheck(buf, fmt.Sprintf(` + buf := new(bytes.Buffer) + WriteStringAndCheck(buf, fmt.Sprintf(` let cobra_completer = {|spans| let ShellCompDirectiveError = %[1]d let ShellCompDirectiveNoSpace = %[2]d @@ -40,7 +40,7 @@ let cobra_completer = {|spans| ] { # This will catch the stderr message related to the directive and any other errors, # such as the command not being a cobra based command - let result = do --ignore-errors { cobra_active_help=0 run-external $cmd "__complete" ...$spans | complete } + let result = do --ignore-errors { COBRA_ACTIVE_HELP=0 run-external $cmd "__complete" ...$spans | complete } if $result != null and $result.exit_code == 0 { let completions = $result.stdout | lines @@ -110,18 +110,18 @@ let cobra_completer = {|spans| } } `, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder)) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder)) - _, err := buf.WriteTo(w) - return err + _, err := buf.WriteTo(w) + return err } func (c *Command) GenNushellCompletionFile(filename string, includeDesc bool) error { - outFile, err := os.Create(filename) - if err != nil { - return err - } - defer outFile.Close() + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() - return c.GenNushellCompletion(outFile, includeDesc) + return c.GenNushellCompletion(outFile, includeDesc) } diff --git a/nushell_completions_test.go b/nushell_completions_test.go index 73fedd07..1901540a 100644 --- a/nushell_completions_test.go +++ b/nushell_completions_test.go @@ -95,3 +95,15 @@ func TestFailGenNushellCompletionFile(t *testing.T) { } } } + +func TestNushellCompletionNoActiveHelp(t *testing.T) { + c := &Command{Use: "c", Run: emptyRun} + + buf := new(bytes.Buffer) + assertNoErr(t, c.GenNushellCompletion(buf, true)) + output := buf.String() + + // check that active help is being disabled + activeHelpVar := activeHelpGlobalEnvVar + check(t, output, fmt.Sprintf("%s=0", activeHelpVar)) +} diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md index 2f598c7c..f64d6e4b 100644 --- a/site/content/completions/_index.md +++ b/site/content/completions/_index.md @@ -73,21 +73,17 @@ PowerShell: Nushell: # To configure the Nushell cobra external completer for the first time: - # 1. Copy the output of the command below: - > %[1]s completion nushell - # 2. Edit the nushell config file: - > config nu - # 3. Paste above the "let-env config" line. - # 4. Change the config block's external_completer line to be - external_completer: $cobra_completer - # 5. You will need to start a new shell or for this setup to take effect. - - # If you have already setup the cobra external completer: # 1. Edit the nushell config file: > config nu - # 2. Modify the cobra_apps varible to contain this application: - > let cobra_apps = [ "othercobraapp", "%[1]s" ] - # 3. You will need to start a new shell for this setup to take effect. + # 2. Copy the completer to at the end of the file. + # 3. Add a section like the following below the cobra_completer: + $env.config.completions.external = { + enable: true + max_results: 100 + completer: $cobra_completer + } + +NOTE: This completer will work for all cobra based commands. More information can be found in the [External Completions](https://www.nushell.sh/book/custom_completions.html#custom-descriptions) section of the Nushell book. Information on setting up more than external completer can be found [Multiple completer](https://www.nushell.sh/cookbook/external_completers.html#multiple-completer) of the Nushell cookbook. `,cmd.Root().Name()), DisableFlagsInUseLine: true, From 982ba402cbbaca8d19e75d48482ebdd2bdba5e9a Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sat, 30 Nov 2024 13:59:41 -0800 Subject: [PATCH 21/35] fix tests --- nushell_completions_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/nushell_completions_test.go b/nushell_completions_test.go index 1901540a..3958a134 100644 --- a/nushell_completions_test.go +++ b/nushell_completions_test.go @@ -37,9 +37,6 @@ func TestGenNushellCompletion(t *testing.T) { buf := new(bytes.Buffer) assertNoErr(t, rootCmd.GenNushellCompletion(buf, true)) - output := buf.String() - - check(t, output, fmt.Sprintf("let cobra_apps = [\"%[1]s\"]", rootCmd.Name())) } func TestGenNushellCompletionFile(t *testing.T) { From 59726e2b0f5408cbb74dadd55e9e314d64617210 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sat, 30 Nov 2024 14:06:56 -0800 Subject: [PATCH 22/35] fixed a typo --- site/content/completions/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md index f64d6e4b..25e2ab66 100644 --- a/site/content/completions/_index.md +++ b/site/content/completions/_index.md @@ -83,7 +83,7 @@ Nushell: completer: $cobra_completer } -NOTE: This completer will work for all cobra based commands. More information can be found in the [External Completions](https://www.nushell.sh/book/custom_completions.html#custom-descriptions) section of the Nushell book. Information on setting up more than external completer can be found [Multiple completer](https://www.nushell.sh/cookbook/external_completers.html#multiple-completer) of the Nushell cookbook. +NOTE: This completer will work for all cobra based commands. More information can be found in the [External Completions](https://www.nushell.sh/book/custom_completions.html#custom-descriptions) section of the Nushell book. Information on setting up more than one external completer can be found [Multiple completer](https://www.nushell.sh/cookbook/external_completers.html#multiple-completer) of the Nushell cookbook. `,cmd.Root().Name()), DisableFlagsInUseLine: true, From 18d7a29987b12444a4de87f74faac3495316ac5c Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sat, 30 Nov 2024 14:58:44 -0800 Subject: [PATCH 23/35] more documentation tweaks --- site/content/completions/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md index 25e2ab66..13cd3fb3 100644 --- a/site/content/completions/_index.md +++ b/site/content/completions/_index.md @@ -76,14 +76,14 @@ Nushell: # 1. Edit the nushell config file: > config nu # 2. Copy the completer to at the end of the file. - # 3. Add a section like the following below the cobra_completer: + # 3. Add a section like the following below at the end of the file: $env.config.completions.external = { enable: true max_results: 100 completer: $cobra_completer } -NOTE: This completer will work for all cobra based commands. More information can be found in the [External Completions](https://www.nushell.sh/book/custom_completions.html#custom-descriptions) section of the Nushell book. Information on setting up more than one external completer can be found [Multiple completer](https://www.nushell.sh/cookbook/external_completers.html#multiple-completer) of the Nushell cookbook. +NOTE: This completer will work for all cobra based commands. More information can be found in the [External Completions](https://www.nushell.sh/book/custom_completions.html#custom-descriptions) section of the Nushell book. Information on setting up more than one external completer can be found in the [Multiple completer](https://www.nushell.sh/cookbook/external_completers.html#multiple-completer) section of the Nushell cookbook. `,cmd.Root().Name()), DisableFlagsInUseLine: true, From 2f80e0879fa87eb2f62821d92d2961b3b09059b6 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sat, 30 Nov 2024 15:01:06 -0800 Subject: [PATCH 24/35] changed from being markdown, as I don't think the docs here are markdown --- site/content/completions/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md index 13cd3fb3..5573fd82 100644 --- a/site/content/completions/_index.md +++ b/site/content/completions/_index.md @@ -83,7 +83,7 @@ Nushell: completer: $cobra_completer } -NOTE: This completer will work for all cobra based commands. More information can be found in the [External Completions](https://www.nushell.sh/book/custom_completions.html#custom-descriptions) section of the Nushell book. Information on setting up more than one external completer can be found in the [Multiple completer](https://www.nushell.sh/cookbook/external_completers.html#multiple-completer) section of the Nushell cookbook. +NOTE: This completer will work for all cobra based commands. More information can be found in the External Completions (https://www.nushell.sh/book/custom_completions.html#custom-descriptions) section of the Nushell book. Information on setting up more than one external completer can be found in the Multiple completer (https://www.nushell.sh/cookbook/external_completers.html#multiple-completer) section of the Nushell cookbook. `,cmd.Root().Name()), DisableFlagsInUseLine: true, From 1886f6baad5e45867d36c337cf0cf6c1729093b0 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sun, 1 Dec 2024 18:27:49 -0800 Subject: [PATCH 25/35] minor formatting tweak --- nushell_completions.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/nushell_completions.go b/nushell_completions.go index d6cc274f..0fd02ea5 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -76,28 +76,28 @@ let cobra_completer = {|spans| # Add space at the end of each completion let completions = if $directive != $ShellCompDirectiveNoSpace { - $completions | each {|it| {value: $"($it.value) ", description: $it.description}} + $completions | each {|it| {value: $"($it.value) ", description: $it.description}} } else { - $completions + $completions } # Cobra returns a list of completions that are supported with this directive # There is no way to currently support this in a nushell external completer let completions = if $directive == $ShellCompDirectiveFilterFileExt { - [] + [] } else { - $completions + $completions } if $directive == $ShellCompDirectiveNoFileComp { - # Allow empty results as this will stop file completion - $completions + # Allow empty results as this will stop file completion + $completions } else if ($completions | is-empty) or $directive == $ShellCompDirectiveError { - # Not returning null causes file completions to break - # Return null if there are no completions or ShellCompDirectiveError - null - } else { - $completions + # Not returning null causes file completions to break + # Return null if there are no completions or ShellCompDirectiveError + null + } else { + $completions } if ($completions | is-empty) { From ddb39920b4f1fbd51ba6fa0da663391cb8dbe438 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sun, 1 Dec 2024 18:44:56 -0800 Subject: [PATCH 26/35] More documentation work for nushell --- completions.go | 25 +++++++++---------- nushell_completions.md | 4 --- site/content/completions/_index.md | 4 ++- .../completions/nushell_completions.md | 3 +++ 4 files changed, 18 insertions(+), 18 deletions(-) delete mode 100644 nushell_completions.md create mode 100644 site/content/completions/nushell_completions.md diff --git a/completions.go b/completions.go index f6924ba7..a3d16bc2 100644 --- a/completions.go +++ b/completions.go @@ -848,21 +848,20 @@ to your powershell profile. Long: fmt.Sprintf(`Generate the autocompletion script for nushell. To configure the Nushell cobra external completer for the first time: - # 1. Copy the output of the command below: - > %[1]s completion nushell - # 2. Edit the nushell config file: - > config nu - # 3. Paste above the "let-env config" line. - # 4. Change the config block's external_completer line to be external_completer: $cobra_completer - # 5. You will need to start a new shel for this setup to take effect. - -If you have already setup the cobra external completer for other Cobra-based applications: # 1. Edit the nushell config file: > config nu - # 2. Modify the cobra_apps variable to contain this new application: - > let cobra_apps = [ "othercobraapp", "%[1]s" ] - # 3. You will need to start a new shell for this setup to take effect. -`, c.Root().Name()), + # 2. Copy the completer to at the end of the file. + # 3. Add a section like the following below at the end of the file: + $env.config.completions.external = { + enable: true + max_results: 100 + completer: $cobra_completer + } + +NOTE: This completer will work for all cobra based commands. +More information can be found in the External Completions (https://www.nushell.sh/book/custom_completions.html#custom-descriptions) section of the Nushell book. +Information on setting up more than one external completer can be found in the Multiple completer (https://www.nushell.sh/cookbook/external_completers.html#multiple-completer) section of the Nushell cookbook. +`), Args: NoArgs, ValidArgsFunction: NoFileCompletions, RunE: func(cmd *Command, args []string) error { diff --git a/nushell_completions.md b/nushell_completions.md deleted file mode 100644 index e0e94eb1..00000000 --- a/nushell_completions.md +++ /dev/null @@ -1,4 +0,0 @@ -## Generating Nushell Completions For Your cobra.Command - -Please refer to [Shell Completions](shell_completions.md) for details. - diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md index 5573fd82..8ab4ca08 100644 --- a/site/content/completions/_index.md +++ b/site/content/completions/_index.md @@ -83,7 +83,9 @@ Nushell: completer: $cobra_completer } -NOTE: This completer will work for all cobra based commands. More information can be found in the External Completions (https://www.nushell.sh/book/custom_completions.html#custom-descriptions) section of the Nushell book. Information on setting up more than one external completer can be found in the Multiple completer (https://www.nushell.sh/cookbook/external_completers.html#multiple-completer) section of the Nushell cookbook. +NOTE: This completer will work for all cobra based commands. +More information can be found in the External Completions (https://www.nushell.sh/book/custom_completions.html#custom-descriptions) section of the Nushell book. +Information on setting up more than one external completer can be found in the Multiple completer (https://www.nushell.sh/cookbook/external_completers.html#multiple-completer) section of the Nushell cookbook. `,cmd.Root().Name()), DisableFlagsInUseLine: true, diff --git a/site/content/completions/nushell_completions.md b/site/content/completions/nushell_completions.md new file mode 100644 index 00000000..3bd8065d --- /dev/null +++ b/site/content/completions/nushell_completions.md @@ -0,0 +1,3 @@ +## Generating Nushell Completions For Your cobra.Command + +Please refer to [Shell Completions](_index.md#nushell-completions) for details. From 470ca0a62845725bff62f8fd5823b477266f722c Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sun, 1 Dec 2024 20:05:18 -0800 Subject: [PATCH 27/35] Added a comment at the beginning to remain consistent with other shells. --- nushell_completions.go | 1 + 1 file changed, 1 insertion(+) diff --git a/nushell_completions.go b/nushell_completions.go index 0fd02ea5..85236525 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -23,6 +23,7 @@ import ( func (c *Command) GenNushellCompletion(w io.Writer, includeDesc bool) error { buf := new(bytes.Buffer) + WriteStringAndCheck(buf, "# nushell completion -*- shell-script -*- \n") WriteStringAndCheck(buf, fmt.Sprintf(` let cobra_completer = {|spans| let ShellCompDirectiveError = %[1]d From 93a41331ec907f11a4e1f882fa01eedaba581516 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sun, 1 Dec 2024 20:05:39 -0800 Subject: [PATCH 28/35] tmpfile handling changes --- nushell_completions_test.go | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/nushell_completions_test.go b/nushell_completions_test.go index 3958a134..d86e8ede 100644 --- a/nushell_completions_test.go +++ b/nushell_completions_test.go @@ -16,9 +16,11 @@ package cobra import ( "bytes" + "errors" "fmt" "log" "os" + "path/filepath" "testing" ) @@ -40,12 +42,12 @@ func TestGenNushellCompletion(t *testing.T) { } func TestGenNushellCompletionFile(t *testing.T) { - err := os.Mkdir("./tmp", 0o755) + tmpFile, err := os.CreateTemp("", "cobra-test") if err != nil { log.Fatal(err.Error()) } - defer os.RemoveAll("./tmp") + defer os.RemoveAll(tmpFile.Name()) rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} child := &Command{ @@ -55,18 +57,18 @@ func TestGenNushellCompletionFile(t *testing.T) { } rootCmd.AddCommand(child) - assertNoErr(t, rootCmd.GenNushellCompletionFile("./tmp/test", true)) + assertNoErr(t, rootCmd.GenNushellCompletionFile(tmpFile.Name(), true)) } func TestFailGenNushellCompletionFile(t *testing.T) { - err := os.Mkdir("./tmp", 0o755) + tmpDir, err := os.MkdirTemp("", "cobra-test") if err != nil { - log.Fatal(err.Error()) + t.Fatal(err.Error()) } - defer os.RemoveAll("./tmp") + defer os.RemoveAll(tmpDir) - f, _ := os.OpenFile("./tmp/test", os.O_CREATE, 0o400) + f, _ := os.OpenFile(filepath.Join(tmpDir, "test"), os.O_CREATE, 0400) defer f.Close() rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} @@ -77,19 +79,9 @@ func TestFailGenNushellCompletionFile(t *testing.T) { } rootCmd.AddCommand(child) - got := rootCmd.GenNushellCompletionFile("./tmp/test", true) - if got == nil { - t.Error("should raise permission denied error") - } - - if os.Getenv("MSYSTEM") == "MINGW64" { - if got.Error() != "open ./tmp/test: Access is denied." { - t.Errorf("got: %s, want: %s", got.Error(), "open ./tmp/test: Access is denied.") - } - } else { - if got.Error() != "open ./tmp/test: permission denied" { - t.Errorf("got: %s, want: %s", got.Error(), "open ./tmp/test: permission denied") - } + got := rootCmd.GenFishCompletionFile(f.Name(), false) + if !errors.Is(got, os.ErrPermission) { + t.Errorf("got: %s, want: %s", got.Error(), os.ErrPermission.Error()) } } From e0ac28fad8c28424920e93ba37695cd67d9bc514 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sun, 8 Dec 2024 19:33:48 -0800 Subject: [PATCH 29/35] fix fish reference --- nushell_completions_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nushell_completions_test.go b/nushell_completions_test.go index d86e8ede..db58cbd2 100644 --- a/nushell_completions_test.go +++ b/nushell_completions_test.go @@ -79,7 +79,7 @@ func TestFailGenNushellCompletionFile(t *testing.T) { } rootCmd.AddCommand(child) - got := rootCmd.GenFishCompletionFile(f.Name(), false) + got := rootCmd.GenNushellCompletionFile(f.Name(), false) if !errors.Is(got, os.ErrPermission) { t.Errorf("got: %s, want: %s", got.Error(), os.ErrPermission.Error()) } From 14e642ede90211776346674e1e66593b1a82364a Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sun, 8 Dec 2024 19:35:50 -0800 Subject: [PATCH 30/35] fixed bad grammar mistake --- completions.go | 2 +- site/content/completions/_index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/completions.go b/completions.go index a3d16bc2..67cee18b 100644 --- a/completions.go +++ b/completions.go @@ -850,7 +850,7 @@ to your powershell profile. To configure the Nushell cobra external completer for the first time: # 1. Edit the nushell config file: > config nu - # 2. Copy the completer to at the end of the file. + # 2. Copy the completer to the end of the file. # 3. Add a section like the following below at the end of the file: $env.config.completions.external = { enable: true diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md index 8ab4ca08..25f04fbd 100644 --- a/site/content/completions/_index.md +++ b/site/content/completions/_index.md @@ -75,7 +75,7 @@ Nushell: # To configure the Nushell cobra external completer for the first time: # 1. Edit the nushell config file: > config nu - # 2. Copy the completer to at the end of the file. + # 2. Copy the completer to the end of the file. # 3. Add a section like the following below at the end of the file: $env.config.completions.external = { enable: true From d728bbb91e1a0905f9bb8eb20b6a63f2e2e9cbba Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sun, 8 Dec 2024 19:38:47 -0800 Subject: [PATCH 31/35] Nushell instructions tweak --- completions.go | 4 ++-- site/content/completions/_index.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/completions.go b/completions.go index 67cee18b..5d67196d 100644 --- a/completions.go +++ b/completions.go @@ -850,7 +850,7 @@ to your powershell profile. To configure the Nushell cobra external completer for the first time: # 1. Edit the nushell config file: > config nu - # 2. Copy the completer to the end of the file. + # 2. Copy the output of %[1]s completion nushell to the end of the file. # 3. Add a section like the following below at the end of the file: $env.config.completions.external = { enable: true @@ -861,7 +861,7 @@ To configure the Nushell cobra external completer for the first time: NOTE: This completer will work for all cobra based commands. More information can be found in the External Completions (https://www.nushell.sh/book/custom_completions.html#custom-descriptions) section of the Nushell book. Information on setting up more than one external completer can be found in the Multiple completer (https://www.nushell.sh/cookbook/external_completers.html#multiple-completer) section of the Nushell cookbook. -`), +`, c.Root().Name()), Args: NoArgs, ValidArgsFunction: NoFileCompletions, RunE: func(cmd *Command, args []string) error { diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md index 25f04fbd..1006020b 100644 --- a/site/content/completions/_index.md +++ b/site/content/completions/_index.md @@ -75,7 +75,7 @@ Nushell: # To configure the Nushell cobra external completer for the first time: # 1. Edit the nushell config file: > config nu - # 2. Copy the completer to the end of the file. + # 2. Copy the output of %[1]s completion nushell to the end of the file. # 3. Add a section like the following below at the end of the file: $env.config.completions.external = { enable: true From 52185bed6e0016f343afd14f57bf7ed6311ec2a4 Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sun, 8 Dec 2024 19:44:45 -0800 Subject: [PATCH 32/35] tweaking extra completion instructions --- completions.go | 9 ++++++--- site/content/completions/_index.md | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/completions.go b/completions.go index 5d67196d..1e5a4f50 100644 --- a/completions.go +++ b/completions.go @@ -858,9 +858,12 @@ To configure the Nushell cobra external completer for the first time: completer: $cobra_completer } -NOTE: This completer will work for all cobra based commands. -More information can be found in the External Completions (https://www.nushell.sh/book/custom_completions.html#custom-descriptions) section of the Nushell book. -Information on setting up more than one external completer can be found in the Multiple completer (https://www.nushell.sh/cookbook/external_completers.html#multiple-completer) section of the Nushell cookbook. +This completer will work for all cobra based commands. +More information can be found in the External Completions section of the Nushell book: +https://www.nushell.sh/book/custom_completions.html#external-completions + +Information on setting up more than one external completer can be found in the Multiple completer section of the Nushell cookbook: +https://www.nushell.sh/cookbook/external_completers.html#multiple-completer `, c.Root().Name()), Args: NoArgs, ValidArgsFunction: NoFileCompletions, diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md index 1006020b..3548478f 100644 --- a/site/content/completions/_index.md +++ b/site/content/completions/_index.md @@ -83,9 +83,12 @@ Nushell: completer: $cobra_completer } -NOTE: This completer will work for all cobra based commands. -More information can be found in the External Completions (https://www.nushell.sh/book/custom_completions.html#custom-descriptions) section of the Nushell book. -Information on setting up more than one external completer can be found in the Multiple completer (https://www.nushell.sh/cookbook/external_completers.html#multiple-completer) section of the Nushell cookbook. +This completer will work for all cobra based commands. +More information can be found in the External Completions section of the Nushell book: +https://www.nushell.sh/book/custom_completions.html#external-completions + +Information on setting up more than one external completer can be found in the Multiple completer section of the Nushell cookbook: +https://www.nushell.sh/cookbook/external_completers.html#multiple-completer `,cmd.Root().Name()), DisableFlagsInUseLine: true, From 1df1dbd552ef4686e1c85afc1a74f1611bb603ec Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sun, 8 Dec 2024 20:34:38 -0800 Subject: [PATCH 33/35] cobra logging command --- nushell_completions.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/nushell_completions.go b/nushell_completions.go index 85236525..7a8962db 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -36,6 +36,15 @@ let cobra_completer = {|spans| let cmd = $spans | first let rest = $spans | skip + def cobra_log [message] { + let file = do -i {$env | get NUSHELL_COMP_DEBUG_FILE} + if $file != null { + echo $"($message)\n" | save $file --append + } + } + + cobra_log $"External Completer called for cmd ($cmd)" + def exec_complete [ spans: list<string> ] { From da1bab975725502baebef6f04066721f8e52b1cb Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Wed, 11 Dec 2024 17:22:41 -0800 Subject: [PATCH 34/35] Fixed the ShellCompDirectiveNoFileComp case --- nushell_completions.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/nushell_completions.go b/nushell_completions.go index 7a8962db..d1740d1d 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -109,12 +109,6 @@ let cobra_completer = {|spans| } else { $completions } - - if ($completions | is-empty) { - null - } else { - $completions - } } else { null } From ae37156f634973d59186b69de0623c866f77415b Mon Sep 17 00:00:00 2001 From: Jack Wright <ayax79@gmail.com> Date: Sun, 29 Dec 2024 13:23:29 -0800 Subject: [PATCH 35/35] Removing unused includeDesc parameter --- completions.go | 2 +- nushell_completions.go | 6 +++--- nushell_completions_test.go | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/completions.go b/completions.go index 1e5a4f50..9bee0a6c 100644 --- a/completions.go +++ b/completions.go @@ -868,7 +868,7 @@ https://www.nushell.sh/cookbook/external_completers.html#multiple-completer Args: NoArgs, ValidArgsFunction: NoFileCompletions, RunE: func(cmd *Command, args []string) error { - return cmd.Root().GenNushellCompletion(out, !noDesc) + return cmd.Root().GenNushellCompletion(out) }, } if haveNoDescFlag { diff --git a/nushell_completions.go b/nushell_completions.go index d1740d1d..830ffe4d 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -21,7 +21,7 @@ import ( "os" ) -func (c *Command) GenNushellCompletion(w io.Writer, includeDesc bool) error { +func (c *Command) GenNushellCompletion(w io.Writer) error { buf := new(bytes.Buffer) WriteStringAndCheck(buf, "# nushell completion -*- shell-script -*- \n") WriteStringAndCheck(buf, fmt.Sprintf(` @@ -120,12 +120,12 @@ let cobra_completer = {|spans| return err } -func (c *Command) GenNushellCompletionFile(filename string, includeDesc bool) error { +func (c *Command) GenNushellCompletionFile(filename string) error { outFile, err := os.Create(filename) if err != nil { return err } defer outFile.Close() - return c.GenNushellCompletion(outFile, includeDesc) + return c.GenNushellCompletion(outFile) } diff --git a/nushell_completions_test.go b/nushell_completions_test.go index db58cbd2..41a98f46 100644 --- a/nushell_completions_test.go +++ b/nushell_completions_test.go @@ -38,7 +38,7 @@ func TestGenNushellCompletion(t *testing.T) { rootCmd.AddCommand(getCmd) buf := new(bytes.Buffer) - assertNoErr(t, rootCmd.GenNushellCompletion(buf, true)) + assertNoErr(t, rootCmd.GenNushellCompletion(buf)) } func TestGenNushellCompletionFile(t *testing.T) { @@ -57,7 +57,7 @@ func TestGenNushellCompletionFile(t *testing.T) { } rootCmd.AddCommand(child) - assertNoErr(t, rootCmd.GenNushellCompletionFile(tmpFile.Name(), true)) + assertNoErr(t, rootCmd.GenNushellCompletionFile(tmpFile.Name())) } func TestFailGenNushellCompletionFile(t *testing.T) { @@ -79,7 +79,7 @@ func TestFailGenNushellCompletionFile(t *testing.T) { } rootCmd.AddCommand(child) - got := rootCmd.GenNushellCompletionFile(f.Name(), false) + got := rootCmd.GenNushellCompletionFile(f.Name()) if !errors.Is(got, os.ErrPermission) { t.Errorf("got: %s, want: %s", got.Error(), os.ErrPermission.Error()) } @@ -89,7 +89,7 @@ func TestNushellCompletionNoActiveHelp(t *testing.T) { c := &Command{Use: "c", Run: emptyRun} buf := new(bytes.Buffer) - assertNoErr(t, c.GenNushellCompletion(buf, true)) + assertNoErr(t, c.GenNushellCompletion(buf)) output := buf.String() // check that active help is being disabled