2022-11-12 02:05:24 +00:00
|
|
|
// 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"
|
2022-11-27 21:46:13 +00:00
|
|
|
"fmt"
|
2022-11-12 02:05:24 +00:00
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
)
|
|
|
|
|
2022-11-28 21:39:12 +00:00
|
|
|
func (c *Command) GenNushellCompletion(w io.Writer, includeDesc bool) error {
|
2022-11-12 02:05:24 +00:00
|
|
|
buf := new(bytes.Buffer)
|
2022-11-28 21:39:12 +00:00
|
|
|
name := c.Name()
|
2022-11-27 21:46:13 +00:00
|
|
|
WriteStringAndCheck(buf, fmt.Sprintf(`
|
2022-11-28 21:39:12 +00:00
|
|
|
# A list of cobra apps that completion will be attempted for.
|
2022-11-27 23:06:59 +00:00
|
|
|
# Add new apps to this list to enable completion for them.
|
|
|
|
let cobra_apps = ["%[1]s"]
|
|
|
|
|
2022-11-28 21:39:12 +00:00
|
|
|
# An external completer that works with any cobra based
|
2022-11-26 22:39:29 +00:00
|
|
|
# command line application (e.g. kubectl, minikube)
|
2022-11-27 21:46:13 +00:00
|
|
|
let cobra_completer = {|spans|
|
2022-11-26 22:39:29 +00:00
|
|
|
let cmd = $spans.0
|
|
|
|
|
2022-11-28 21:39:12 +00:00
|
|
|
if not ($cobra_apps | where $cmd =~ $it | is-empty) {
|
2022-11-27 23:06:59 +00:00
|
|
|
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)
|
2022-11-26 22:39:29 +00:00
|
|
|
|
2022-11-27 23:06:59 +00:00
|
|
|
# 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 ' ')
|
2022-11-26 22:39:29 +00:00
|
|
|
|
2022-11-27 23:06:59 +00:00
|
|
|
# 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
|
|
|
|
}
|
2022-11-26 22:39:29 +00:00
|
|
|
|
2022-11-27 23:06:59 +00:00
|
|
|
# The full command to be executed with active help disable (Nushell does not support active help)
|
2022-11-28 21:39:12 +00:00
|
|
|
let full_cmd = $'%[7]s=0 ($cmd) __complete ($cmd_args)'
|
2022-11-26 22:39:29 +00:00
|
|
|
|
2022-11-27 23:06:59 +00:00
|
|
|
# Since nushell doesn't have anything like eval, execute in a subshell
|
|
|
|
let result = (do -i { nu -c $"'($full_cmd)'" } | complete)
|
2022-11-26 22:39:29 +00:00
|
|
|
|
2022-11-27 23:06:59 +00:00
|
|
|
# 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)
|
2022-11-26 22:39:29 +00:00
|
|
|
|
2022-11-28 21:39:12 +00:00
|
|
|
# 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
|
|
|
|
}
|
|
|
|
|
2022-11-27 23:06:59 +00:00
|
|
|
# Add space at the end of each completion
|
|
|
|
let completions = if $directive != $ShellCompDirectiveNoSpace {
|
|
|
|
($completions | each {|it| {value: $"($it.value) ", description: $it.description}})
|
|
|
|
} else {
|
|
|
|
$completions
|
|
|
|
}
|
|
|
|
|
2022-11-28 21:39:12 +00:00
|
|
|
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)" }
|
2022-11-27 23:06:59 +00:00
|
|
|
} 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
|
|
|
|
}
|
2022-11-27 21:46:13 +00:00
|
|
|
} else {
|
2022-11-27 23:06:59 +00:00
|
|
|
null
|
2022-11-27 21:46:13 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-28 21:39:12 +00:00
|
|
|
`, name, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
|
|
|
|
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name)))
|
2022-11-12 02:05:24 +00:00
|
|
|
|
|
|
|
_, err := buf.WriteTo(w)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-11-28 21:39:12 +00:00
|
|
|
func (c *Command) GenNushellCompletionFile(filename string, includeDesc bool) error {
|
2022-11-12 02:05:24 +00:00
|
|
|
outFile, err := os.Create(filename)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer outFile.Close()
|
|
|
|
|
2022-11-28 21:39:12 +00:00
|
|
|
return c.GenNushellCompletion(outFile, includeDesc)
|
2022-11-12 02:05:24 +00:00
|
|
|
}
|