Skip to content

Commit

Permalink
Add groups for commands in help
Browse files Browse the repository at this point in the history
Adds the possibility to group the commands in the help message.
  • Loading branch information
Alexander Weiss committed Dec 14, 2019
1 parent b04b5bf commit cd741be
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 3 deletions.
5 changes: 5 additions & 0 deletions README.md
Expand Up @@ -550,6 +550,11 @@ command and flag definitions are needed.
Help is just a command like any other. There is no special logic or behavior
around it. In fact, you can provide your own if you want.

### Grouping commands in help

Cobra supports grouping of available commands. Groups can either be explicitly defined by `AddGroup` and set by
the `Group` element of a subcommand. If Groups are not explicitly defined they are implicitly defined.

### Defining your own help

You can provide your own Help command or your own template for the default command to use
Expand Down
60 changes: 57 additions & 3 deletions command.go
Expand Up @@ -33,6 +33,12 @@ var ErrSubCommandRequired = errors.New("subcommand is required")
// FParseErrWhitelist configures Flag parse errors to be ignored
type FParseErrWhitelist flag.ParseErrorsWhitelist

// Structure to manage groups for commands
type Group struct {
Group string
Title string
}

// Command is just that, a command for your application.
// E.g. 'go run ...' - 'run' is the command. Cobra requires
// you to define the usage and description as part of your command
Expand All @@ -51,6 +57,9 @@ type Command struct {
// Short is the short description shown in the 'help' output.
Short string

// The group under which the command is grouped in the 'help' output.
Group string

// Long is the long message shown in the 'help <this-command>' output.
Long string

Expand Down Expand Up @@ -162,6 +171,9 @@ type Command struct {
called bool
}

// groups for commands
commandgroups []*Group

// args is actual args parsed from flags.
args []string
// flagErrorBuf contains all error messages from pflag.
Expand Down Expand Up @@ -194,6 +206,9 @@ type Command struct {
// helpCommand is command with usage 'help'. If it's not defined by user,
// cobra uses default help command.
helpCommand *Command
// helpCommandGroup is the default group the helpCommand is in
helpCommandGroup string

// versionTemplate is the version template defined by user.
versionTemplate string

Expand Down Expand Up @@ -263,6 +278,15 @@ func (c *Command) SetHelpCommand(cmd *Command) {
c.helpCommand = cmd
}

// SetHelpCommandGroup sets the group of the help command.
func (c *Command) SetHelpCommandGroup(group string) {
if c.helpCommand != nil {
c.helpCommand.Group = group
}
// helpCommandGroup is used if no helpCommand is defined by the user
c.helpCommandGroup = group
}

// SetHelpTemplate sets help template to be used. Application can use it to set custom template.
func (c *Command) SetHelpTemplate(s string) {
c.helpTemplate = s
Expand Down Expand Up @@ -469,10 +493,13 @@ Aliases:
{{.NameAndAliases}}{{end}}{{if .HasExample}}
Examples:
{{.Example}}{{end}}{{if .HasAvailableSubCommands}}
{{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}
Available Commands:{{range $cmds}}{{if (and (eq .Group "") (or .IsAvailableCommand (eq .Name "help")))}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{range $group := .Groups}}
Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
{{.Title}}{{range $cmds}}{{if (and (eq .Group $group.Group) (or .IsAvailableCommand (eq .Name "help")))}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
Flags:
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
Expand Down Expand Up @@ -1034,6 +1061,7 @@ Simply type ` + c.Name() + ` help [path to command] for full details.`,
cmd.Help()
}
},
Group: c.helpCommandGroup,
}
}
c.RemoveCommand(c.helpCommand)
Expand Down Expand Up @@ -1072,6 +1100,10 @@ func (c *Command) AddCommand(cmds ...*Command) {
panic("Command can't be a child of itself")
}
cmds[i].parent = c
// if Group is not defined generate a new one with same title
if x.Group != "" && !c.ContainsGroup(x.Group) {
c.AddGroup(&Group{Group: x.Group, Title: x.Group})
}
// update max lengths
usageLen := len(x.Use)
if usageLen > c.commandsMaxUseLen {
Expand All @@ -1094,6 +1126,28 @@ func (c *Command) AddCommand(cmds ...*Command) {
}
}

// Groups returns a slice of child command groups.
func (c *Command) Groups() []*Group {
return c.commandgroups
}

// ContainGroups return if group is in command groups.
func (c *Command) ContainsGroup(group string) bool {
for _, x := range c.commandgroups {
if x.Group == group {
return true
}
}
return false
}

// AddGroup adds one or more command groups to this parent command.
func (c *Command) AddGroup(groups ...*Group) {
for _, x := range groups {
c.commandgroups = append(c.commandgroups, x)
}
}

// RemoveCommand removes one or more commands from a parent command.
func (c *Command) RemoveCommand(cmds ...*Command) {
commands := []*Command{}
Expand Down

0 comments on commit cd741be

Please sign in to comment.