mirror of
https://github.com/spf13/cobra
synced 2024-11-24 22:57:12 +00:00
Add error handling to GenBashCompletion
Since the switch from *bytes.Buffer to io.Writer, errors can no longer be ignored. Also makes the reuse of GenBashCompletion in GenBashCompletionFile without a buffer treat errors properly again.
This commit is contained in:
parent
a5ff2f28ab
commit
e0479ff7a7
1 changed files with 145 additions and 55 deletions
|
@ -16,8 +16,8 @@ const (
|
||||||
BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir"
|
BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir"
|
||||||
)
|
)
|
||||||
|
|
||||||
func preamble(out io.Writer) {
|
func preamble(out io.Writer) error {
|
||||||
fmt.Fprintf(out, `#!/bin/bash
|
_, err := fmt.Fprintf(out, `#!/bin/bash
|
||||||
|
|
||||||
__debug()
|
__debug()
|
||||||
{
|
{
|
||||||
|
@ -205,12 +205,16 @@ __handle_word()
|
||||||
}
|
}
|
||||||
|
|
||||||
`)
|
`)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func postscript(w io.Writer, name string) {
|
func postscript(w io.Writer, name string) error {
|
||||||
name = strings.Replace(name, ":", "__", -1)
|
name = strings.Replace(name, ":", "__", -1)
|
||||||
fmt.Fprintf(w, "__start_%s()\n", name)
|
_, err := fmt.Fprintf(w, "__start_%s()\n", name)
|
||||||
fmt.Fprintf(w, `{
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = fmt.Fprintf(w, `{
|
||||||
local cur prev words cword
|
local cur prev words cword
|
||||||
declare -A flaghash
|
declare -A flaghash
|
||||||
if declare -F _init_completion >/dev/null 2>&1; then
|
if declare -F _init_completion >/dev/null 2>&1; then
|
||||||
|
@ -234,55 +238,77 @@ func postscript(w io.Writer, name string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
`, name)
|
`, name)
|
||||||
fmt.Fprintf(w, `if [[ $(type -t compopt) = "builtin" ]]; then
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = fmt.Fprintf(w, `if [[ $(type -t compopt) = "builtin" ]]; then
|
||||||
complete -o default -F __start_%s %s
|
complete -o default -F __start_%s %s
|
||||||
else
|
else
|
||||||
complete -o default -o nospace -F __start_%s %s
|
complete -o default -o nospace -F __start_%s %s
|
||||||
fi
|
fi
|
||||||
|
|
||||||
`, name, name, name, name)
|
`, name, name, name, name)
|
||||||
fmt.Fprintf(w, "# ex: ts=4 sw=4 et filetype=sh\n")
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = fmt.Fprintf(w, "# ex: ts=4 sw=4 et filetype=sh\n")
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeCommands(cmd *Command, w io.Writer) {
|
func writeCommands(cmd *Command, w io.Writer) error {
|
||||||
fmt.Fprintf(w, " commands=()\n")
|
if _, err := fmt.Fprintf(w, " commands=()\n"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
for _, c := range cmd.Commands() {
|
for _, c := range cmd.Commands() {
|
||||||
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, " commands+=(%q)\n", c.Name())
|
if _, err := fmt.Fprintf(w, " commands+=(%q)\n", c.Name()); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "\n")
|
}
|
||||||
|
_, err := fmt.Fprintf(w, "\n")
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeFlagHandler(name string, annotations map[string][]string, w io.Writer) {
|
func writeFlagHandler(name string, annotations map[string][]string, w io.Writer) error {
|
||||||
for key, value := range annotations {
|
for key, value := range annotations {
|
||||||
switch key {
|
switch key {
|
||||||
case BashCompFilenameExt:
|
case BashCompFilenameExt:
|
||||||
fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name)
|
_, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if len(value) > 0 {
|
if len(value) > 0 {
|
||||||
ext := "__handle_filename_extension_flag " + strings.Join(value, "|")
|
ext := "__handle_filename_extension_flag " + strings.Join(value, "|")
|
||||||
fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
||||||
} else {
|
} else {
|
||||||
ext := "_filedir"
|
ext := "_filedir"
|
||||||
fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
case BashCompSubdirsInDir:
|
case BashCompSubdirsInDir:
|
||||||
fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name)
|
_, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name)
|
||||||
|
|
||||||
if len(value) == 1 {
|
if len(value) == 1 {
|
||||||
ext := "__handle_subdirs_in_dir_flag " + value[0]
|
ext := "__handle_subdirs_in_dir_flag " + value[0]
|
||||||
fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
||||||
} else {
|
} else {
|
||||||
ext := "_filedir -d"
|
ext := "_filedir -d"
|
||||||
fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeShortFlag(flag *pflag.Flag, w io.Writer) {
|
func writeShortFlag(flag *pflag.Flag, w io.Writer) error {
|
||||||
b := (flag.Value.Type() == "bool")
|
b := (flag.Value.Type() == "bool")
|
||||||
name := flag.Shorthand
|
name := flag.Shorthand
|
||||||
format := " "
|
format := " "
|
||||||
|
@ -290,11 +316,13 @@ func writeShortFlag(flag *pflag.Flag, w io.Writer) {
|
||||||
format += "two_word_"
|
format += "two_word_"
|
||||||
}
|
}
|
||||||
format += "flags+=(\"-%s\")\n"
|
format += "flags+=(\"-%s\")\n"
|
||||||
fmt.Fprintf(w, format, name)
|
if _, err := fmt.Fprintf(w, format, name); err != nil {
|
||||||
writeFlagHandler("-"+name, flag.Annotations, w)
|
return err
|
||||||
|
}
|
||||||
|
return writeFlagHandler("-"+name, flag.Annotations, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeFlag(flag *pflag.Flag, w io.Writer) {
|
func writeFlag(flag *pflag.Flag, w io.Writer) error {
|
||||||
b := (flag.Value.Type() == "bool")
|
b := (flag.Value.Type() == "bool")
|
||||||
name := flag.Name
|
name := flag.Name
|
||||||
format := " flags+=(\"--%s"
|
format := " flags+=(\"--%s"
|
||||||
|
@ -302,36 +330,64 @@ func writeFlag(flag *pflag.Flag, w io.Writer) {
|
||||||
format += "="
|
format += "="
|
||||||
}
|
}
|
||||||
format += "\")\n"
|
format += "\")\n"
|
||||||
fmt.Fprintf(w, format, name)
|
if _, err := fmt.Fprintf(w, format, name); err != nil {
|
||||||
writeFlagHandler("--"+name, flag.Annotations, w)
|
return err
|
||||||
|
}
|
||||||
|
return writeFlagHandler("--"+name, flag.Annotations, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeFlags(cmd *Command, w io.Writer) {
|
func writeFlags(cmd *Command, w io.Writer) error {
|
||||||
fmt.Fprintf(w, ` flags=()
|
_, err := fmt.Fprintf(w, ` flags=()
|
||||||
two_word_flags=()
|
two_word_flags=()
|
||||||
flags_with_completion=()
|
flags_with_completion=()
|
||||||
flags_completion=()
|
flags_completion=()
|
||||||
|
|
||||||
`)
|
`)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var visitErr error
|
||||||
cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
||||||
writeFlag(flag, w)
|
if err := writeFlag(flag, w); err != nil {
|
||||||
|
visitErr = err
|
||||||
|
return
|
||||||
|
}
|
||||||
if len(flag.Shorthand) > 0 {
|
if len(flag.Shorthand) > 0 {
|
||||||
writeShortFlag(flag, w)
|
if err := writeShortFlag(flag, w); err != nil {
|
||||||
|
visitErr = err
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if visitErr != nil {
|
||||||
|
return visitErr
|
||||||
|
}
|
||||||
cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
||||||
writeFlag(flag, w)
|
if err := writeFlag(flag, w); err != nil {
|
||||||
|
visitErr = err
|
||||||
|
return
|
||||||
|
}
|
||||||
if len(flag.Shorthand) > 0 {
|
if len(flag.Shorthand) > 0 {
|
||||||
writeShortFlag(flag, w)
|
if err := writeShortFlag(flag, w); err != nil {
|
||||||
|
visitErr = err
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if visitErr != nil {
|
||||||
fmt.Fprintf(w, "\n")
|
return visitErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeRequiredFlag(cmd *Command, w io.Writer) {
|
_, err = fmt.Fprintf(w, "\n")
|
||||||
fmt.Fprintf(w, " must_have_one_flag=()\n")
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeRequiredFlag(cmd *Command, w io.Writer) error {
|
||||||
|
if _, err := fmt.Fprintf(w, " must_have_one_flag=()\n"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
flags := cmd.NonInheritedFlags()
|
flags := cmd.NonInheritedFlags()
|
||||||
|
var visitErr error
|
||||||
flags.VisitAll(func(flag *pflag.Flag) {
|
flags.VisitAll(func(flag *pflag.Flag) {
|
||||||
for key := range flag.Annotations {
|
for key := range flag.Annotations {
|
||||||
switch key {
|
switch key {
|
||||||
|
@ -342,50 +398,85 @@ func writeRequiredFlag(cmd *Command, w io.Writer) {
|
||||||
format += "="
|
format += "="
|
||||||
}
|
}
|
||||||
format += "\")\n"
|
format += "\")\n"
|
||||||
fmt.Fprintf(w, format, flag.Name)
|
if _, err := fmt.Fprintf(w, format, flag.Name); err != nil {
|
||||||
|
visitErr = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if len(flag.Shorthand) > 0 {
|
if len(flag.Shorthand) > 0 {
|
||||||
fmt.Fprintf(w, " must_have_one_flag+=(\"-%s\")\n", flag.Shorthand)
|
if _, err := fmt.Fprintf(w, " must_have_one_flag+=(\"-%s\")\n", flag.Shorthand); err != nil {
|
||||||
|
visitErr = err
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
return visitErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeRequiredNoun(cmd *Command, w io.Writer) {
|
func writeRequiredNoun(cmd *Command, w io.Writer) error {
|
||||||
fmt.Fprintf(w, " must_have_one_noun=()\n")
|
if _, err := fmt.Fprintf(w, " must_have_one_noun=()\n"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
sort.Sort(sort.StringSlice(cmd.ValidArgs))
|
sort.Sort(sort.StringSlice(cmd.ValidArgs))
|
||||||
for _, value := range cmd.ValidArgs {
|
for _, value := range cmd.ValidArgs {
|
||||||
fmt.Fprintf(w, " must_have_one_noun+=(%q)\n", value)
|
if _, err := fmt.Fprintf(w, " must_have_one_noun+=(%q)\n", value); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func gen(cmd *Command, w io.Writer) {
|
func gen(cmd *Command, w io.Writer) error {
|
||||||
for _, c := range cmd.Commands() {
|
for _, c := range cmd.Commands() {
|
||||||
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
gen(c, w)
|
if err := gen(c, w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
commandName := cmd.CommandPath()
|
commandName := cmd.CommandPath()
|
||||||
commandName = strings.Replace(commandName, " ", "_", -1)
|
commandName = strings.Replace(commandName, " ", "_", -1)
|
||||||
commandName = strings.Replace(commandName, ":", "__", -1)
|
commandName = strings.Replace(commandName, ":", "__", -1)
|
||||||
fmt.Fprintf(w, "_%s()\n{\n", commandName)
|
if _, err := fmt.Fprintf(w, "_%s()\n{\n", commandName); err != nil {
|
||||||
fmt.Fprintf(w, " last_command=%q\n", commandName)
|
return err
|
||||||
writeCommands(cmd, w)
|
}
|
||||||
writeFlags(cmd, w)
|
if _, err := fmt.Fprintf(w, " last_command=%q\n", commandName); err != nil {
|
||||||
writeRequiredFlag(cmd, w)
|
return err
|
||||||
writeRequiredNoun(cmd, w)
|
}
|
||||||
fmt.Fprintf(w, "}\n\n")
|
if err := writeCommands(cmd, w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := writeFlags(cmd, w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := writeRequiredFlag(cmd, w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := writeRequiredNoun(cmd, w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := fmt.Fprintf(w, "}\n\n"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Command) GenBashCompletion(w io.Writer) {
|
func (cmd *Command) GenBashCompletion(w io.Writer) error {
|
||||||
preamble(w)
|
if err := preamble(w); err != nil {
|
||||||
if len(cmd.BashCompletionFunction) > 0 {
|
return err
|
||||||
fmt.Fprintf(w, "%s\n", cmd.BashCompletionFunction)
|
|
||||||
}
|
}
|
||||||
gen(cmd, w)
|
if len(cmd.BashCompletionFunction) > 0 {
|
||||||
postscript(w, cmd.Name())
|
if _, err := fmt.Fprintf(w, "%s\n", cmd.BashCompletionFunction); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := gen(cmd, w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return postscript(w, cmd.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Command) GenBashCompletionFile(filename string) error {
|
func (cmd *Command) GenBashCompletionFile(filename string) error {
|
||||||
|
@ -395,8 +486,7 @@ func (cmd *Command) GenBashCompletionFile(filename string) error {
|
||||||
}
|
}
|
||||||
defer outFile.Close()
|
defer outFile.Close()
|
||||||
|
|
||||||
cmd.GenBashCompletion(outFile)
|
return cmd.GenBashCompletion(outFile)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists.
|
// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists.
|
||||||
|
|
Loading…
Reference in a new issue