From edcf765d9fb36cbc5382ea5bf7e33f1ad931588c Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 8 Sep 2015 16:02:02 -0400 Subject: [PATCH] Mangen: allow callers to specify header information We previously had this weak argument called projectName which let you set a single part of a man page header. Instead do the best we can if the caller doesn't pass us anything, but let the caller specify anything they want. --- examples_test.go | 34 ++++++++++++++++++++ man_docs.go | 81 ++++++++++++++++++++++++++++++++++++++---------- man_docs.md | 6 +++- man_docs_test.go | 8 +++-- md_docs.go | 2 +- 5 files changed, 110 insertions(+), 21 deletions(-) create mode 100644 examples_test.go diff --git a/examples_test.go b/examples_test.go new file mode 100644 index 00000000..10da9850 --- /dev/null +++ b/examples_test.go @@ -0,0 +1,34 @@ +package cobra_test + +import ( + "bytes" + "fmt" + + "github.com/spf13/cobra" +) + +func ExampleCommand_GenManTree() { + cmd := &cobra.Command{ + Use: "test", + Short: "my test program", + } + header := &cobra.GenManHeader{ + Title: "MINE", + Section: "3", + } + cmd.GenManTree(header, "/tmp") +} + +func ExampleCommand_GenMan() { + cmd := &cobra.Command{ + Use: "test", + Short: "my test program", + } + header := &cobra.GenManHeader{ + Title: "MINE", + Section: "3", + } + out := new(bytes.Buffer) + cmd.GenMan(header, out) + fmt.Print(out.String()) +} diff --git a/man_docs.go b/man_docs.go index 894e5ecf..e5edbfdd 100644 --- a/man_docs.go +++ b/man_docs.go @@ -25,20 +25,29 @@ import ( "github.com/spf13/pflag" ) -func GenManTree(cmd *Command, projectName, dir string) { - cmd.GenManTree(projectName, dir) +// GenManTree will call cmd.GenManTree(header, dir) +func GenManTree(cmd *Command, header *GenManHeader, dir string) { + cmd.GenManTree(header, dir) } -func (cmd *Command) GenManTree(projectName, dir string) { +// GenManTree will generate a man page for this command and all decendants +// in the directory given. The header may be nil. This function may not work +// 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 (cmd *Command) GenManTree(header *GenManHeader, dir string) { + if header == nil { + header = &GenManHeader{} + } for _, c := range cmd.Commands() { if len(c.Deprecated) != 0 || c == cmd.helpCommand { continue } - GenManTree(c, projectName, dir) + GenManTree(c, header, dir) } out := new(bytes.Buffer) - cmd.GenMan(projectName, out) + cmd.GenMan(header, out) filename := cmd.CommandPath() filename = dir + strings.Replace(filename, " ", "-", -1) + ".1" @@ -55,21 +64,58 @@ func (cmd *Command) GenManTree(projectName, dir string) { } } -func GenMan(cmd *Command, projectName string, out *bytes.Buffer) { - cmd.GenMan(projectName, out) +// GenManHeader is a lot like the .TH header at the start of man pages. These +// include the title, section, date, source, and manual. We will use the +// current time if Date if unset and will use "Auto generated by spf13/cobra" +// if the Source is unset. +type GenManHeader struct { + Title string + Section string + Date *time.Time + date string + Source string + Manual string } -func (cmd *Command) GenMan(projectName string, out *bytes.Buffer) { +// GenMan will call cmd.GenMan(header, out) +func GenMan(cmd *Command, header *GenManHeader, out *bytes.Buffer) { + cmd.GenMan(header, out) +} - buf := genMarkdown(cmd, projectName) +// 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 (cmd *Command) GenMan(header *GenManHeader, out *bytes.Buffer) { + if header == nil { + header = &GenManHeader{} + } + buf := genMarkdown(cmd, header) final := mangen.Render(buf) out.Write(final) } -func manPreamble(out *bytes.Buffer, projectName, name, short, long string) { - fmt.Fprintf(out, `%% %s(1) +func fillHeader(header *GenManHeader, name string) { + if header.Title == "" { + header.Title = name + } + if header.Section == "" { + header.Section = "1" + } + if header.Date == nil { + now := time.Now() + header.Date = &now + } + header.date = (*header.Date).Format("Jan 2006") + if header.Source == "" { + header.Source = "Auto generated by spf13/cobra" + } +} + +func manPreamble(out *bytes.Buffer, header *GenManHeader, name, short, long string) { + fmt.Fprintf(out, `%% %s(%s)%s +%% %s +%% %s # NAME -`, projectName) +`, header.Title, header.Section, header.date, header.Source, header.Manual) fmt.Fprintf(out, "%s \\- %s\n\n", name, short) fmt.Fprintf(out, "# SYNOPSIS\n") fmt.Fprintf(out, "**%s** [OPTIONS]\n\n", name) @@ -120,7 +166,8 @@ func manPrintOptions(out *bytes.Buffer, command *Command) { } } -func genMarkdown(cmd *Command, projectName string) []byte { +func genMarkdown(cmd *Command, header *GenManHeader) []byte { + fillHeader(header, cmd.Name()) // something like `rootcmd subcmd1 subcmd2` commandName := cmd.CommandPath() // something like `rootcmd-subcmd1-subcmd2` @@ -134,7 +181,7 @@ func genMarkdown(cmd *Command, projectName string) []byte { long = short } - manPreamble(buf, projectName, commandName, short, long) + manPreamble(buf, header, commandName, short, long) manPrintOptions(buf, cmd) if len(cmd.Example) > 0 { @@ -147,7 +194,7 @@ func genMarkdown(cmd *Command, projectName string) []byte { if cmd.HasParent() { parentPath := cmd.Parent().CommandPath() dashParentPath := strings.Replace(parentPath, " ", "-", -1) - fmt.Fprintf(buf, "**%s(1)**, ", dashParentPath) + fmt.Fprintf(buf, "**%s(%s)**, ", dashParentPath, header.Section) } children := cmd.Commands() @@ -156,11 +203,11 @@ func genMarkdown(cmd *Command, projectName string) []byte { if len(c.Deprecated) != 0 || c == cmd.helpCommand { continue } - fmt.Fprintf(buf, "**%s-%s(1)**, ", dashCommandName, c.Name()) + fmt.Fprintf(buf, "**%s-%s(%s)**, ", dashCommandName, c.Name(), header.Section) } fmt.Fprintf(buf, "\n") } - fmt.Fprintf(buf, "# HISTORY\n%s Auto generated by spf13/cobra\n", time.Now().UTC()) + fmt.Fprintf(buf, "# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006")) return buf.Bytes() } diff --git a/man_docs.md b/man_docs.md index 3516d37c..a764099e 100644 --- a/man_docs.md +++ b/man_docs.md @@ -14,7 +14,11 @@ func main() { Use: "test", Short: "my test program", } - cmd.GenManTree("/tmp") + header := &cobra.GenManHeader{ + Title: "MINE", + Section: "3", + } + cmd.GenManTree(header, "/tmp") } ``` diff --git a/man_docs_test.go b/man_docs_test.go index cb86edb9..1c121d6c 100644 --- a/man_docs_test.go +++ b/man_docs_test.go @@ -24,15 +24,19 @@ func TestGenManDoc(t *testing.T) { out := new(bytes.Buffer) + header := &GenManHeader{ + Title: "Project", + Section: "2", + } // We generate on a subcommand so we have both subcommands and parents - cmdEcho.GenMan("PROJECT", out) + cmdEcho.GenMan(header, out) found := out.String() // Make sure parent has - in CommandPath() in SEE ALSO: parentPath := cmdEcho.Parent().CommandPath() dashParentPath := strings.Replace(parentPath, " ", "-", -1) expected := translate(dashParentPath) - expected = expected + "(1)" + expected = expected + "(" + header.Section + ")" checkStringContains(t, found, expected) // Our description diff --git a/md_docs.go b/md_docs.go index dde5b114..4e5b23a1 100644 --- a/md_docs.go +++ b/md_docs.go @@ -108,7 +108,7 @@ func (cmd *Command) GenMarkdownCustom(out *bytes.Buffer, linkHandler func(string fmt.Fprintf(out, "\n") } - fmt.Fprintf(out, "###### Auto generated by spf13/cobra at %s\n", time.Now().UTC()) + fmt.Fprintf(out, "###### Auto generated by spf13/cobra on %s\n", time.Now().Format("2-Jan-2006")) } func GenMarkdownTree(cmd *Command, dir string) {