Merge pull request #218 from mvdan/error-checking

Error checking for doc generation
This commit is contained in:
Eric Paris 2016-01-06 09:57:15 -05:00
commit a3a9f345ca
6 changed files with 112 additions and 75 deletions

View file

@ -11,7 +11,7 @@ import (
)
var flagb1, flagb2, flagb3, flagbr, flagbp bool
var flags1, flags2a, flags2b, flags3, outs string
var flags1, flags2a, flags2b, flags3 string
var flagi1, flagi2, flagi3, flagir int
const strtwoParentHelp = "help message for parent flag strtwo"

View file

@ -32,7 +32,7 @@ import (
// correctly if your command names have - in them. If you have `cmd` with two
// subcmds, `sub` and `sub-third`. And `sub` has a subcommand called `third`
// it is undefined which help output will be in the file `cmd-sub-third.1`.
func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) {
func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error {
if header == nil {
header = &GenManHeader{}
}
@ -40,31 +40,28 @@ func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) {
if !c.IsAvailableCommand() || c.IsHelpCommand() {
continue
}
GenManTree(c, header, dir)
if err := GenManTree(c, header, dir); err != nil {
return err
}
}
out := new(bytes.Buffer)
needToResetTitle := header.Title == ""
GenMan(cmd, header, out)
filename := cmd.CommandPath()
filename = dir + strings.Replace(filename, " ", "-", -1) + ".1"
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
if err := GenMan(cmd, header, f); err != nil {
return err
}
if needToResetTitle {
header.Title = ""
}
filename := cmd.CommandPath()
filename = dir + strings.Replace(filename, " ", "-", -1) + ".1"
outFile, err := os.Create(filename)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer outFile.Close()
_, err = outFile.Write(out.Bytes())
if err != nil {
fmt.Println(err)
os.Exit(1)
}
return nil
}
// GenManHeader is a lot like the .TH header at the start of man pages. These
@ -80,15 +77,16 @@ type GenManHeader struct {
Manual string
}
// GenMan will generate a man page for the given command in the out buffer.
// The header argument may be nil, however obviously out may not.
func GenMan(cmd *cobra.Command, header *GenManHeader, out io.Writer) {
// GenMan will generate a man page for the given command and write it to
// w. The header argument may be nil, however obviously w may not.
func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error {
if header == nil {
header = &GenManHeader{}
}
buf := genMan(cmd, header)
final := mangen.Render(buf)
out.Write(final)
b := genMan(cmd, header)
final := mangen.Render(b)
_, err := w.Write(final)
return err
}
func fillHeader(header *GenManHeader, name string) {

View file

@ -29,7 +29,9 @@ func TestGenManDoc(t *testing.T) {
Section: "2",
}
// We generate on a subcommand so we have both subcommands and parents
GenMan(cmdEcho, header, out)
if err := GenMan(cmdEcho, header, out); err != nil {
t.Fatal(err)
}
found := out.String()
// Make sure parent has - in CommandPath() in SEE ALSO:
@ -85,7 +87,9 @@ func TestGenManNoGenTag(t *testing.T) {
Section: "2",
}
// We generate on a subcommand so we have both subcommands and parents
GenMan(cmdEcho, header, out)
if err := GenMan(cmdEcho, header, out); err != nil {
t.Fatal(err)
}
found := out.String()
unexpected := translate("#HISTORY")

View file

@ -14,7 +14,6 @@
package doc
import (
"bytes"
"fmt"
"io"
"os"
@ -25,29 +24,38 @@ import (
"github.com/spf13/cobra"
)
func printOptions(out io.Writer, cmd *cobra.Command, name string) {
func printOptions(w io.Writer, cmd *cobra.Command, name string) error {
flags := cmd.NonInheritedFlags()
flags.SetOutput(out)
flags.SetOutput(w)
if flags.HasFlags() {
fmt.Fprintf(out, "### Options\n\n```\n")
if _, err := fmt.Fprintf(w, "### Options\n\n```\n"); err != nil {
return err
}
flags.PrintDefaults()
fmt.Fprintf(out, "```\n\n")
if _, err := fmt.Fprintf(w, "```\n\n"); err != nil {
return err
}
}
parentFlags := cmd.InheritedFlags()
parentFlags.SetOutput(out)
parentFlags.SetOutput(w)
if parentFlags.HasFlags() {
fmt.Fprintf(out, "### Options inherited from parent commands\n\n```\n")
if _, err := fmt.Fprintf(w, "### Options inherited from parent commands\n\n```\n"); err != nil {
return err
}
parentFlags.PrintDefaults()
fmt.Fprintf(out, "```\n\n")
if _, err := fmt.Fprintf(w, "```\n\n"); err != nil {
return err
}
}
return nil
}
func GenMarkdown(cmd *cobra.Command, out io.Writer) {
GenMarkdownCustom(cmd, out, func(s string) string { return s })
func GenMarkdown(cmd *cobra.Command, w io.Writer) error {
return GenMarkdownCustom(cmd, w, func(s string) string { return s })
}
func GenMarkdownCustom(cmd *cobra.Command, out io.Writer, linkHandler func(string) string) {
func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error {
name := cmd.CommandPath()
short := cmd.Short
@ -56,29 +64,49 @@ func GenMarkdownCustom(cmd *cobra.Command, out io.Writer, linkHandler func(strin
long = short
}
fmt.Fprintf(out, "## %s\n\n", name)
fmt.Fprintf(out, "%s\n\n", short)
fmt.Fprintf(out, "### Synopsis\n\n")
fmt.Fprintf(out, "\n%s\n\n", long)
if _, err := fmt.Fprintf(w, "## %s\n\n", name); err != nil {
return err
}
if _, err := fmt.Fprintf(w, "%s\n\n", short); err != nil {
return err
}
if _, err := fmt.Fprintf(w, "### Synopsis\n\n"); err != nil {
return err
}
if _, err := fmt.Fprintf(w, "\n%s\n\n", long); err != nil {
return err
}
if cmd.Runnable() {
fmt.Fprintf(out, "```\n%s\n```\n\n", cmd.UseLine())
if _, err := fmt.Fprintf(w, "```\n%s\n```\n\n", cmd.UseLine()); err != nil {
return err
}
}
if len(cmd.Example) > 0 {
fmt.Fprintf(out, "### Examples\n\n")
fmt.Fprintf(out, "```\n%s\n```\n\n", cmd.Example)
if _, err := fmt.Fprintf(w, "### Examples\n\n"); err != nil {
return err
}
if _, err := fmt.Fprintf(w, "```\n%s\n```\n\n", cmd.Example); err != nil {
return err
}
}
printOptions(out, cmd, name)
if err := printOptions(w, cmd, name); err != nil {
return err
}
if hasSeeAlso(cmd) {
fmt.Fprintf(out, "### SEE ALSO\n")
if _, err := fmt.Fprintf(w, "### SEE ALSO\n"); err != nil {
return err
}
if cmd.HasParent() {
parent := cmd.Parent()
pname := parent.CommandPath()
link := pname + ".md"
link = strings.Replace(link, " ", "_", -1)
fmt.Fprintf(out, "* [%s](%s)\t - %s\n", pname, linkHandler(link), parent.Short)
if _, err := fmt.Fprintf(w, "* [%s](%s)\t - %s\n", pname, linkHandler(link), parent.Short); err != nil {
return err
}
cmd.VisitParents(func(c *cobra.Command) {
if c.DisableAutoGenTag {
cmd.DisableAutoGenTag = c.DisableAutoGenTag
@ -96,48 +124,51 @@ func GenMarkdownCustom(cmd *cobra.Command, out io.Writer, linkHandler func(strin
cname := name + " " + child.Name()
link := cname + ".md"
link = strings.Replace(link, " ", "_", -1)
fmt.Fprintf(out, "* [%s](%s)\t - %s\n", cname, linkHandler(link), child.Short)
if _, err := fmt.Fprintf(w, "* [%s](%s)\t - %s\n", cname, linkHandler(link), child.Short); err != nil {
return err
}
}
if _, err := fmt.Fprintf(w, "\n"); err != nil {
return err
}
fmt.Fprintf(out, "\n")
}
if !cmd.DisableAutoGenTag {
fmt.Fprintf(out, "###### Auto generated by spf13/cobra on %s\n", time.Now().Format("2-Jan-2006"))
if _, err := fmt.Fprintf(w, "###### Auto generated by spf13/cobra on %s\n", time.Now().Format("2-Jan-2006")); err != nil {
return err
}
}
return nil
}
func GenMarkdownTree(cmd *cobra.Command, dir string) {
func GenMarkdownTree(cmd *cobra.Command, dir string) error {
identity := func(s string) string { return s }
emptyStr := func(s string) string { return "" }
GenMarkdownTreeCustom(cmd, dir, emptyStr, identity)
return GenMarkdownTreeCustom(cmd, dir, emptyStr, identity)
}
func GenMarkdownTreeCustom(cmd *cobra.Command, dir string, filePrepender func(string) string, linkHandler func(string) string) {
func GenMarkdownTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error {
for _, c := range cmd.Commands() {
if !c.IsAvailableCommand() || c.IsHelpCommand() {
continue
}
GenMarkdownTreeCustom(c, dir, filePrepender, linkHandler)
if err := GenMarkdownTreeCustom(c, dir, filePrepender, linkHandler); err != nil {
return err
}
}
out := new(bytes.Buffer)
GenMarkdownCustom(cmd, out, linkHandler)
filename := cmd.CommandPath()
filename = dir + strings.Replace(filename, " ", "_", -1) + ".md"
outFile, err := os.Create(filename)
f, err := os.Create(filename)
if err != nil {
fmt.Println(err)
os.Exit(1)
return err
}
defer outFile.Close()
_, err = outFile.WriteString(filePrepender(filename))
if err != nil {
fmt.Println(err)
os.Exit(1)
defer f.Close()
if _, err := io.WriteString(f, filePrepender(filename)); err != nil {
return err
}
_, err = outFile.Write(out.Bytes())
if err != nil {
fmt.Println(err)
os.Exit(1)
if err := GenMarkdownCustom(cmd, f, linkHandler); err != nil {
return err
}
return nil
}

View file

@ -39,13 +39,13 @@ This will write the markdown doc for ONLY "cmd" into the out, buffer.
Both `GenMarkdown` and `GenMarkdownTree` have alternate versions with callbacks to get some control of the output:
```go
func GenMarkdownTreeCustom(cmd *Command, dir string, filePrepender func(string) string, linkHandler func(string) string) {
func GenMarkdownTreeCustom(cmd *Command, dir string, filePrepender, linkHandler func(string) string) error {
//...
}
```
```go
func GenMarkdownCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string) string) {
func GenMarkdownCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string) string) error {
//...
}
```

View file

@ -21,7 +21,9 @@ func TestGenMdDoc(t *testing.T) {
out := new(bytes.Buffer)
// We generate on s subcommand so we have both subcommands and parents
GenMarkdown(cmdEcho, out)
if err := GenMarkdown(cmdEcho, out); err != nil {
t.Fatal(err)
}
found := out.String()
// Our description
@ -75,7 +77,9 @@ func TestGenMdNoTag(t *testing.T) {
cmdRootWithRun.PersistentFlags().StringVarP(&flags2a, "rootflag", "r", "two", strtwoParentHelp)
out := new(bytes.Buffer)
GenMarkdown(c, out)
if err := GenMarkdown(c, out); err != nil {
t.Fatal(err)
}
found := out.String()
unexpected := "Auto generated"