cobra.go 3.0 KB

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