From 4ad4930a12843bc131467a13c82f72099b6ce371 Mon Sep 17 00:00:00 2001 From: Jack Wright Date: Mon, 28 Nov 2022 13:39:12 -0800 Subject: [PATCH] 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 +++++---- shell_completions.md | 12 ++---------- 4 files changed, 34 insertions(+), 46 deletions(-) diff --git a/completions.go b/completions.go index 5e6e80d4..4c86d0af 100644 --- a/completions.go +++ b/completions.go @@ -809,39 +809,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/shell_completions.md b/shell_completions.md index 89198cc4..48317664 100644 --- a/shell_completions.md +++ b/shell_completions.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()),