mirror of https://github.com/spf13/cobra.git
rewriting nushell implementation
This commit is contained in:
parent
29af015b57
commit
e7abbf39a3
|
@ -23,105 +23,57 @@ import (
|
||||||
|
|
||||||
func (c *Command) GenNushellCompletion(w io.Writer, includeDesc bool) 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.
|
|
||||||
# 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
|
# 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 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 cmd = $spans | first
|
||||||
let ShellCompDirectiveError = %[2]d
|
let rest = $spans | skip
|
||||||
let ShellCompDirectiveNoSpace = %[3]d
|
|
||||||
let ShellCompDirectiveNoFileComp = %[4]d
|
|
||||||
let ShellCompDirectiveFilterFileExt = %[5]d
|
|
||||||
let ShellCompDirectiveFilterDirs = %[6]d
|
|
||||||
let last_span = ($spans | last | str trim)
|
|
||||||
|
|
||||||
def exec_complete [
|
def exec_complete [
|
||||||
--fuzzy,
|
spans: list<string>
|
||||||
spans: list
|
|
||||||
] {
|
] {
|
||||||
let params = {
|
# This will catch the stderr message related to the directive and any other errors,
|
||||||
last_span: ($spans | last | str trim),
|
# such as the command not being a cobra based command
|
||||||
spans: $spans
|
let result = do --ignore-errors { cobra_active_help=0 run-external $cmd "__complete" ...$spans | complete }
|
||||||
}
|
|
||||||
# If there is an equals in the last span
|
if $result != null and $result.exit_code == 0 {
|
||||||
# parse the span into two
|
let completions = $result.stdout | lines
|
||||||
let params = if $last_span =~ '=' {
|
|
||||||
let split = ($last_span | split row '=')
|
# the directive is the last line
|
||||||
if ($split | length) > 1 {
|
let directive = do -i { $completions | last | str replace ':' '' | into int }
|
||||||
{
|
|
||||||
last_span: ($split | last),
|
let completions = $completions | drop | each { |it|
|
||||||
spans: ($spans | drop | append ($split | first) | append ($split | last))
|
# 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 {
|
} else {
|
||||||
{
|
$words
|
||||||
last_span: '',
|
|
||||||
spans: ($spans | drop | append ($split | first) | append '')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{value: ($words | first | str trim), description: ($words | skip | str join ' ')}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{completions: $completions, directive: $directive}
|
||||||
} else {
|
} else {
|
||||||
$params
|
{completions: [], directive: -1}
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = (exec_complete $spans)
|
if (not ($rest | is-empty)) {
|
||||||
let result = if (not ($last_span | is-empty)) and ($result.completions | is-empty) {
|
let result = exec_complete $rest
|
||||||
exec_complete --fuzzy $spans
|
|
||||||
} else {
|
|
||||||
$result
|
|
||||||
}
|
|
||||||
|
|
||||||
let directive = $result.directive
|
|
||||||
let completions = $result.completions
|
let completions = $result.completions
|
||||||
|
let directive = $result.directive
|
||||||
|
|
||||||
# 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 {
|
||||||
|
@ -138,10 +90,7 @@ let cobra_completer = {|spans|
|
||||||
$completions
|
$completions
|
||||||
}
|
}
|
||||||
|
|
||||||
let return_val = if $last_span =~ '=' {
|
if $directive == $ShellCompDirectiveNoFileComp {
|
||||||
# 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
|
# Allow empty results as this will stop file completion
|
||||||
$completions
|
$completions
|
||||||
} else if ($completions | is-empty) or $directive == $ShellCompDirectiveError {
|
} else if ($completions | is-empty) or $directive == $ShellCompDirectiveError {
|
||||||
|
@ -152,12 +101,16 @@ let cobra_completer = {|spans|
|
||||||
$completions
|
$completions
|
||||||
}
|
}
|
||||||
|
|
||||||
$return_val
|
if ($completions | is-empty) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
$completions
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`, name, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
|
`, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
|
||||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
|
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
|
||||||
|
|
||||||
_, err := buf.WriteTo(w)
|
_, err := buf.WriteTo(w)
|
||||||
|
|
Loading…
Reference in New Issue