mirror of
https://github.com/spf13/cobra
synced 2024-11-24 14:47:12 +00:00
Add a COMMANDS section to generated man pages
When a command has available sub-commands, the COMMANDS man section is generated with the list of sub-commands, with their name, short description, and the name of the dedicated man page.
This commit is contained in:
parent
68b6b24f0c
commit
98e8c716ca
3 changed files with 72 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
||||||
package doc
|
package doc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -89,3 +90,9 @@ func checkStringOmits(t *testing.T, got, expected string) {
|
||||||
t.Errorf("Expected to not contain: \n %v\nGot: %v", expected, got)
|
t.Errorf("Expected to not contain: \n %v\nGot: %v", expected, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkStringMatch(t *testing.T, got, pattern string) {
|
||||||
|
if ok, _ := regexp.MatchString(pattern, got); !ok {
|
||||||
|
t.Errorf("Expected to match: \n%v\nGot:\n %v\n", pattern, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -155,6 +155,31 @@ func manPreamble(buf io.StringWriter, header *GenManHeader, cmd *cobra.Command,
|
||||||
cobra.WriteStringAndCheck(buf, description+"\n\n")
|
cobra.WriteStringAndCheck(buf, description+"\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func manPrintCommands(buf io.StringWriter, header *GenManHeader, cmd *cobra.Command) {
|
||||||
|
// Find sub-commands that need to be documented
|
||||||
|
subCommands := []*cobra.Command{}
|
||||||
|
for _, c := range cmd.Commands() {
|
||||||
|
if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
subCommands = append(subCommands, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to go further if there is no sub-commands to document
|
||||||
|
if len(subCommands) <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a 'COMMANDS' section in the generated documentation
|
||||||
|
cobra.WriteStringAndCheck(buf, "# COMMANDS\n")
|
||||||
|
// For each sub-commands, and an entry with the command name and it's Short description and reference to dedicated
|
||||||
|
// man page
|
||||||
|
for _, c := range subCommands {
|
||||||
|
dashedPath := strings.Replace(c.CommandPath(), " ", "-", -1)
|
||||||
|
cobra.WriteStringAndCheck(buf, fmt.Sprintf("**%s**\n %s \n See **%s(%s)**.\n\n", c.Name(), c.Short, dashedPath, header.Section))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func manPrintFlags(buf io.StringWriter, flags *pflag.FlagSet) {
|
func manPrintFlags(buf io.StringWriter, 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 {
|
||||||
|
@ -208,6 +233,7 @@ func genMan(cmd *cobra.Command, header *GenManHeader) []byte {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
manPreamble(buf, header, cmd, dashCommandName)
|
manPreamble(buf, header, cmd, dashCommandName)
|
||||||
|
manPrintCommands(buf, header, cmd)
|
||||||
manPrintOptions(buf, cmd)
|
manPrintOptions(buf, cmd)
|
||||||
if len(cmd.Example) > 0 {
|
if len(cmd.Example) > 0 {
|
||||||
buf.WriteString("# EXAMPLE\n")
|
buf.WriteString("# EXAMPLE\n")
|
||||||
|
|
|
@ -151,6 +151,45 @@ func TestManPrintFlagsHidesShortDeperecated(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGenManCommands(t *testing.T) {
|
||||||
|
header := &GenManHeader{
|
||||||
|
Title: "Project",
|
||||||
|
Section: "2",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Root command
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
if err := GenMan(rootCmd, header, buf); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
output := buf.String()
|
||||||
|
|
||||||
|
checkStringContains(t, output, ".SH COMMANDS")
|
||||||
|
checkStringMatch(t, output, "\\\\fBecho\\\\fP\n[ \t]+Echo anything to the screen\n[ \t]+See \\\\fBroot-echo\\(2\\)\\\\fP\\\\&\\.")
|
||||||
|
checkStringOmits(t, output, ".PP\n\\fBprint\\fP\n")
|
||||||
|
|
||||||
|
// Echo command
|
||||||
|
buf = new(bytes.Buffer)
|
||||||
|
if err := GenMan(echoCmd, header, buf); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
output = buf.String()
|
||||||
|
|
||||||
|
checkStringContains(t, output, ".SH COMMANDS")
|
||||||
|
checkStringMatch(t, output, "\\\\fBtimes\\\\fP\n[ \t]+Echo anything to the screen more times\n[ \t]+See \\\\fBroot-echo-times\\(2\\)\\\\fP\\\\&\\.")
|
||||||
|
checkStringMatch(t, output, "\\\\fBechosub\\\\fP\n[ \t]+second sub command for echo\n[ \t]+See \\\\fBroot-echo-echosub\\(2\\)\\\\fP\\\\&\\.")
|
||||||
|
checkStringOmits(t, output, ".PP\n\\fBdeprecated\\fP\n")
|
||||||
|
|
||||||
|
// Time command as echo's subcommand
|
||||||
|
buf = new(bytes.Buffer)
|
||||||
|
if err := GenMan(timesCmd, header, buf); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
output = buf.String()
|
||||||
|
|
||||||
|
checkStringOmits(t, output, ".SH COMMANDS")
|
||||||
|
}
|
||||||
|
|
||||||
func TestGenManTree(t *testing.T) {
|
func TestGenManTree(t *testing.T) {
|
||||||
c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"}
|
c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"}
|
||||||
header := &GenManHeader{Section: "2"}
|
header := &GenManHeader{Section: "2"}
|
||||||
|
|
Loading…
Reference in a new issue