cobra.go 3.2 KB

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