Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion command.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ type Command struct {
// A value of 0 means all arguments are treated as positional (no flag parsing).
// A nil value means normal v3 flag parsing behavior (flags can appear anywhere).
StopOnNthArg *int `json:"stopOnNthArg"`

// Additional topics in the help message. Used to print arbitrary help topics
// in addition to the default help topics.
AdditionalHelpTopics map[string]string `json:"additionalHelpTopics"`
// categories contains the categorized commands and is populated on app startup
categories CommandCategories
// flagCategories contains the categorized flags and is populated on app startup
Expand Down
8 changes: 8 additions & 0 deletions command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4923,6 +4923,7 @@ func TestJSONExportCommand(t *testing.T) {
"description": "Description of the application.",
"defaultCommand": "",
"category": "",
"additionalHelpTopics": null,
"commands": [
{
"name": "config",
Expand All @@ -4936,6 +4937,7 @@ func TestJSONExportCommand(t *testing.T) {
"description": "",
"defaultCommand": "",
"category": "",
"additionalHelpTopics": null,
"commands": [
{
"name": "sub-config",
Expand All @@ -4950,6 +4952,7 @@ func TestJSONExportCommand(t *testing.T) {
"description": "",
"defaultCommand": "",
"category": "",
"additionalHelpTopics": null,
"commands": null,
"flags": [
{
Expand Down Expand Up @@ -5091,6 +5094,7 @@ func TestJSONExportCommand(t *testing.T) {
"description": "",
"defaultCommand": "",
"category": "",
"additionalHelpTopics": null,
"commands": null,
"flags": null,
"hideHelp": false,
Expand Down Expand Up @@ -5123,6 +5127,7 @@ func TestJSONExportCommand(t *testing.T) {
"description": "",
"defaultCommand": "",
"category": "",
"additionalHelpTopics": null,
"commands": null,
"flags": null,
"hideHelp": false,
Expand Down Expand Up @@ -5155,6 +5160,7 @@ func TestJSONExportCommand(t *testing.T) {
"description": "",
"defaultCommand": "",
"category": "",
"additionalHelpTopics": null,
"commands": null,
"flags": [
{
Expand Down Expand Up @@ -5208,6 +5214,7 @@ func TestJSONExportCommand(t *testing.T) {
"description": "",
"defaultCommand": "",
"category": "",
"additionalHelpTopics": null,
"commands": [
{
"name": "sub-usage",
Expand All @@ -5221,6 +5228,7 @@ func TestJSONExportCommand(t *testing.T) {
"description": "",
"defaultCommand": "",
"category": "",
"additionalHelpTopics": null,
"commands": null,
"flags": [
{
Expand Down
15 changes: 12 additions & 3 deletions godoc-current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ var CommandHelpTemplate = `NAME:
{{template "helpNameTemplate" .}}

USAGE:
{{template "usageTemplate" .}}{{if .Category}}
{{template "usageTemplate" .}}

{{- if .AdditionalHelpTopics}}{{ template "additionalHelpTopicsTemplate" .}}{{end}}{{if .Category}}

CATEGORY:
{{.Category}}{{end}}{{if .Description}}
Expand Down Expand Up @@ -115,7 +117,9 @@ var RootCommandHelpTemplate = `NAME:
{{template "helpNameTemplate" .}}

USAGE:
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}} {{if .VisibleFlags}}[global options]{{end}}{{if .VisibleCommands}} [command [command options]]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Arguments}} [arguments...]{{end}}{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}} {{if .VisibleFlags}}[global options]{{end}}{{if .VisibleCommands}} [command [command options]]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Arguments}} [arguments...]{{end}}{{end}}{{end}}

{{- if .AdditionalHelpTopics}}{{ template "additionalHelpTopicsTemplate" .}}{{end}}{{ if .Version}}{{if not .HideVersion}}

VERSION:
{{.Version}}{{end}}{{end}}{{if .Description}}
Expand Down Expand Up @@ -158,7 +162,9 @@ var SubcommandHelpTemplate = `NAME:
{{template "helpNameTemplate" .}}

USAGE:
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}}{{if .VisibleCommands}} [command [command options]]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Arguments}} [arguments...]{{end}}{{end}}{{end}}{{if .Category}}
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}}{{if .VisibleCommands}} [command [command options]]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Arguments}} [arguments...]{{end}}{{end}}{{end}}

{{- if .AdditionalHelpTopics}}{{ template "additionalHelpTopicsTemplate" .}}{{end}}{{if .Category}}

CATEGORY:
{{.Category}}{{end}}{{if .Description}}
Expand Down Expand Up @@ -549,6 +555,9 @@ type Command struct {
// A value of 0 means all arguments are treated as positional (no flag parsing).
// A nil value means normal v3 flag parsing behavior (flags can appear anywhere).
StopOnNthArg *int `json:"stopOnNthArg"`
// Additional topics in the help message. Used to print arbitrary help topics
// in addition to the default help topics.
AdditionalHelpTopics map[string]string `json:"additionalHelpTopics"`

// Has unexported fields.
}
Expand Down
4 changes: 4 additions & 0 deletions help.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,10 @@ func DefaultPrintHelpCustom(out io.Writer, templ string, data any, customFuncs m
handleTemplateError(err)
}

if _, err := t.New("additionalHelpTopicsTemplate").Parse(additionalHelpTopicsTemplate); err != nil {
handleTemplateError(err)
}

tracef("executing template")
handleTemplateError(t.Execute(w, data))

Expand Down
72 changes: 72 additions & 0 deletions help_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2096,6 +2096,7 @@ func TestPrintHelpCustomTemplateError(t *testing.T) {
&visibleFlagCategoryTemplate,
&authorsTemplate,
&visibleCommandCategoryTemplate,
&additionalHelpTopicsTemplate,
}

oldErrWriter := ErrWriter
Expand Down Expand Up @@ -2144,3 +2145,74 @@ func TestCustomUsageCommandHelp(t *testing.T) {
_ = cmd.Run(buildTestContext(t), []string{"app", "help"})
assert.Contains(t, out.String(), UsageCommandHelp)
}

func TestAdditionalHelpTopics(t *testing.T) {
expectedRootHelp := `NAME:
root - A new cli application

USAGE:
root [global options] [command [command options]]

ADDITIONAL-HELP:
ADDITIONAL-HELP

COMMANDS:
sub
help, h Shows a list of commands or help for one command

GLOBAL OPTIONS:
--help, -h show help
`

expectedSubHelp := `NAME:
root sub

USAGE:
root sub [options]

SUB-ADDITIONAL-HELP:
SUB-ADDITIONAL-HELP

OPTIONS:
--help, -h show help
`
tests := []struct {
name string
expectedOut string
command []string
}{
{
name: "rootCommandTest",
expectedOut: expectedRootHelp,
command: []string{"root", "--help"},
},
{
name: "subCommandTest",
expectedOut: expectedSubHelp,
command: []string{"root", "sub", "--help"},
},
}

rootCmd := &Command{
Name: "root",
Commands: []*Command{
{
Name: "sub",
AdditionalHelpTopics: map[string]string{
"SUB-ADDITIONAL-HELP": "SUB-ADDITIONAL-HELP",
},
},
},
AdditionalHelpTopics: map[string]string{
"ADDITIONAL-HELP": "ADDITIONAL-HELP",
},
}

for _, test := range tests {
actualOut := &bytes.Buffer{}
rootCmd.Writer = actualOut
err := rootCmd.Run(buildTestContext(t), test.command)
require.NoError(t, err)
assert.Equal(t, test.expectedOut, actualOut.String())
}
}
18 changes: 15 additions & 3 deletions template.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,22 @@ VERSION:

var copyrightTemplate = `{{wrap .Copyright 3}}`

var additionalHelpTopicsTemplate = `{{range $key, $value := .AdditionalHelpTopics}}

{{$key}}:
{{$value}}
{{- end}}`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{{- end}}`
{{end}}`


// RootCommandHelpTemplate is the text template for the Default help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
var RootCommandHelpTemplate = `NAME:
{{template "helpNameTemplate" .}}

USAGE:
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}} {{if .VisibleFlags}}[global options]{{end}}{{if .VisibleCommands}} [command [command options]]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Arguments}} [arguments...]{{end}}{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}} {{if .VisibleFlags}}[global options]{{end}}{{if .VisibleCommands}} [command [command options]]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Arguments}} [arguments...]{{end}}{{end}}{{end}}

{{- if .AdditionalHelpTopics}}{{ template "additionalHelpTopicsTemplate" .}}{{end}}{{ if .Version}}{{if not .HideVersion}}

VERSION:
{{.Version}}{{end}}{{end}}{{if .Description}}
Expand Down Expand Up @@ -73,7 +81,9 @@ var CommandHelpTemplate = `NAME:
{{template "helpNameTemplate" .}}

USAGE:
{{template "usageTemplate" .}}{{if .Category}}
{{template "usageTemplate" .}}

{{- if .AdditionalHelpTopics}}{{ template "additionalHelpTopicsTemplate" .}}{{end}}{{if .Category}}

CATEGORY:
{{.Category}}{{end}}{{if .Description}}
Expand All @@ -95,7 +105,9 @@ var SubcommandHelpTemplate = `NAME:
{{template "helpNameTemplate" .}}

USAGE:
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}}{{if .VisibleCommands}} [command [command options]]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Arguments}} [arguments...]{{end}}{{end}}{{end}}{{if .Category}}
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}}{{if .VisibleCommands}} [command [command options]]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Arguments}} [arguments...]{{end}}{{end}}{{end}}

