@@ -28,16 +28,20 @@ const (
2828)
2929
3030type helpFields struct {
31- Indent string
32- Usage string
33- Path string
34- Tagline string
35- Arguments string
36- Options string
37- Synopsis string
38- Subcommands string
39- Description string
40- MoreHelp bool
31+ Indent string
32+ Warning string
33+ Usage string
34+ Path string
35+ Tagline string
36+ Arguments string
37+ Options string
38+ Synopsis string
39+ Subcommands string
40+ ExperimentalSubcommands string
41+ DeprecatedSubcommands string
42+ RemovedSubcommands string
43+ Description string
44+ MoreHelp bool
4145}
4246
4347// TrimNewlines removes extra newlines from fields. This makes aligning
@@ -50,12 +54,16 @@ type helpFields struct {
5054// `
5155func (f * helpFields ) TrimNewlines () {
5256 f .Path = strings .Trim (f .Path , "\n " )
57+ f .Warning = strings .Trim (f .Warning , "\n " )
5358 f .Usage = strings .Trim (f .Usage , "\n " )
5459 f .Tagline = strings .Trim (f .Tagline , "\n " )
5560 f .Arguments = strings .Trim (f .Arguments , "\n " )
5661 f .Options = strings .Trim (f .Options , "\n " )
5762 f .Synopsis = strings .Trim (f .Synopsis , "\n " )
5863 f .Subcommands = strings .Trim (f .Subcommands , "\n " )
64+ f .ExperimentalSubcommands = strings .Trim (f .ExperimentalSubcommands , "\n " )
65+ f .DeprecatedSubcommands = strings .Trim (f .DeprecatedSubcommands , "\n " )
66+ f .RemovedSubcommands = strings .Trim (f .RemovedSubcommands , "\n " )
5967 f .Description = strings .Trim (f .Description , "\n " )
6068}
6169
@@ -68,15 +76,21 @@ func (f *helpFields) IndentAll() {
6876 return indentString (s , indentStr )
6977 }
7078
79+ f .Warning = indent (f .Warning )
7180 f .Usage = indent (f .Usage )
7281 f .Arguments = indent (f .Arguments )
7382 f .Options = indent (f .Options )
7483 f .Synopsis = indent (f .Synopsis )
7584 f .Subcommands = indent (f .Subcommands )
85+ f .DeprecatedSubcommands = indent (f .DeprecatedSubcommands )
86+ f .ExperimentalSubcommands = indent (f .ExperimentalSubcommands )
87+ f .RemovedSubcommands = indent (f .RemovedSubcommands )
7688 f .Description = indent (f .Description )
7789}
7890
79- const longHelpFormat = `USAGE
91+ const longHelpFormat = `{{if .Warning}}WARNING: {{.Warning}}
92+
93+ {{end}}USAGE
8094{{.Usage}}
8195
8296{{if .Synopsis}}SYNOPSIS
@@ -99,9 +113,21 @@ const longHelpFormat = `USAGE
99113
100114{{.Indent}}For more information about each command, use:
101115{{.Indent}}'{{.Path}} <subcmd> --help'
116+
117+ {{end}}{{if .ExperimentalSubcommands}}EXPERIMENTAL SUBCOMMANDS
118+ {{.ExperimentalSubcommands}}
119+
120+ {{end}}{{if .DeprecatedSubcommands}}DEPRECATED SUBCOMMANDS
121+ {{.DeprecatedSubcommands}}
122+
123+ {{end}}{{if .RemovedSubcommands}}REMOVED SUBCOMMANDS
124+ {{.RemovedSubcommands}}
125+
102126{{end}}
103127`
104- const shortHelpFormat = `USAGE
128+ const shortHelpFormat = `{{if .Warning}}WARNING: {{.Warning}}
129+
130+ {{end}}USAGE
105131{{.Usage}}
106132{{if .Synopsis}}
107133{{.Synopsis}}
@@ -113,6 +139,16 @@ SUBCOMMANDS
113139{{end}}{{if .MoreHelp}}
114140{{.Indent}}For more information about each command, use:
115141{{.Indent}}'{{.Path}} <subcmd> --help'
142+
143+ {{end}}{{if .ExperimentalSubcommands}}EXPERIMENTAL SUBCOMMANDS
144+ {{.ExperimentalSubcommands}}
145+
146+ {{end}}{{if .DeprecatedSubcommands}}DEPRECATED SUBCOMMANDS
147+ {{.DeprecatedSubcommands}}
148+
149+ {{end}}{{if .RemovedSubcommands}}REMOVED SUBCOMMANDS
150+ {{.RemovedSubcommands}}
151+
116152{{end}}
117153`
118154
@@ -188,6 +224,7 @@ func LongHelp(rootName string, root *cmds.Command, path []string, out io.Writer)
188224 }
189225
190226 // autogen fields that are empty
227+ fields .Warning = generateWarningText (cmd )
191228 if len (cmd .Helptext .Usage ) > 0 {
192229 fields .Usage = cmd .Helptext .Usage
193230 } else {
@@ -200,7 +237,10 @@ func LongHelp(rootName string, root *cmds.Command, path []string, out io.Writer)
200237 fields .Options = strings .Join (optionText (width , cmd ), "\n " )
201238 }
202239 if len (fields .Subcommands ) == 0 {
203- fields .Subcommands = strings .Join (subcommandText (width , cmd , rootName , path ), "\n " )
240+ fields .Subcommands = strings .Join (subcommandText (width , cmd , rootName , path , cmds .Active ), "\n " )
241+ fields .ExperimentalSubcommands = strings .Join (subcommandText (width , cmd , rootName , path , cmds .Experimental ), "\n " )
242+ fields .DeprecatedSubcommands = strings .Join (subcommandText (width , cmd , rootName , path , cmds .Deprecated ), "\n " )
243+ fields .RemovedSubcommands = strings .Join (subcommandText (width , cmd , rootName , path , cmds .Removed ), "\n " )
204244 }
205245 if len (fields .Synopsis ) == 0 {
206246 fields .Synopsis = generateSynopsis (width , cmd , pathStr )
@@ -245,13 +285,17 @@ func ShortHelp(rootName string, root *cmds.Command, path []string, out io.Writer
245285 width := getTerminalWidth (out ) - len (indentStr )
246286
247287 // autogen fields that are empty
288+ fields .Warning = generateWarningText (cmd )
248289 if len (cmd .Helptext .Usage ) > 0 {
249290 fields .Usage = cmd .Helptext .Usage
250291 } else {
251292 fields .Usage = commandUsageText (width , cmd , rootName , path )
252293 }
253294 if len (fields .Subcommands ) == 0 {
254- fields .Subcommands = strings .Join (subcommandText (width , cmd , rootName , path ), "\n " )
295+ fields .Subcommands = strings .Join (subcommandText (width , cmd , rootName , path , cmds .Active ), "\n " )
296+ fields .ExperimentalSubcommands = strings .Join (subcommandText (width , cmd , rootName , path , cmds .Experimental ), "\n " )
297+ fields .DeprecatedSubcommands = strings .Join (subcommandText (width , cmd , rootName , path , cmds .Deprecated ), "\n " )
298+ fields .RemovedSubcommands = strings .Join (subcommandText (width , cmd , rootName , path , cmds .Removed ), "\n " )
255299 }
256300 if len (fields .Synopsis ) == 0 {
257301 fields .Synopsis = generateSynopsis (width , cmd , pathStr )
@@ -409,24 +453,28 @@ func optionText(width int, cmd ...*cmds.Command) []string {
409453 return lines
410454}
411455
412- func subcommandText (width int , cmd * cmds.Command , rootName string , path []string ) []string {
456+ func subcommandText (width int , cmd * cmds.Command , rootName string , path []string , status cmds. Status ) []string {
413457 prefix := fmt .Sprintf ("%v %v" , rootName , strings .Join (path , " " ))
414458 if len (path ) > 0 {
415459 prefix += " "
416460 }
417461
462+ subCmds := make (map [string ]* cmds.Command , len (cmd .Subcommands ))
418463 // Sorting fixes changing order bug #2981.
419464 sortedNames := make ([]string , 0 )
420- for name := range cmd .Subcommands {
421- sortedNames = append (sortedNames , name )
465+ for name , c := range cmd .Subcommands {
466+ if c .Status == status {
467+ sortedNames = append (sortedNames , name )
468+ subCmds [name ] = c
469+ }
422470 }
423471 sort .Strings (sortedNames )
424472
425- subcmds := make ([]* cmds.Command , len (cmd . Subcommands ))
426- lines := make ([]string , len (cmd . Subcommands ))
473+ subcmds := make ([]* cmds.Command , len (subCmds ))
474+ lines := make ([]string , len (subCmds ))
427475
428476 for i , name := range sortedNames {
429- sub := cmd . Subcommands [name ]
477+ sub := subCmds [name ]
430478 usage := usageText (sub )
431479 if len (usage ) > 0 {
432480 usage = " " + usage
@@ -445,6 +493,23 @@ func subcommandText(width int, cmd *cmds.Command, rootName string, path []string
445493 return lines
446494}
447495
496+ // Text printed at the beginning of --help,
497+ // after 'WARNING: ' tag at the start of the command.
498+ func generateWarningText (cmd * cmds.Command ) string {
499+ switch cmd .Status {
500+ case cmds .Active :
501+ return "" // We don't print a warning for a normal active command.
502+ case cmds .Deprecated :
503+ return "DEPRECATED, command will be removed in the future"
504+ case cmds .Experimental :
505+ return "EXPERIMENTAL, command may change in future releases"
506+ case cmds .Removed :
507+ return "REMOVED, command is no longer available"
508+ default :
509+ panic ("unknown command status" )
510+ }
511+ }
512+
448513func commandUsageText (width int , cmd * cmds.Command , rootName string , path []string ) string {
449514 text := fmt .Sprintf ("%v %v" , rootName , strings .Join (path , " " ))
450515 argUsage := usageText (cmd )
0 commit comments