docs: Auto generate formats document from examples (#192)

* Auto generate formats document from examples

* fix lint issues
This commit is contained in:
Khosrow Moossavi
2020-02-10 20:53:57 -05:00
committed by GitHub
parent dafa2e84f7
commit 54ab7f9bbb
17 changed files with 583 additions and 368 deletions

188
scripts/docs/generate.go Normal file
View File

@@ -0,0 +1,188 @@
package main
import (
"bytes"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/segmentio/terraform-docs/cmd"
"github.com/segmentio/terraform-docs/internal/pkg/print"
"github.com/segmentio/terraform-docs/internal/pkg/print/json"
"github.com/segmentio/terraform-docs/internal/pkg/print/markdown/document"
"github.com/segmentio/terraform-docs/internal/pkg/print/markdown/table"
"github.com/segmentio/terraform-docs/internal/pkg/print/pretty"
"github.com/segmentio/terraform-docs/internal/pkg/print/yaml"
"github.com/segmentio/terraform-docs/internal/pkg/tfconf"
"github.com/spf13/cobra"
)
// These are practiaclly a copy/paste of https://github.com/spf13/cobra/blob/master/doc/md_docs.go
// The reason we've decided to bring them over and not use them directly from cobra module was
// that we wanted to inject custom "Example" section with generated output based on the "examples"
// folder.
func main() {
for _, c := range cmd.FormatterCmds() {
err := generate(c, "./docs/formats")
if err != nil {
log.Fatal(err)
}
}
}
func generate(cmd *cobra.Command, dir string) error {
for _, c := range cmd.Commands() {
if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
continue
}
if err := generate(c, dir); err != nil {
return err
}
}
cmdpath := strings.Replace(cmd.CommandPath(), "terraform-docs ", "", -1)
basename := strings.Replace(cmdpath, " ", "-", -1) + ".md"
filename := filepath.Join(dir, basename)
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close() //nolint:errcheck
if _, err := io.WriteString(f, ""); err != nil {
return err
}
if err := generateMarkdown(cmd, f); err != nil {
return err
}
return nil
}
func generateMarkdown(cmd *cobra.Command, w io.Writer) error {
cmd.InitDefaultHelpCmd()
cmd.InitDefaultHelpFlag()
buf := new(bytes.Buffer)
name := cmd.CommandPath()
short := cmd.Short
long := cmd.Long
if len(long) == 0 {
long = short
}
buf.WriteString("## " + name + "\n\n")
buf.WriteString(short + "\n\n")
buf.WriteString("### Synopsis\n\n")
buf.WriteString(long + "\n\n")
if cmd.Runnable() {
buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine()))
}
if len(cmd.Example) > 0 {
buf.WriteString("### Examples\n\n")
buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.Example))
}
if err := printOptions(buf, cmd, name); err != nil {
return err
}
err := printExample(buf, name)
if err != nil {
return err
}
if !cmd.DisableAutoGenTag {
buf.WriteString("###### Auto generated by spf13/cobra on " + time.Now().Format("2-Jan-2006") + "\n")
}
_, err = buf.WriteTo(w)
return err
}
func printOptions(buf *bytes.Buffer, cmd *cobra.Command, name string) error {
flags := cmd.NonInheritedFlags()
flags.SetOutput(buf)
if flags.HasAvailableFlags() {
buf.WriteString("### Options\n\n```\n")
flags.PrintDefaults()
buf.WriteString("```\n\n")
}
parentFlags := cmd.InheritedFlags()
parentFlags.SetOutput(buf)
if parentFlags.HasAvailableFlags() {
buf.WriteString("### Options inherited from parent commands\n\n```\n")
parentFlags.PrintDefaults()
buf.WriteString("```\n\n")
}
return nil
}
type printer func(*tfconf.Module, *print.Settings) (string, error)
func getPrinter(name string) printer {
switch strings.Replace(name, "terraform-docs ", "", -1) {
case "json":
return json.Print
case "markdown document":
return document.Print
case "markdown table":
return table.Print
case "pretty":
return pretty.Print
case "yaml":
return yaml.Print
}
return nil
}
func getFlags(name string) string {
switch strings.Replace(name, "terraform-docs ", "", -1) {
case "pretty":
return " --no-color"
}
return ""
}
func printExample(buf *bytes.Buffer, name string) error {
buf.WriteString("### Example\n\n")
buf.WriteString("Given the [`examples`](/examples/) module:\n\n")
buf.WriteString("```shell\n")
buf.WriteString(fmt.Sprintf("%s%s ./examples/\n", name, getFlags(name)))
buf.WriteString("```\n\n")
buf.WriteString("generates the following output:\n\n")
module, err := tfconf.CreateModule("./examples")
if err != nil {
log.Fatal(err)
}
// fmt.Println(name)
if fn := getPrinter(name); fn != nil {
settings := print.NewSettings()
settings.ShowColor = false
output, err := fn(module, settings)
if err != nil {
return err
}
segments := strings.Split(output, "\n")
for _, s := range segments {
if s == "" {
buf.WriteString("\n")
} else {
buf.WriteString(fmt.Sprintf(" %s\n", s))
}
}
}
buf.WriteString("\n\n")
return nil
}