@@ -35,6 +35,12 @@ const FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra"
35
35
// FParseErrWhitelist configures Flag parse errors to be ignored
36
36
type FParseErrWhitelist flag.ParseErrorsWhitelist
37
37
38
+ // Structure to manage groups for commands
39
+ type Group struct {
40
+ ID string
41
+ Title string
42
+ }
43
+
38
44
// Command is just that, a command for your application.
39
45
// E.g. 'go run ...' - 'run' is the command. Cobra requires
40
46
// you to define the usage and description as part of your command
@@ -61,6 +67,9 @@ type Command struct {
61
67
// Short is the short description shown in the 'help' output.
62
68
Short string
63
69
70
+ // The group id under which this subcommand is grouped in the 'help' output of its parent.
71
+ GroupID string
72
+
64
73
// Long is the long message shown in the 'help <this-command>' output.
65
74
Long string
66
75
@@ -128,6 +137,9 @@ type Command struct {
128
137
// PersistentPostRunE: PersistentPostRun but returns an error.
129
138
PersistentPostRunE func (cmd * Command , args []string ) error
130
139
140
+ // groups for subcommands
141
+ commandgroups []* Group
142
+
131
143
// args is actual args parsed from flags.
132
144
args []string
133
145
// flagErrorBuf contains all error messages from pflag.
@@ -160,6 +172,12 @@ type Command struct {
160
172
// helpCommand is command with usage 'help'. If it's not defined by user,
161
173
// cobra uses default help command.
162
174
helpCommand * Command
175
+ // helpCommandGroupID is the group id for the helpCommand
176
+ helpCommandGroupID string
177
+
178
+ // completionCommandGroupID is the group id for the completion command
179
+ completionCommandGroupID string
180
+
163
181
// versionTemplate is the version template defined by user.
164
182
versionTemplate string
165
183
@@ -303,6 +321,21 @@ func (c *Command) SetHelpCommand(cmd *Command) {
303
321
c .helpCommand = cmd
304
322
}
305
323
324
+ // SetHelpCommandGroup sets the group id of the help command.
325
+ func (c * Command ) SetHelpCommandGroupID (groupID string ) {
326
+ if c .helpCommand != nil {
327
+ c .helpCommand .GroupID = groupID
328
+ }
329
+ // helpCommandGroupID is used if no helpCommand is defined by the user
330
+ c .helpCommandGroupID = groupID
331
+ }
332
+
333
+ // SetCompletionCommandGroup sets the group id of the completion command.
334
+ func (c * Command ) SetCompletionCommandGroupID (groupID string ) {
335
+ // completionCommandGroupID is used if no completion command is defined by the user
336
+ c .Root ().completionCommandGroupID = groupID
337
+ }
338
+
306
339
// SetHelpTemplate sets help template to be used. Application can use it to set custom template.
307
340
func (c * Command ) SetHelpTemplate (s string ) {
308
341
c .helpTemplate = s
@@ -511,10 +544,16 @@ Aliases:
511
544
{{.NameAndAliases}}{{end}}{{if .HasExample}}
512
545
513
546
Examples:
514
- {{.Example}}{{end}}{{if .HasAvailableSubCommands}}
547
+ {{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}}
548
+
549
+ Available Commands:{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
550
+ {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}}
515
551
516
- Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
517
- {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
552
+ {{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}}
553
+ {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}}
554
+
555
+ Additional Commands:{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}}
556
+ {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
518
557
519
558
Flags:
520
559
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
@@ -1140,6 +1179,7 @@ Simply type ` + c.Name() + ` help [path to command] for full details.`,
1140
1179
CheckErr (cmd .Help ())
1141
1180
}
1142
1181
},
1182
+ GroupID : c .helpCommandGroupID ,
1143
1183
}
1144
1184
}
1145
1185
c .RemoveCommand (c .helpCommand )
@@ -1178,6 +1218,10 @@ func (c *Command) AddCommand(cmds ...*Command) {
1178
1218
panic ("Command can't be a child of itself" )
1179
1219
}
1180
1220
cmds [i ].parent = c
1221
+ // if Group is not defined let the developer know right away
1222
+ if x .GroupID != "" && ! c .ContainsGroup (x .GroupID ) {
1223
+ panic (fmt .Sprintf ("Group id '%s' is not defined for subcommand '%s'" , x .GroupID , cmds [i ].CommandPath ()))
1224
+ }
1181
1225
// update max lengths
1182
1226
usageLen := len (x .Use )
1183
1227
if usageLen > c .commandsMaxUseLen {
@@ -1200,6 +1244,36 @@ func (c *Command) AddCommand(cmds ...*Command) {
1200
1244
}
1201
1245
}
1202
1246
1247
+ // Groups returns a slice of child command groups.
1248
+ func (c * Command ) Groups () []* Group {
1249
+ return c .commandgroups
1250
+ }
1251
+
1252
+ // AllChildCommandsHaveGroup returns if all subcommands are assigned to a group
1253
+ func (c * Command ) AllChildCommandsHaveGroup () bool {
1254
+ for _ , sub := range c .commands {
1255
+ if (sub .IsAvailableCommand () || sub == c .helpCommand ) && sub .GroupID == "" {
1256
+ return false
1257
+ }
1258
+ }
1259
+ return true
1260
+ }
1261
+
1262
+ // ContainGroups return if groupID exists in the list of command groups.
1263
+ func (c * Command ) ContainsGroup (groupID string ) bool {
1264
+ for _ , x := range c .commandgroups {
1265
+ if x .ID == groupID {
1266
+ return true
1267
+ }
1268
+ }
1269
+ return false
1270
+ }
1271
+
1272
+ // AddGroup adds one or more command groups to this parent command.
1273
+ func (c * Command ) AddGroup (groups ... * Group ) {
1274
+ c .commandgroups = append (c .commandgroups , groups ... )
1275
+ }
1276
+
1203
1277
// RemoveCommand removes one or more commands from a parent command.
1204
1278
func (c * Command ) RemoveCommand (cmds ... * Command ) {
1205
1279
commands := []* Command {}
0 commit comments