github.com/docker/docker-ce@v17.12.1-ce-rc2+incompatible/components/engine/cli/cobra.go (about)

     1  package cli
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/docker/docker/pkg/term"
     8  	"github.com/pkg/errors"
     9  	"github.com/spf13/cobra"
    10  )
    11  
    12  // SetupRootCommand sets default usage, help, and error handling for the
    13  // root command.
    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)
    20  
    21  	rootCmd.SetUsageTemplate(usageTemplate)
    22  	rootCmd.SetHelpTemplate(helpTemplate)
    23  	rootCmd.SetFlagErrorFunc(FlagErrorFunc)
    24  	rootCmd.SetHelpCommand(helpCommand)
    25  
    26  	rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage")
    27  	rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help")
    28  }
    29  
    30  // FlagErrorFunc prints an error message which matches the format of the
    31  // docker/docker/cli error messages
    32  func FlagErrorFunc(cmd *cobra.Command, err error) error {
    33  	if err == nil {
    34  		return nil
    35  	}
    36  
    37  	usage := ""
    38  	if cmd.HasSubCommands() {
    39  		usage = "\n\n" + cmd.UsageString()
    40  	}
    41  	return StatusError{
    42  		Status:     fmt.Sprintf("%s\nSee '%s --help'.%s", err, cmd.CommandPath(), usage),
    43  		StatusCode: 125,
    44  	}
    45  }
    46  
    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, " "))
    56  		}
    57  
    58  		helpFunc := cmd.HelpFunc()
    59  		helpFunc(cmd, args)
    60  		return nil
    61  	},
    62  }
    63  
    64  func hasSubCommands(cmd *cobra.Command) bool {
    65  	return len(operationSubCommands(cmd)) > 0
    66  }
    67  
    68  func hasManagementSubCommands(cmd *cobra.Command) bool {
    69  	return len(managementSubCommands(cmd)) > 0
    70  }
    71  
    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)
    77  		}
    78  	}
    79  	return cmds
    80  }
    81  
    82  func wrappedFlagUsages(cmd *cobra.Command) string {
    83  	width := 80
    84  	if ws, err := term.GetWinsize(0); err == nil {
    85  		width = int(ws.Width)
    86  	}
    87  	return cmd.Flags().FlagUsagesWrapped(width - 1)
    88  }
    89  
    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)
    95  		}
    96  	}
    97  	return cmds
    98  }
    99  
   100  var usageTemplate = `Usage:
   101  
   102  {{- if not .HasSubCommands}}	{{.UseLine}}{{end}}
   103  {{- if .HasSubCommands}}	{{ .CommandPath}} COMMAND{{end}}
   104  
   105  {{ .Short | trim }}
   106  
   107  {{- if gt .Aliases 0}}
   108  
   109  Aliases:
   110    {{.NameAndAliases}}
   111  
   112  {{- end}}
   113  {{- if .HasExample}}
   114  
   115  Examples:
   116  {{ .Example }}
   117  
   118  {{- end}}
   119  {{- if .HasFlags}}
   120  
   121  Options:
   122  {{ wrappedFlagUsages . | trimRightSpace}}
   123  
   124  {{- end}}
   125  {{- if hasManagementSubCommands . }}
   126  
   127  Management Commands:
   128  
   129  {{- range managementSubCommands . }}
   130    {{rpad .Name .NamePadding }} {{.Short}}
   131  {{- end}}
   132  
   133  {{- end}}
   134  {{- if hasSubCommands .}}
   135  
   136  Commands:
   137  
   138  {{- range operationSubCommands . }}
   139    {{rpad .Name .NamePadding }} {{.Short}}
   140  {{- end}}
   141  {{- end}}
   142  
   143  {{- if .HasSubCommands }}
   144  
   145  Run '{{.CommandPath}} COMMAND --help' for more information on a command.
   146  {{- end}}
   147  `
   148  
   149  var helpTemplate = `
   150  {{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`