7 "github.com/docker/docker/pkg/term"
8 "github.com/pkg/errors"
9 "github.com/spf13/cobra"
12 // SetupRootCommand sets default usage, help, and error handling for the
14 func SetupRootCommand(rootCmd *cobra.Command) {
15 cobra.AddTemplateFunc("hasSubCommands", hasSubCommands)
16 cobra.AddTemplateFunc("hasManagementSubCommands", hasManagementSubCommands)
17 cobra.AddTemplateFunc("operationSubCommands", operationSubCommands)
18 cobra.AddTemplateFunc("managementSubCommands", managementSubCommands)
19 cobra.AddTemplateFunc("wrappedFlagUsages", wrappedFlagUsages)
21 rootCmd.SetUsageTemplate(usageTemplate)
22 rootCmd.SetHelpTemplate(helpTemplate)
23 rootCmd.SetFlagErrorFunc(FlagErrorFunc)
24 rootCmd.SetHelpCommand(helpCommand)
26 rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage")
27 rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help")
30 // FlagErrorFunc prints an error message which matches the format of the
31 // docker/cli/cli error messages
32 func FlagErrorFunc(cmd *cobra.Command, err error) error {
38 if cmd.HasSubCommands() {
39 usage = "\n\n" + cmd.UsageString()
42 Status: fmt.Sprintf("%s\nSee '%s --help'.%s", err, cmd.CommandPath(), usage),
47 var helpCommand = &cobra.Command{
48 Use: "help [command]",
49 Short: "Help about the command",
50 PersistentPreRun: func(cmd *cobra.Command, args []string) {},
51 PersistentPostRun: func(cmd *cobra.Command, args []string) {},
52 RunE: func(c *cobra.Command, args []string) error {
53 cmd, args, e := c.Root().Find(args)
54 if cmd == nil || e != nil || len(args) > 0 {
55 return errors.Errorf("unknown help topic: %v", strings.Join(args, " "))
58 helpFunc := cmd.HelpFunc()
64 func hasSubCommands(cmd *cobra.Command) bool {
65 return len(operationSubCommands(cmd)) > 0
68 func hasManagementSubCommands(cmd *cobra.Command) bool {
69 return len(managementSubCommands(cmd)) > 0
72 func operationSubCommands(cmd *cobra.Command) []*cobra.Command {
73 cmds := []*cobra.Command{}
74 for _, sub := range cmd.Commands() {
75 if sub.IsAvailableCommand() && !sub.HasSubCommands() {
76 cmds = append(cmds, sub)
82 func wrappedFlagUsages(cmd *cobra.Command) string {
84 if ws, err := term.GetWinsize(0); err == nil {
87 return cmd.Flags().FlagUsagesWrapped(width - 1)
90 func managementSubCommands(cmd *cobra.Command) []*cobra.Command {
91 cmds := []*cobra.Command{}
92 for _, sub := range cmd.Commands() {
93 if sub.IsAvailableCommand() && sub.HasSubCommands() {
94 cmds = append(cmds, sub)
100 var usageTemplate = `Usage:
102 {{- if not .HasSubCommands}} {{.UseLine}}{{end}}
103 {{- if .HasSubCommands}} {{ .CommandPath}} COMMAND{{end}}
107 {{- if gt .Aliases 0}}
122 {{ wrappedFlagUsages . | trimRightSpace}}
125 {{- if hasManagementSubCommands . }}
129 {{- range managementSubCommands . }}
130 {{rpad .Name .NamePadding }} {{.Short}}
134 {{- if hasSubCommands .}}
138 {{- range operationSubCommands . }}
139 {{rpad .Name .NamePadding }} {{.Short}}
143 {{- if .HasSubCommands }}
145 Run '{{.CommandPath}} COMMAND --help' for more information on a command.
150 {{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`