{{- if .AdditionalHelpTopics}}{{ template "additionalHelpTopicsTemplate" .}}{{end}}{{if .Category}}

CATEGORY:
{{.Category}}{{end}}{{if .Description}}
Expand Down
15 changes: 12 additions & 3 deletions testdata/godoc-v3.x.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ var CommandHelpTemplate = `NAME:
{{template "helpNameTemplate" .}}

USAGE:
{{template "usageTemplate" .}}{{if .Category}}
{{template "usageTemplate" .}}

{{- if .AdditionalHelpTopics}}{{ template "additionalHelpTopicsTemplate" .}}{{end}}{{if .Category}}

CATEGORY:
{{.Category}}{{end}}{{if .Description}}
Expand Down Expand Up @@ -115,7 +117,9 @@ var RootCommandHelpTemplate = `NAME:
{{template "helpNameTemplate" .}}

USAGE:
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}} {{if .VisibleFlags}}[global options]{{end}}{{if .VisibleCommands}} [command [command options]]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Arguments}} [arguments...]{{end}}{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}} {{if .VisibleFlags}}[global options]{{end}}{{if .VisibleCommands}} [command [command options]]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Arguments}} [arguments...]{{end}}{{end}}{{end}}

{{- if .AdditionalHelpTopics}}{{ template "additionalHelpTopicsTemplate" .}}{{end}}{{ if .Version}}{{if not .HideVersion}}

VERSION:
{{.Version}}{{end}}{{end}}{{if .Description}}
Expand Down Expand Up @@ -158,7 +162,9 @@ var SubcommandHelpTemplate = `NAME:
{{template "helpNameTemplate" .}}

USAGE:
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}}{{if .VisibleCommands}} [command [command options]]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Arguments}} [arguments...]{{end}}{{end}}{{end}}{{if .Category}}
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}}{{if .VisibleCommands}} [command [command options]]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Arguments}} [arguments...]{{end}}{{end}}{{end}}

{{- if .AdditionalHelpTopics}}{{ template "additionalHelpTopicsTemplate" .}}{{end}}{{if .Category}}

CATEGORY:
{{.Category}}{{end}}{{if .Description}}
Expand Down Expand Up @@ -549,6 +555,9 @@ type Command struct {
// A value of 0 means all arguments are treated as positional (no flag parsing).
// A nil value means normal v3 flag parsing behavior (flags can appear anywhere).
StopOnNthArg *int `json:"stopOnNthArg"`
// Additional topics in the help message. Used to print arbitrary help topics
// in addition to the default help topics.
AdditionalHelpTopics map[string]string `json:"additionalHelpTopics"`

// Has unexported fields.
}
Expand Down
Loading