doc: Refactor man docs

Performance impact (very strange):
benchmark                        old ns/op     new ns/op     delta
BenchmarkGenManToFile-4          30037         29001         -3.45%

benchmark                        old allocs     new allocs     delta
BenchmarkGenManToFile-4          77             89             +15.58%

benchmark                        old bytes     new bytes     delta
BenchmarkGenManToFile-4          9075          9651          +6.35%
This commit is contained in:
Albert Nigmatzianov 2017-04-24 20:40:15 +02:00
parent ea3c5beeff
commit de484eefb4
2 changed files with 46 additions and 29 deletions

View File

@ -23,7 +23,7 @@ import (
"strings" "strings"
"time" "time"
mangen "github.com/cpuguy83/go-md2man/md2man" "github.com/cpuguy83/go-md2man/md2man"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
@ -105,7 +105,7 @@ func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error {
fillHeader(header, cmd.CommandPath()) fillHeader(header, cmd.CommandPath())
b := genMan(cmd, header) b := genMan(cmd, header)
_, err := w.Write(mangen.Render(b)) _, err := w.Write(md2man.Render(b))
return err return err
} }
@ -126,25 +126,25 @@ func fillHeader(header *GenManHeader, name string) {
} }
} }
func manPreamble(out io.Writer, header *GenManHeader, cmd *cobra.Command, dashedName string) { func manPreamble(buf *bytes.Buffer, header *GenManHeader, cmd *cobra.Command, dashedName string) {
description := cmd.Long description := cmd.Long
if len(description) == 0 { if len(description) == 0 {
description = cmd.Short description = cmd.Short
} }
fmt.Fprintf(out, `%% %s(%s)%s buf.WriteString(fmt.Sprintf(`%% %s(%s)%s
%% %s %% %s
%% %s %% %s
# NAME # NAME
`, header.Title, header.Section, header.date, header.Source, header.Manual) `, header.Title, header.Section, header.date, header.Source, header.Manual))
fmt.Fprintf(out, "%s \\- %s\n\n", dashedName, cmd.Short) buf.WriteString(fmt.Sprintf("%s \\- %s\n\n", dashedName, cmd.Short))
fmt.Fprintf(out, "# SYNOPSIS\n") buf.WriteString("# SYNOPSIS\n")
fmt.Fprintf(out, "**%s**\n\n", cmd.UseLine()) buf.WriteString(fmt.Sprintf("**%s**\n\n", cmd.UseLine()))
fmt.Fprintf(out, "# DESCRIPTION\n") buf.WriteString("# DESCRIPTION\n")
fmt.Fprintf(out, "%s\n\n", description) buf.WriteString(description + "\n\n")
} }
func manPrintFlags(out io.Writer, flags *pflag.FlagSet) { func manPrintFlags(buf *bytes.Buffer, flags *pflag.FlagSet) {
flags.VisitAll(func(flag *pflag.Flag) { flags.VisitAll(func(flag *pflag.Flag) {
if len(flag.Deprecated) > 0 || flag.Hidden { if len(flag.Deprecated) > 0 || flag.Hidden {
return return
@ -156,34 +156,34 @@ func manPrintFlags(out io.Writer, flags *pflag.FlagSet) {
format = fmt.Sprintf("**--%s**", flag.Name) format = fmt.Sprintf("**--%s**", flag.Name)
} }
if len(flag.NoOptDefVal) > 0 { if len(flag.NoOptDefVal) > 0 {
format = format + "[" format += "["
} }
if flag.Value.Type() == "string" { if flag.Value.Type() == "string" {
// put quotes on the value // put quotes on the value
format = format + "=%q" format += "=%q"
} else { } else {
format = format + "=%s" format += "=%s"
} }
if len(flag.NoOptDefVal) > 0 { if len(flag.NoOptDefVal) > 0 {
format = format + "]" format += "]"
} }
format = format + "\n\t%s\n\n" format += "\n\t%s\n\n"
fmt.Fprintf(out, format, flag.DefValue, flag.Usage) buf.WriteString(fmt.Sprintf(format, flag.DefValue, flag.Usage))
}) })
} }
func manPrintOptions(out io.Writer, command *cobra.Command) { func manPrintOptions(buf *bytes.Buffer, command *cobra.Command) {
flags := command.NonInheritedFlags() flags := command.NonInheritedFlags()
if flags.HasFlags() { if flags.HasFlags() {
fmt.Fprintf(out, "# OPTIONS\n") buf.WriteString("# OPTIONS\n")
manPrintFlags(out, flags) manPrintFlags(buf, flags)
fmt.Fprintf(out, "\n") buf.WriteString("\n")
} }
flags = command.InheritedFlags() flags = command.InheritedFlags()
if flags.HasFlags() { if flags.HasFlags() {
fmt.Fprintf(out, "# OPTIONS INHERITED FROM PARENT COMMANDS\n") buf.WriteString("# OPTIONS INHERITED FROM PARENT COMMANDS\n")
manPrintFlags(out, flags) manPrintFlags(buf, flags)
fmt.Fprintf(out, "\n") buf.WriteString("\n")
} }
} }
@ -196,11 +196,11 @@ func genMan(cmd *cobra.Command, header *GenManHeader) []byte {
manPreamble(buf, header, cmd, dashCommandName) manPreamble(buf, header, cmd, dashCommandName)
manPrintOptions(buf, cmd) manPrintOptions(buf, cmd)
if len(cmd.Example) > 0 { if len(cmd.Example) > 0 {
fmt.Fprintf(buf, "# EXAMPLE\n") buf.WriteString("# EXAMPLE\n")
fmt.Fprintf(buf, "```\n%s\n```\n", cmd.Example) buf.WriteString(fmt.Sprintf("```\n%s\n```\n", cmd.Example))
} }
if hasSeeAlso(cmd) { if hasSeeAlso(cmd) {
fmt.Fprintf(buf, "# SEE ALSO\n") buf.WriteString("# SEE ALSO\n")
seealsos := make([]string, 0) seealsos := make([]string, 0)
if cmd.HasParent() { if cmd.HasParent() {
parentPath := cmd.Parent().CommandPath() parentPath := cmd.Parent().CommandPath()
@ -222,10 +222,10 @@ func genMan(cmd *cobra.Command, header *GenManHeader) []byte {
seealso := fmt.Sprintf("**%s-%s(%s)**", dashCommandName, c.Name(), header.Section) seealso := fmt.Sprintf("**%s-%s(%s)**", dashCommandName, c.Name(), header.Section)
seealsos = append(seealsos, seealso) seealsos = append(seealsos, seealso)
} }
fmt.Fprintf(buf, "%s\n", strings.Join(seealsos, ", ")) buf.WriteString(strings.Join(seealsos, ", ") + "\n")
} }
if !cmd.DisableAutoGenTag { if !cmd.DisableAutoGenTag {
fmt.Fprintf(buf, "# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006")) buf.WriteString(fmt.Sprintf("# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006")))
} }
return buf.Bytes() return buf.Bytes()
} }

View File

@ -197,3 +197,20 @@ func AssertNextLineEquals(scanner *bufio.Scanner, expectedLine string) error {
return fmt.Errorf("AssertNextLineEquals: hit EOF before finding %#v", expectedLine) return fmt.Errorf("AssertNextLineEquals: hit EOF before finding %#v", expectedLine)
} }
func BenchmarkGenManToFile(b *testing.B) {
c := initializeWithRootCmd()
file, err := ioutil.TempFile("", "")
if err != nil {
b.Fatal(err)
}
defer os.Remove(file.Name())
defer file.Close()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := GenMan(c, nil, file); err != nil {
b.Fatal(err)
}
}
}