Incorporating pull request feedback

- Fixing completion on full paths
- Fixing completion with equals in flags
- Fixing fuzzy search
- Typos
This commit is contained in:
Jack Wright 2022-11-28 13:39:12 -08:00
parent 95f2d8e38a
commit 4ad4930a12
4 changed files with 34 additions and 46 deletions

View file

@ -809,39 +809,26 @@ to your powershell profile.
Short: fmt.Sprintf(shortDesc, "nushell"), Short: fmt.Sprintf(shortDesc, "nushell"),
Long: fmt.Sprintf(`Generate the autocompletion script for 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. Copy the output of the command below:
> %[1]s completion nushell > %[1]s completion nushell
# 2. Edit the nushell config file: # 2. Edit the nushell config file:
> config nu > config nu
# 3. Paste above the "let-env config" line. # 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. # 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: # 1. Edit the nushell config file:
> config nu > config nu
# 2. Modify the cobra_apps varible to contain this application: # 2. Modify the cobra_apps varible to contain this application:
> let cobra_apps = [ "othercobraapp", "%[1]s" ] > let cobra_apps = [ "othercobraapp", "%[1]s" ]
# 3. You will need to start a new shell for this setup to take effect.
# 3. You will need to start a new shell or for this setup to take effect.
`, c.Root().Name()), `, c.Root().Name()),
Args: NoArgs, Args: NoArgs,
ValidArgsFunction: NoFileCompletions, ValidArgsFunction: NoFileCompletions,
RunE: func(cmd *Command, args []string) error { RunE: func(cmd *Command, args []string) error {
if noDesc { return cmd.Root().GenNushellCompletion(out, !noDesc)
return cmd.Root().GenPowerShellCompletion(out)
}
return cmd.Root().GenPowerShellCompletionWithDesc(out)
}, },
} }
if haveNoDescFlag { if haveNoDescFlag {

View file

@ -21,20 +21,20 @@ import (
"os" "os"
) )
func (c *Command) GenNushellCompletion(w io.Writer) error { func (c *Command) GenNushellCompletion(w io.Writer, includeDesc bool) error {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
name := c.Name()
WriteStringAndCheck(buf, fmt.Sprintf(` WriteStringAndCheck(buf, fmt.Sprintf(`
# A list of cobra apps that completion will be attempted for.
# A list of cobra that completion will be attempted for.
# Add new apps to this list to enable completion for them. # Add new apps to this list to enable completion for them.
let cobra_apps = ["%[1]s"] 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) # command line application (e.g. kubectl, minikube)
let cobra_completer = {|spans| let cobra_completer = {|spans|
let cmd = $spans.0 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 ShellCompDirectiveError = %[2]d
let ShellCompDirectiveNoSpace = %[3]d let ShellCompDirectiveNoSpace = %[3]d
let ShellCompDirectiveNoFileComp = %[4]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) # 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 # Since nushell doesn't have anything like eval, execute in a subshell
let result = (do -i { nu -c $"'($full_cmd)'" } | complete) 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 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)
# 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 # Add space at the end of each completion
let completions = if $directive != $ShellCompDirectiveNoSpace { let completions = if $directive != $ShellCompDirectiveNoSpace {
($completions | each {|it| {value: $"($it.value) ", description: $it.description}}) ($completions | each {|it| {value: $"($it.value) ", description: $it.description}})
@ -72,9 +80,9 @@ let cobra_completer = {|spans|
$completions $completions
} }
if $last_span =~ '=$' { if $last_span =~ '=' {
# return flag as part of the completion so that it doesn't get replaced # 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)($it.value)" } $completions | each {|it| $"($last_span | split row '=' | first)=($it.value)" }
} else if $directive == $ShellCompDirectiveNoFileComp { } else if $directive == $ShellCompDirectiveNoFileComp {
# Allow empty results as this will stop file completion # Allow empty results as this will stop file completion
$completions $completions
@ -89,19 +97,19 @@ let cobra_completer = {|spans|
null null
} }
} }
`, c.Name(), ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, `, name, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name)))
_, err := buf.WriteTo(w) _, err := buf.WriteTo(w)
return err return err
} }
func (c *Command) GenNushellCompletionFile(filename string) error { func (c *Command) GenNushellCompletionFile(filename string, includeDesc bool) error {
outFile, err := os.Create(filename) outFile, err := os.Create(filename)
if err != nil { if err != nil {
return err return err
} }
defer outFile.Close() defer outFile.Close()
return c.GenNushellCompletion(outFile) return c.GenNushellCompletion(outFile, includeDesc)
} }

View file

@ -16,6 +16,7 @@ package cobra
import ( import (
"bytes" "bytes"
"fmt"
"log" "log"
"os" "os"
"testing" "testing"
@ -35,10 +36,10 @@ func TestGenNushellCompletion(t *testing.T) {
rootCmd.AddCommand(getCmd) rootCmd.AddCommand(getCmd)
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
assertNoErr(t, rootCmd.GenNushellCompletion(buf)) assertNoErr(t, rootCmd.GenNushellCompletion(buf, true))
output := buf.String() 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) { func TestGenNushellCompletionFile(t *testing.T) {
@ -57,7 +58,7 @@ func TestGenNushellCompletionFile(t *testing.T) {
} }
rootCmd.AddCommand(child) rootCmd.AddCommand(child)
assertNoErr(t, rootCmd.GenNushellCompletionFile("./tmp/test")) assertNoErr(t, rootCmd.GenNushellCompletionFile("./tmp/test", true))
} }
func TestFailGenNushellCompletionFile(t *testing.T) { func TestFailGenNushellCompletionFile(t *testing.T) {
@ -79,7 +80,7 @@ func TestFailGenNushellCompletionFile(t *testing.T) {
} }
rootCmd.AddCommand(child) rootCmd.AddCommand(child)
got := rootCmd.GenNushellCompletionFile("./tmp/test") got := rootCmd.GenNushellCompletionFile("./tmp/test", true)
if got == nil { if got == nil {
t.Error("should raise permission denied error") t.Error("should raise permission denied error")
} }

View file

@ -72,29 +72,21 @@ PowerShell:
Nushell: 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. Copy the output of the command below:
> %[1]s completion nushell > %[1]s completion nushell
# 2. Edit the nushell config file: # 2. Edit the nushell config file:
> config nu > config nu
# 3. Paste above the "let-env config" line. # 3. Paste above the "let-env config" line.
# 4. Change the config block's external_completer line to be # 4. Change the config block's external_completer line to be
external_completer: $cobra_completer 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 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: # 1. Edit the nushell config file:
> config nu > config nu
# 2. Modify the cobra_apps varible to contain this application: # 2. Modify the cobra_apps varible to contain this application:
> let cobra_apps = [ "othercobraapp", "%[1]s" ] > let cobra_apps = [ "othercobraapp", "%[1]s" ]
# 3. You will need to start a new shell for this setup to take effect. # 3. You will need to start a new shell for this setup to take effect.
`,cmd.Root().Name()), `,cmd.Root().Name()),