cobra.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package cli
  2. import (
  3. "fmt"
  4. "github.com/spf13/cobra"
  5. )
  6. // SetupRootCommand sets default usage, help, and error handling for the
  7. // root command.
  8. func SetupRootCommand(rootCmd *cobra.Command) {
  9. cobra.AddTemplateFunc("hasSubCommands", hasSubCommands)
  10. cobra.AddTemplateFunc("hasManagementSubCommands", hasManagementSubCommands)
  11. cobra.AddTemplateFunc("operationSubCommands", operationSubCommands)
  12. cobra.AddTemplateFunc("managementSubCommands", managementSubCommands)
  13. rootCmd.SetUsageTemplate(usageTemplate)
  14. rootCmd.SetHelpTemplate(helpTemplate)
  15. rootCmd.SetFlagErrorFunc(FlagErrorFunc)
  16. rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage")
  17. rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help")
  18. }
  19. // FlagErrorFunc prints an error message which matches the format of the
  20. // docker/docker/cli error messages
  21. func FlagErrorFunc(cmd *cobra.Command, err error) error {
  22. if err == nil {
  23. return err
  24. }
  25. usage := ""
  26. if cmd.HasSubCommands() {
  27. usage = "\n\n" + cmd.UsageString()
  28. }
  29. return StatusError{
  30. Status: fmt.Sprintf("%s\nSee '%s --help'.%s", err, cmd.CommandPath(), usage),
  31. StatusCode: 125,
  32. }
  33. }
  34. func hasSubCommands(cmd *cobra.Command) bool {
  35. return len(operationSubCommands(cmd)) > 0
  36. }
  37. func hasManagementSubCommands(cmd *cobra.Command) bool {
  38. return len(managementSubCommands(cmd)) > 0
  39. }
  40. func operationSubCommands(cmd *cobra.Command) []*cobra.Command {
  41. cmds := []*cobra.Command{}
  42. for _, sub := range cmd.Commands() {
  43. if sub.IsAvailableCommand() && !sub.HasSubCommands() {
  44. cmds = append(cmds, sub)
  45. }
  46. }
  47. return cmds
  48. }
  49. func managementSubCommands(cmd *cobra.Command) []*cobra.Command {
  50. cmds := []*cobra.Command{}
  51. for _, sub := range cmd.Commands() {
  52. if sub.IsAvailableCommand() && sub.HasSubCommands() {
  53. cmds = append(cmds, sub)
  54. }
  55. }
  56. return cmds
  57. }
  58. var usageTemplate = `Usage:
  59. {{- if not .HasSubCommands}} {{.UseLine}}{{end}}
  60. {{- if .HasSubCommands}} {{ .CommandPath}} COMMAND{{end}}
  61. {{ .Short | trim }}
  62. {{- if gt .Aliases 0}}
  63. Aliases:
  64. {{.NameAndAliases}}
  65. {{- end}}
  66. {{- if .HasExample}}
  67. Examples:
  68. {{ .Example }}
  69. {{- end}}
  70. {{- if .HasFlags}}
  71. Options:
  72. {{.Flags.FlagUsages | trimRightSpace}}
  73. {{- end}}
  74. {{- if hasManagementSubCommands . }}
  75. Management Commands:
  76. {{- range managementSubCommands . }}
  77. {{rpad .Name .NamePadding }} {{.Short}}
  78. {{- end}}
  79. {{- end}}
  80. {{- if hasSubCommands .}}
  81. Commands:
  82. {{- range operationSubCommands . }}
  83. {{rpad .Name .NamePadding }} {{.Short}}
  84. {{- end}}
  85. {{- end}}
  86. {{- if .HasSubCommands }}
  87. Run '{{.CommandPath}} COMMAND --help' for more information on a command.
  88. {{- end}}
  89. `
  90. var helpTemplate = `
  91. {{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`