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 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 var flagi1, flagi2, flagi3, flagir int
const strtwoParentHelp = "help message for parent flag strtwo" 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 // 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` // 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`. // 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 { if header == nil {
header = &GenManHeader{} header = &GenManHeader{}
} }
@ -40,31 +40,28 @@ func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) {
if !c.IsAvailableCommand() || c.IsHelpCommand() { if !c.IsAvailableCommand() || c.IsHelpCommand() {
continue continue
} }
GenManTree(c, header, dir) if err := GenManTree(c, header, dir); err != nil {
return err
}
} }
out := new(bytes.Buffer)
needToResetTitle := header.Title == "" 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 { if needToResetTitle {
header.Title = "" header.Title = ""
} }
return nil
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)
}
} }
// GenManHeader is a lot like the .TH header at the start of man pages. These // GenManHeader is a lot like the .TH header at the start of man pages. These
@ -80,15 +77,16 @@ type GenManHeader struct {
Manual string Manual string
} }
// GenMan will generate a man page for the given command in the out buffer. // GenMan will generate a man page for the given command and write it to
// The header argument may be nil, however obviously out may not. // w. The header argument may be nil, however obviously w may not.
func GenMan(cmd *cobra.Command, header *GenManHeader, out io.Writer) { func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error {
if header == nil { if header == nil {
header = &GenManHeader{} header = &GenManHeader{}
} }
buf := genMan(cmd, header) b := genMan(cmd, header)
final := mangen.Render(buf) final := mangen.Render(b)
out.Write(final) _, err := w.Write(final)
return err
} }
func fillHeader(header *GenManHeader, name string) { func fillHeader(header *GenManHeader, name string) {

View file

@ -29,7 +29,9 @@ func TestGenManDoc(t *testing.T) {
Section: "2", Section: "2",
} }
// We generate on a subcommand so we have both subcommands and parents // 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() found := out.String()
// Make sure parent has - in CommandPath() in SEE ALSO: // Make sure parent has - in CommandPath() in SEE ALSO:
@ -85,7 +87,9 @@ func TestGenManNoGenTag(t *testing.T) {
Section: "2", Section: "2",
} }
// We generate on a subcommand so we have both subcommands and parents // 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() found := out.String()
unexpected := translate("#HISTORY") unexpected := translate("#HISTORY")

View file

@ -14,7 +14,6 @@
package doc package doc
import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -25,29 +24,38 @@ import (
"github.com/spf13/cobra" "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 := cmd.NonInheritedFlags()
flags.SetOutput(out) flags.SetOutput(w)
if flags.HasFlags() { 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() flags.PrintDefaults()
fmt.Fprintf(out, "```\n\n") if _, err := fmt.Fprintf(w, "```\n\n"); err != nil {
return err
}
} }
parentFlags := cmd.InheritedFlags() parentFlags := cmd.InheritedFlags()
parentFlags.SetOutput(out) parentFlags.SetOutput(w)
if parentFlags.HasFlags() { 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 {
parentFlags.PrintDefaults() return err
fmt.Fprintf(out, "```\n\n")
} }
parentFlags.PrintDefaults()
if _, err := fmt.Fprintf(w, "```\n\n"); err != nil {
return err
}
}
return nil
} }
func GenMarkdown(cmd *cobra.Command, out io.Writer) { func GenMarkdown(cmd *cobra.Command, w io.Writer) error {
GenMarkdownCustom(cmd, out, func(s string) string { return s }) 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() name := cmd.CommandPath()
short := cmd.Short short := cmd.Short
@ -56,29 +64,49 @@ func GenMarkdownCustom(cmd *cobra.Command, out io.Writer, linkHandler func(strin
long = short long = short
} }
fmt.Fprintf(out, "## %s\n\n", name) if _, err := fmt.Fprintf(w, "## %s\n\n", name); err != nil {
fmt.Fprintf(out, "%s\n\n", short) return err
fmt.Fprintf(out, "### Synopsis\n\n") }
fmt.Fprintf(out, "\n%s\n\n", long) 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() { 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 { if len(cmd.Example) > 0 {
fmt.Fprintf(out, "### Examples\n\n") if _, err := fmt.Fprintf(w, "### Examples\n\n"); err != nil {
fmt.Fprintf(out, "```\n%s\n```\n\n", cmd.Example) 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) { if hasSeeAlso(cmd) {
fmt.Fprintf(out, "### SEE ALSO\n") if _, err := fmt.Fprintf(w, "### SEE ALSO\n"); err != nil {
return err
}
if cmd.HasParent() { if cmd.HasParent() {
parent := cmd.Parent() parent := cmd.Parent()
pname := parent.CommandPath() pname := parent.CommandPath()
link := pname + ".md" link := pname + ".md"
link = strings.Replace(link, " ", "_", -1) 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) { cmd.VisitParents(func(c *cobra.Command) {
if c.DisableAutoGenTag { if c.DisableAutoGenTag {
cmd.DisableAutoGenTag = 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() cname := name + " " + child.Name()
link := cname + ".md" link := cname + ".md"
link = strings.Replace(link, " ", "_", -1) 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 { 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 } identity := func(s string) string { return s }
emptyStr := func(s string) string { return "" } 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() { for _, c := range cmd.Commands() {
if !c.IsAvailableCommand() || c.IsHelpCommand() { if !c.IsAvailableCommand() || c.IsHelpCommand() {
continue 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 := cmd.CommandPath()
filename = dir + strings.Replace(filename, " ", "_", -1) + ".md" filename = dir + strings.Replace(filename, " ", "_", -1) + ".md"
outFile, err := os.Create(filename) f, err := os.Create(filename)
if err != nil { if err != nil {
fmt.Println(err) return err
os.Exit(1)
} }
defer outFile.Close() defer f.Close()
_, err = outFile.WriteString(filePrepender(filename))
if err != nil { if _, err := io.WriteString(f, filePrepender(filename)); err != nil {
fmt.Println(err) return err
os.Exit(1)
} }
_, err = outFile.Write(out.Bytes()) if err := GenMarkdownCustom(cmd, f, linkHandler); err != nil {
if err != nil { return err
fmt.Println(err)
os.Exit(1)
} }
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: Both `GenMarkdown` and `GenMarkdownTree` have alternate versions with callbacks to get some control of the output:
```go ```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 ```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) out := new(bytes.Buffer)
// We generate on s subcommand so we have both subcommands and parents // 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() found := out.String()
// Our description // Our description
@ -75,7 +77,9 @@ func TestGenMdNoTag(t *testing.T) {
cmdRootWithRun.PersistentFlags().StringVarP(&flags2a, "rootflag", "r", "two", strtwoParentHelp) cmdRootWithRun.PersistentFlags().StringVarP(&flags2a, "rootflag", "r", "two", strtwoParentHelp)
out := new(bytes.Buffer) out := new(bytes.Buffer)
GenMarkdown(c, out) if err := GenMarkdown(c, out); err != nil {
t.Fatal(err)
}
found := out.String() found := out.String()
unexpected := "Auto generated" unexpected := "Auto generated"