mirror of
https://github.com/spf13/cobra
synced 2024-11-24 14:47:12 +00:00
Merge pull request #215 from mvdan/interfacer
Replace *bytes.Buffer with io.Writer
This commit is contained in:
commit
c82a0ceef8
1 changed files with 146 additions and 63 deletions
|
@ -1,8 +1,8 @@
|
|||
package cobra
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
@ -16,8 +16,8 @@ const (
|
|||
BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir"
|
||||
)
|
||||
|
||||
func preamble(out *bytes.Buffer) {
|
||||
fmt.Fprintf(out, `#!/bin/bash
|
||||
func preamble(out io.Writer) error {
|
||||
_, err := fmt.Fprintf(out, `#!/bin/bash
|
||||
|
||||
__debug()
|
||||
{
|
||||
|
@ -205,12 +205,16 @@ __handle_word()
|
|||
}
|
||||
|
||||
`)
|
||||
return err
|
||||
}
|
||||
|
||||
func postscript(out *bytes.Buffer, name string) {
|
||||
func postscript(w io.Writer, name string) error {
|
||||
name = strings.Replace(name, ":", "__", -1)
|
||||
fmt.Fprintf(out, "__start_%s()\n", name)
|
||||
fmt.Fprintf(out, `{
|
||||
_, err := fmt.Fprintf(w, "__start_%s()\n", name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = fmt.Fprintf(w, `{
|
||||
local cur prev words cword
|
||||
declare -A flaghash
|
||||
if declare -F _init_completion >/dev/null 2>&1; then
|
||||
|
@ -234,55 +238,77 @@ func postscript(out *bytes.Buffer, name string) {
|
|||
}
|
||||
|
||||
`, name)
|
||||
fmt.Fprintf(out, `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
|
||||
else
|
||||
complete -o default -o nospace -F __start_%s %s
|
||||
fi
|
||||
|
||||
`, name, name, name, name)
|
||||
fmt.Fprintf(out, "# 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, out *bytes.Buffer) {
|
||||
fmt.Fprintf(out, " commands=()\n")
|
||||
func writeCommands(cmd *Command, w io.Writer) error {
|
||||
if _, err := fmt.Fprintf(w, " commands=()\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, c := range cmd.Commands() {
|
||||
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(out, " commands+=(%q)\n", c.Name())
|
||||
if _, err := fmt.Fprintf(w, " commands+=(%q)\n", c.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(out, "\n")
|
||||
}
|
||||
_, err := fmt.Fprintf(w, "\n")
|
||||
return err
|
||||
}
|
||||
|
||||
func writeFlagHandler(name string, annotations map[string][]string, out *bytes.Buffer) {
|
||||
func writeFlagHandler(name string, annotations map[string][]string, w io.Writer) error {
|
||||
for key, value := range annotations {
|
||||
switch key {
|
||||
case BashCompFilenameExt:
|
||||
fmt.Fprintf(out, " 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 {
|
||||
ext := "__handle_filename_extension_flag " + strings.Join(value, "|")
|
||||
fmt.Fprintf(out, " flags_completion+=(%q)\n", ext)
|
||||
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
||||
} else {
|
||||
ext := "_filedir"
|
||||
fmt.Fprintf(out, " flags_completion+=(%q)\n", ext)
|
||||
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case BashCompSubdirsInDir:
|
||||
fmt.Fprintf(out, " flags_with_completion+=(%q)\n", name)
|
||||
_, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name)
|
||||
|
||||
if len(value) == 1 {
|
||||
ext := "__handle_subdirs_in_dir_flag " + value[0]
|
||||
fmt.Fprintf(out, " flags_completion+=(%q)\n", ext)
|
||||
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
||||
} else {
|
||||
ext := "_filedir -d"
|
||||
fmt.Fprintf(out, " 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, out *bytes.Buffer) {
|
||||
func writeShortFlag(flag *pflag.Flag, w io.Writer) error {
|
||||
b := (flag.Value.Type() == "bool")
|
||||
name := flag.Shorthand
|
||||
format := " "
|
||||
|
@ -290,11 +316,13 @@ func writeShortFlag(flag *pflag.Flag, out *bytes.Buffer) {
|
|||
format += "two_word_"
|
||||
}
|
||||
format += "flags+=(\"-%s\")\n"
|
||||
fmt.Fprintf(out, format, name)
|
||||
writeFlagHandler("-"+name, flag.Annotations, out)
|
||||
if _, err := fmt.Fprintf(w, format, name); err != nil {
|
||||
return err
|
||||
}
|
||||
return writeFlagHandler("-"+name, flag.Annotations, w)
|
||||
}
|
||||
|
||||
func writeFlag(flag *pflag.Flag, out *bytes.Buffer) {
|
||||
func writeFlag(flag *pflag.Flag, w io.Writer) error {
|
||||
b := (flag.Value.Type() == "bool")
|
||||
name := flag.Name
|
||||
format := " flags+=(\"--%s"
|
||||
|
@ -302,36 +330,64 @@ func writeFlag(flag *pflag.Flag, out *bytes.Buffer) {
|
|||
format += "="
|
||||
}
|
||||
format += "\")\n"
|
||||
fmt.Fprintf(out, format, name)
|
||||
writeFlagHandler("--"+name, flag.Annotations, out)
|
||||
if _, err := fmt.Fprintf(w, format, name); err != nil {
|
||||
return err
|
||||
}
|
||||
return writeFlagHandler("--"+name, flag.Annotations, w)
|
||||
}
|
||||
|
||||
func writeFlags(cmd *Command, out *bytes.Buffer) {
|
||||
fmt.Fprintf(out, ` flags=()
|
||||
func writeFlags(cmd *Command, w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w, ` flags=()
|
||||
two_word_flags=()
|
||||
flags_with_completion=()
|
||||
flags_completion=()
|
||||
|
||||
`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var visitErr error
|
||||
cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
||||
writeFlag(flag, out)
|
||||
if err := writeFlag(flag, w); err != nil {
|
||||
visitErr = err
|
||||
return
|
||||
}
|
||||
if len(flag.Shorthand) > 0 {
|
||||
writeShortFlag(flag, out)
|
||||
if err := writeShortFlag(flag, w); err != nil {
|
||||
visitErr = err
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
if visitErr != nil {
|
||||
return visitErr
|
||||
}
|
||||
cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
||||
writeFlag(flag, out)
|
||||
if err := writeFlag(flag, w); err != nil {
|
||||
visitErr = err
|
||||
return
|
||||
}
|
||||
if len(flag.Shorthand) > 0 {
|
||||
writeShortFlag(flag, out)
|
||||
if err := writeShortFlag(flag, w); err != nil {
|
||||
visitErr = err
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
if visitErr != nil {
|
||||
return visitErr
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, "\n")
|
||||
_, err = fmt.Fprintf(w, "\n")
|
||||
return err
|
||||
}
|
||||
|
||||
func writeRequiredFlag(cmd *Command, out *bytes.Buffer) {
|
||||
fmt.Fprintf(out, " must_have_one_flag=()\n")
|
||||
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()
|
||||
var visitErr error
|
||||
flags.VisitAll(func(flag *pflag.Flag) {
|
||||
for key := range flag.Annotations {
|
||||
switch key {
|
||||
|
@ -342,68 +398,95 @@ func writeRequiredFlag(cmd *Command, out *bytes.Buffer) {
|
|||
format += "="
|
||||
}
|
||||
format += "\")\n"
|
||||
fmt.Fprintf(out, format, flag.Name)
|
||||
if _, err := fmt.Fprintf(w, format, flag.Name); err != nil {
|
||||
visitErr = err
|
||||
return
|
||||
}
|
||||
|
||||
if len(flag.Shorthand) > 0 {
|
||||
fmt.Fprintf(out, " 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, out *bytes.Buffer) {
|
||||
fmt.Fprintf(out, " must_have_one_noun=()\n")
|
||||
func writeRequiredNoun(cmd *Command, w io.Writer) error {
|
||||
if _, err := fmt.Fprintf(w, " must_have_one_noun=()\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
sort.Sort(sort.StringSlice(cmd.ValidArgs))
|
||||
for _, value := range cmd.ValidArgs {
|
||||
fmt.Fprintf(out, " 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, out *bytes.Buffer) {
|
||||
func gen(cmd *Command, w io.Writer) error {
|
||||
for _, c := range cmd.Commands() {
|
||||
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
||||
continue
|
||||
}
|
||||
gen(c, out)
|
||||
if err := gen(c, w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
commandName := cmd.CommandPath()
|
||||
commandName = strings.Replace(commandName, " ", "_", -1)
|
||||
commandName = strings.Replace(commandName, ":", "__", -1)
|
||||
fmt.Fprintf(out, "_%s()\n{\n", commandName)
|
||||
fmt.Fprintf(out, " last_command=%q\n", commandName)
|
||||
writeCommands(cmd, out)
|
||||
writeFlags(cmd, out)
|
||||
writeRequiredFlag(cmd, out)
|
||||
writeRequiredNoun(cmd, out)
|
||||
fmt.Fprintf(out, "}\n\n")
|
||||
if _, err := fmt.Fprintf(w, "_%s()\n{\n", commandName); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := fmt.Fprintf(w, " last_command=%q\n", commandName); err != nil {
|
||||
return err
|
||||
}
|
||||
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(out *bytes.Buffer) {
|
||||
preamble(out)
|
||||
if len(cmd.BashCompletionFunction) > 0 {
|
||||
fmt.Fprintf(out, "%s\n", cmd.BashCompletionFunction)
|
||||
func (cmd *Command) GenBashCompletion(w io.Writer) error {
|
||||
if err := preamble(w); err != nil {
|
||||
return err
|
||||
}
|
||||
gen(cmd, out)
|
||||
postscript(out, cmd.Name())
|
||||
if len(cmd.BashCompletionFunction) > 0 {
|
||||
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 {
|
||||
out := new(bytes.Buffer)
|
||||
|
||||
cmd.GenBashCompletion(out)
|
||||
|
||||
outFile, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer outFile.Close()
|
||||
|
||||
_, err = outFile.Write(out.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return cmd.GenBashCompletion(outFile)
|
||||
}
|
||||
|
||||
// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists.
|
||||
|
|
Loading…
Reference in a new issue