feat(docs): add UsageText to docs output for markdown and man page generation (#1171)
* feat(docs): add UsageText to docs output for markdown and man page generation * feat(docs): updated tests, DRYd up code, cleaned up string logic * fix(lint): fixed go1.15 lint errors
This commit is contained in:
parent
e79ceb69ff
commit
581b769cf3
48
docs.go
48
docs.go
@ -68,15 +68,16 @@ func prepareCommands(commands []*Command, level int) []string {
|
||||
if command.Hidden {
|
||||
continue
|
||||
}
|
||||
usage := ""
|
||||
if command.Usage != "" {
|
||||
usage = command.Usage
|
||||
}
|
||||
|
||||
prepared := fmt.Sprintf("%s %s\n\n%s\n",
|
||||
usageText := prepareUsageText(command)
|
||||
|
||||
usage := prepareUsage(command, usageText)
|
||||
|
||||
prepared := fmt.Sprintf("%s %s\n\n%s%s",
|
||||
strings.Repeat("#", level+2),
|
||||
strings.Join(command.Names(), ", "),
|
||||
usage,
|
||||
usageText,
|
||||
)
|
||||
|
||||
flags := prepareArgsWithValues(command.Flags)
|
||||
@ -155,3 +156,40 @@ func flagDetails(flag DocGenerationFlag) string {
|
||||
}
|
||||
return ": " + description
|
||||
}
|
||||
|
||||
func prepareUsageText(command *Command) string {
|
||||
if command.UsageText == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Remove leading and trailing newlines
|
||||
preparedUsageText := strings.Trim(command.UsageText, "\n")
|
||||
|
||||
var usageText string
|
||||
if strings.Contains(preparedUsageText, "\n") {
|
||||
// Format multi-line string as a code block using the 4 space schema to allow for embedded markdown such
|
||||
// that it will not break the continuous code block.
|
||||
for _, ln := range strings.Split(preparedUsageText, "\n") {
|
||||
usageText += fmt.Sprintf(" %s\n", ln)
|
||||
}
|
||||
} else {
|
||||
// Style a single line as a note
|
||||
usageText = fmt.Sprintf(">%s\n", preparedUsageText)
|
||||
}
|
||||
|
||||
return usageText
|
||||
}
|
||||
|
||||
func prepareUsage(command *Command, usageText string) string {
|
||||
if command.Usage == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
usage := command.Usage + "\n"
|
||||
// Add a newline to the Usage IFF there is a UsageText
|
||||
if usageText != "" {
|
||||
usage += "\n"
|
||||
}
|
||||
|
||||
return usage
|
||||
}
|
||||
|
148
docs_test.go
148
docs_test.go
@ -67,6 +67,47 @@ func testApp() *App {
|
||||
}, {
|
||||
Name: "hidden-command",
|
||||
Hidden: true,
|
||||
}, {
|
||||
Aliases: []string{"u"},
|
||||
Flags: []Flag{
|
||||
&StringFlag{
|
||||
Name: "flag",
|
||||
Aliases: []string{"fl", "f"},
|
||||
TakesFile: true,
|
||||
},
|
||||
&BoolFlag{
|
||||
Name: "another-flag",
|
||||
Aliases: []string{"b"},
|
||||
Usage: "another usage text",
|
||||
},
|
||||
},
|
||||
Name: "usage",
|
||||
Usage: "standard usage text",
|
||||
UsageText: `
|
||||
Usage for the usage text
|
||||
- formatted: Based on the specified ConfigMap and summon secrets.yml
|
||||
- list: Inspect the environment for a specific process running on a Pod
|
||||
- for_effect: Compare 'namespace' environment with 'local'
|
||||
|
||||
` + "```" + `
|
||||
func() { ... }
|
||||
` + "```" + `
|
||||
|
||||
Should be a part of the same code block
|
||||
`,
|
||||
Subcommands: []*Command{{
|
||||
Aliases: []string{"su"},
|
||||
Flags: []Flag{
|
||||
&BoolFlag{
|
||||
Name: "sub-command-flag",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "some usage text",
|
||||
},
|
||||
},
|
||||
Name: "sub-usage",
|
||||
Usage: "standard usage text",
|
||||
UsageText: "Single line of UsageText",
|
||||
}},
|
||||
}}
|
||||
app.UsageText = "app [first_arg] [second_arg]"
|
||||
app.Usage = "Some app"
|
||||
@ -175,3 +216,110 @@ func TestToManWithSection(t *testing.T) {
|
||||
expect(t, err, nil)
|
||||
expectFileContent(t, "testdata/expected-doc-full.man", res)
|
||||
}
|
||||
|
||||
func Test_prepareUsageText(t *testing.T) {
|
||||
t.Run("no UsageText provided", func(t *testing.T) {
|
||||
// Given
|
||||
cmd := Command{}
|
||||
|
||||
// When
|
||||
res := prepareUsageText(&cmd)
|
||||
|
||||
// Then
|
||||
expect(t, res, "")
|
||||
})
|
||||
|
||||
t.Run("single line UsageText", func(t *testing.T) {
|
||||
// Given
|
||||
cmd := Command{UsageText: "Single line usage text"}
|
||||
|
||||
// When
|
||||
res := prepareUsageText(&cmd)
|
||||
|
||||
// Then
|
||||
expect(t, res, ">Single line usage text\n")
|
||||
})
|
||||
|
||||
t.Run("multiline UsageText", func(t *testing.T) {
|
||||
// Given
|
||||
cmd := Command{
|
||||
UsageText: `
|
||||
Usage for the usage text
|
||||
- Should be a part of the same code block
|
||||
`,
|
||||
}
|
||||
|
||||
// When
|
||||
res := prepareUsageText(&cmd)
|
||||
|
||||
// Then
|
||||
test := ` Usage for the usage text
|
||||
- Should be a part of the same code block
|
||||
`
|
||||
expect(t, res, test)
|
||||
})
|
||||
|
||||
t.Run("multiline UsageText has formatted embedded markdown", func(t *testing.T) {
|
||||
// Given
|
||||
cmd := Command{
|
||||
UsageText: `
|
||||
Usage for the usage text
|
||||
|
||||
` + "```" + `
|
||||
func() { ... }
|
||||
` + "```" + `
|
||||
|
||||
Should be a part of the same code block
|
||||
`,
|
||||
}
|
||||
|
||||
// When
|
||||
res := prepareUsageText(&cmd)
|
||||
|
||||
// Then
|
||||
test := ` Usage for the usage text
|
||||
|
||||
` + "```" + `
|
||||
func() { ... }
|
||||
` + "```" + `
|
||||
|
||||
Should be a part of the same code block
|
||||
`
|
||||
expect(t, res, test)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_prepareUsage(t *testing.T) {
|
||||
t.Run("no Usage provided", func(t *testing.T) {
|
||||
// Given
|
||||
cmd := Command{}
|
||||
|
||||
// When
|
||||
res := prepareUsage(&cmd, "")
|
||||
|
||||
// Then
|
||||
expect(t, res, "")
|
||||
})
|
||||
|
||||
t.Run("simple Usage", func(t *testing.T) {
|
||||
// Given
|
||||
cmd := Command{Usage: "simple usage text"}
|
||||
|
||||
// When
|
||||
res := prepareUsage(&cmd, "")
|
||||
|
||||
// Then
|
||||
expect(t, res, cmd.Usage+"\n")
|
||||
})
|
||||
|
||||
t.Run("simple Usage with UsageText", func(t *testing.T) {
|
||||
// Given
|
||||
cmd := Command{Usage: "simple usage text"}
|
||||
|
||||
// When
|
||||
res := prepareUsage(&cmd, "a non-empty string")
|
||||
|
||||
// Then
|
||||
expect(t, res, cmd.Usage+"\n\n")
|
||||
})
|
||||
}
|
||||
|
42
testdata/expected-doc-full.man
vendored
42
testdata/expected-doc-full.man
vendored
@ -76,3 +76,45 @@ another usage test
|
||||
retrieve generic information
|
||||
|
||||
.SH some\-command
|
||||
.SH usage, u
|
||||
.PP
|
||||
standard usage text
|
||||
|
||||
.PP
|
||||
.RS
|
||||
|
||||
.nf
|
||||
Usage for the usage text
|
||||
\- formatted: Based on the specified ConfigMap and summon secrets.yml
|
||||
\- list: Inspect the environment for a specific process running on a Pod
|
||||
\- for\_effect: Compare 'namespace' environment with 'local'
|
||||
|
||||
```
|
||||
func() { ... }
|
||||
```
|
||||
|
||||
Should be a part of the same code block
|
||||
|
||||
.fi
|
||||
.RE
|
||||
|
||||
.PP
|
||||
\fB\-\-another\-flag, \-b\fP: another usage text
|
||||
|
||||
.PP
|
||||
\fB\-\-flag, \-\-fl, \-f\fP="":
|
||||
|
||||
.SS sub\-usage, su
|
||||
.PP
|
||||
standard usage text
|
||||
|
||||
.PP
|
||||
.RS
|
||||
|
||||
.PP
|
||||
Single line of UsageText
|
||||
|
||||
.RE
|
||||
|
||||
.PP
|
||||
\fB\-\-sub\-command\-flag, \-s\fP: some usage text
|
||||
|
26
testdata/expected-doc-full.md
vendored
26
testdata/expected-doc-full.md
vendored
@ -58,3 +58,29 @@ retrieve generic information
|
||||
## some-command
|
||||
|
||||
|
||||
## usage, u
|
||||
|
||||
standard usage text
|
||||
|
||||
Usage for the usage text
|
||||
- formatted: Based on the specified ConfigMap and summon secrets.yml
|
||||
- list: Inspect the environment for a specific process running on a Pod
|
||||
- for_effect: Compare 'namespace' environment with 'local'
|
||||
|
||||
```
|
||||
func() { ... }
|
||||
```
|
||||
|
||||
Should be a part of the same code block
|
||||
|
||||
**--another-flag, -b**: another usage text
|
||||
|
||||
**--flag, --fl, -f**="":
|
||||
|
||||
### sub-usage, su
|
||||
|
||||
standard usage text
|
||||
|
||||
>Single line of UsageText
|
||||
|
||||
**--sub-command-flag, -s**: some usage text
|
||||
|
26
testdata/expected-doc-no-authors.md
vendored
26
testdata/expected-doc-no-authors.md
vendored
@ -58,3 +58,29 @@ retrieve generic information
|
||||
## some-command
|
||||
|
||||
|
||||
## usage, u
|
||||
|
||||
standard usage text
|
||||
|
||||
Usage for the usage text
|
||||
- formatted: Based on the specified ConfigMap and summon secrets.yml
|
||||
- list: Inspect the environment for a specific process running on a Pod
|
||||
- for_effect: Compare 'namespace' environment with 'local'
|
||||
|
||||
```
|
||||
func() { ... }
|
||||
```
|
||||
|
||||
Should be a part of the same code block
|
||||
|
||||
**--another-flag, -b**: another usage text
|
||||
|
||||
**--flag, --fl, -f**="":
|
||||
|
||||
### sub-usage, su
|
||||
|
||||
standard usage text
|
||||
|
||||
>Single line of UsageText
|
||||
|
||||
**--sub-command-flag, -s**: some usage text
|
||||
|
26
testdata/expected-doc-no-flags.md
vendored
26
testdata/expected-doc-no-flags.md
vendored
@ -43,3 +43,29 @@ retrieve generic information
|
||||
## some-command
|
||||
|
||||
|
||||
## usage, u
|
||||
|
||||
standard usage text
|
||||
|
||||
Usage for the usage text
|
||||
- formatted: Based on the specified ConfigMap and summon secrets.yml
|
||||
- list: Inspect the environment for a specific process running on a Pod
|
||||
- for_effect: Compare 'namespace' environment with 'local'
|
||||
|
||||
```
|
||||
func() { ... }
|
||||
```
|
||||
|
||||
Should be a part of the same code block
|
||||
|
||||
**--another-flag, -b**: another usage text
|
||||
|
||||
**--flag, --fl, -f**="":
|
||||
|
||||
### sub-usage, su
|
||||
|
||||
standard usage text
|
||||
|
||||
>Single line of UsageText
|
||||
|
||||
**--sub-command-flag, -s**: some usage text
|
||||
|
9
testdata/expected-fish-full.fish
vendored
9
testdata/expected-fish-full.fish
vendored
@ -2,7 +2,7 @@
|
||||
|
||||
function __fish_greet_no_subcommand --description 'Test if there has been any subcommand yet'
|
||||
for i in (commandline -opc)
|
||||
if contains -- $i config c sub-config s ss info i in some-command
|
||||
if contains -- $i config c sub-config s ss info i in some-command usage u sub-usage su
|
||||
return 1
|
||||
end
|
||||
end
|
||||
@ -27,3 +27,10 @@ complete -c greet -n '__fish_seen_subcommand_from info i in' -f -l help -s h -d
|
||||
complete -r -c greet -n '__fish_greet_no_subcommand' -a 'info i in' -d 'retrieve generic information'
|
||||
complete -c greet -n '__fish_seen_subcommand_from some-command' -f -l help -s h -d 'show help'
|
||||
complete -r -c greet -n '__fish_greet_no_subcommand' -a 'some-command'
|
||||
complete -c greet -n '__fish_seen_subcommand_from usage u' -f -l help -s h -d 'show help'
|
||||
complete -r -c greet -n '__fish_greet_no_subcommand' -a 'usage u' -d 'standard usage text'
|
||||
complete -c greet -n '__fish_seen_subcommand_from usage u' -l flag -s fl -s f -r
|
||||
complete -c greet -n '__fish_seen_subcommand_from usage u' -f -l another-flag -s b -d 'another usage text'
|
||||
complete -c greet -n '__fish_seen_subcommand_from sub-usage su' -f -l help -s h -d 'show help'
|
||||
complete -r -c greet -n '__fish_seen_subcommand_from usage u' -a 'sub-usage su' -d 'standard usage text'
|
||||
complete -c greet -n '__fish_seen_subcommand_from sub-usage su' -f -l sub-command-flag -s s -d 'some usage text'
|
||||
|
Loading…
Reference in New Issue
Block a user