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.
This commit is contained in:
		
							
								
								
									
										34
									
								
								examples_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								examples_test.go
									
									
									
									
									
										Normal file
									
								
							@ -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())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										81
									
								
								man_docs.go
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								man_docs.go
									
									
									
									
									
								
							@ -25,20 +25,29 @@ import (
 | 
				
			|||||||
	"github.com/spf13/pflag"
 | 
						"github.com/spf13/pflag"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GenManTree(cmd *Command, projectName, dir string) {
 | 
					// GenManTree will call cmd.GenManTree(header, dir)
 | 
				
			||||||
	cmd.GenManTree(projectName, 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() {
 | 
						for _, c := range cmd.Commands() {
 | 
				
			||||||
		if len(c.Deprecated) != 0 || c == cmd.helpCommand {
 | 
							if len(c.Deprecated) != 0 || c == cmd.helpCommand {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		GenManTree(c, projectName, dir)
 | 
							GenManTree(c, header, dir)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	out := new(bytes.Buffer)
 | 
						out := new(bytes.Buffer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd.GenMan(projectName, out)
 | 
						cmd.GenMan(header, out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	filename := cmd.CommandPath()
 | 
						filename := cmd.CommandPath()
 | 
				
			||||||
	filename = dir + strings.Replace(filename, " ", "-", -1) + ".1"
 | 
						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) {
 | 
					// GenManHeader is a lot like the .TH header at the start of man pages. These
 | 
				
			||||||
	cmd.GenMan(projectName, out)
 | 
					// 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)
 | 
						final := mangen.Render(buf)
 | 
				
			||||||
	out.Write(final)
 | 
						out.Write(final)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func manPreamble(out *bytes.Buffer, projectName, name, short, long string) {
 | 
					func fillHeader(header *GenManHeader, name string) {
 | 
				
			||||||
	fmt.Fprintf(out, `%% %s(1)
 | 
						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
 | 
					# NAME
 | 
				
			||||||
`, projectName)
 | 
					`, header.Title, header.Section, header.date, header.Source, header.Manual)
 | 
				
			||||||
	fmt.Fprintf(out, "%s \\- %s\n\n", name, short)
 | 
						fmt.Fprintf(out, "%s \\- %s\n\n", name, short)
 | 
				
			||||||
	fmt.Fprintf(out, "# SYNOPSIS\n")
 | 
						fmt.Fprintf(out, "# SYNOPSIS\n")
 | 
				
			||||||
	fmt.Fprintf(out, "**%s** [OPTIONS]\n\n", name)
 | 
						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`
 | 
						// something like `rootcmd subcmd1 subcmd2`
 | 
				
			||||||
	commandName := cmd.CommandPath()
 | 
						commandName := cmd.CommandPath()
 | 
				
			||||||
	// something like `rootcmd-subcmd1-subcmd2`
 | 
						// something like `rootcmd-subcmd1-subcmd2`
 | 
				
			||||||
@ -134,7 +181,7 @@ func genMarkdown(cmd *Command, projectName string) []byte {
 | 
				
			|||||||
		long = short
 | 
							long = short
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	manPreamble(buf, projectName, commandName, short, long)
 | 
						manPreamble(buf, header, commandName, short, long)
 | 
				
			||||||
	manPrintOptions(buf, cmd)
 | 
						manPrintOptions(buf, cmd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(cmd.Example) > 0 {
 | 
						if len(cmd.Example) > 0 {
 | 
				
			||||||
@ -147,7 +194,7 @@ func genMarkdown(cmd *Command, projectName string) []byte {
 | 
				
			|||||||
		if cmd.HasParent() {
 | 
							if cmd.HasParent() {
 | 
				
			||||||
			parentPath := cmd.Parent().CommandPath()
 | 
								parentPath := cmd.Parent().CommandPath()
 | 
				
			||||||
			dashParentPath := strings.Replace(parentPath, " ", "-", -1)
 | 
								dashParentPath := strings.Replace(parentPath, " ", "-", -1)
 | 
				
			||||||
			fmt.Fprintf(buf, "**%s(1)**, ", dashParentPath)
 | 
								fmt.Fprintf(buf, "**%s(%s)**, ", dashParentPath, header.Section)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		children := cmd.Commands()
 | 
							children := cmd.Commands()
 | 
				
			||||||
@ -156,11 +203,11 @@ func genMarkdown(cmd *Command, projectName string) []byte {
 | 
				
			|||||||
			if len(c.Deprecated) != 0 || c == cmd.helpCommand {
 | 
								if len(c.Deprecated) != 0 || c == cmd.helpCommand {
 | 
				
			||||||
				continue
 | 
									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, "\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()
 | 
						return buf.Bytes()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,11 @@ func main() {
 | 
				
			|||||||
		Use:   "test",
 | 
							Use:   "test",
 | 
				
			||||||
		Short: "my test program",
 | 
							Short: "my test program",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cmd.GenManTree("/tmp")
 | 
						header := &cobra.GenManHeader{
 | 
				
			||||||
 | 
							Title: "MINE",
 | 
				
			||||||
 | 
							Section: "3",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cmd.GenManTree(header, "/tmp")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -24,15 +24,19 @@ func TestGenManDoc(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	out := new(bytes.Buffer)
 | 
						out := new(bytes.Buffer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						header := &GenManHeader{
 | 
				
			||||||
 | 
							Title:   "Project",
 | 
				
			||||||
 | 
							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
 | 
				
			||||||
	cmdEcho.GenMan("PROJECT", out)
 | 
						cmdEcho.GenMan(header, out)
 | 
				
			||||||
	found := out.String()
 | 
						found := out.String()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Make sure parent has - in CommandPath() in SEE ALSO:
 | 
						// Make sure parent has - in CommandPath() in SEE ALSO:
 | 
				
			||||||
	parentPath := cmdEcho.Parent().CommandPath()
 | 
						parentPath := cmdEcho.Parent().CommandPath()
 | 
				
			||||||
	dashParentPath := strings.Replace(parentPath, " ", "-", -1)
 | 
						dashParentPath := strings.Replace(parentPath, " ", "-", -1)
 | 
				
			||||||
	expected := translate(dashParentPath)
 | 
						expected := translate(dashParentPath)
 | 
				
			||||||
	expected = expected + "(1)"
 | 
						expected = expected + "(" + header.Section + ")"
 | 
				
			||||||
	checkStringContains(t, found, expected)
 | 
						checkStringContains(t, found, expected)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Our description
 | 
						// Our description
 | 
				
			||||||
 | 
				
			|||||||
@ -108,7 +108,7 @@ func (cmd *Command) GenMarkdownCustom(out *bytes.Buffer, linkHandler func(string
 | 
				
			|||||||
		fmt.Fprintf(out, "\n")
 | 
							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) {
 | 
					func GenMarkdownTree(cmd *Command, dir string) {
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user