github.com/fabiokung/docker@v0.11.2-0.20170222101415-4534dcd49497/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/spf13/cobra" 9 ) 10 11 // SetupRootCommand sets default usage, help, and error handling for the 12 // root command. 13 func SetupRootCommand(rootCmd *cobra.Command) { 14 cobra.AddTemplateFunc("hasSubCommands", hasSubCommands) 15 cobra.AddTemplateFunc("hasManagementSubCommands", hasManagementSubCommands) 16 cobra.AddTemplateFunc("operationSubCommands", operationSubCommands) 17 cobra.AddTemplateFunc("managementSubCommands", managementSubCommands) 18 cobra.AddTemplateFunc("wrappedFlagUsages", wrappedFlagUsages) 19 20 rootCmd.SetUsageTemplate(usageTemplate) 21 rootCmd.SetHelpTemplate(helpTemplate) 22 rootCmd.SetFlagErrorFunc(FlagErrorFunc) 23 rootCmd.SetHelpCommand(helpCommand) 24 25 rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage") 26 rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help") 27 } 28 29 // FlagErrorFunc prints an error message which matches the format of the 30 // docker/docker/cli error messages 31 func FlagErrorFunc(cmd *cobra.Command, err error) error { 32 if err == nil { 33 return err 34 } 35 36 usage := "" 37 if cmd.HasSubCommands() { 38 usage = "\n\n" + cmd.UsageString() 39 } 40 return StatusError{ 41 Status: fmt.Sprintf("%s\nSee '%s --help'.%s", err, cmd.CommandPath(), usage), 42 StatusCode: 125, 43 } 44 } 45 46 var helpCommand = &cobra.Command{ 47 Use: "help [command]", 48 Short: "Help about the command", 49 PersistentPreRun: func(cmd *cobra.Command, args []string) {}, 50 PersistentPostRun: func(cmd *cobra.Command, args []string) {}, 51 RunE: func(c *cobra.Command, args []string) error { 52 cmd, args, e := c.Root().Find(args) 53 if cmd == nil || e != nil || len(args) > 0 { 54 return fmt.Errorf("unknown help topic: %v", strings.Join(args, " ")) 55 } 56 57 helpFunc := cmd.HelpFunc() 58 helpFunc(cmd, args) 59 return nil 60 }, 61 } 62 63 func hasSubCommands(cmd *cobra.Command) bool { 64 return len(operationSubCommands(cmd)) > 0 65 } 66 67 func hasManagementSubCommands(cmd *cobra.Command) bool { 68 return len(managementSubCommands(cmd)) > 0 69 } 70 71 func operationSubCommands(cmd *cobra.Command) []*cobra.Command { 72 cmds := []*cobra.Command{} 73 for _, sub := range cmd.Commands() { 74 if sub.IsAvailableCommand() && !sub.HasSubCommands() { 75 cmds = append(cmds, sub) 76 } 77 } 78 return cmds 79 } 80 81 func wrappedFlagUsages(cmd *cobra.Command) string { 82 width := 80 83 if ws, err := term.GetWinsize(0); err == nil { 84 width = int(ws.Width) 85 } 86 return cmd.Flags().FlagUsagesWrapped(width - 1) 87 } 88 89 func managementSubCommands(cmd *cobra.Command) []*cobra.Command { 90 cmds := []*cobra.Command{} 91 for _, sub := range cmd.Commands() { 92 if sub.IsAvailableCommand() && sub.HasSubCommands() { 93 cmds = append(cmds, sub) 94 } 95 } 96 return cmds 97 } 98 99 var usageTemplate = `Usage: 100 101 {{- if not .HasSubCommands}} {{.UseLine}}{{end}} 102 {{- if .HasSubCommands}} {{ .CommandPath}} COMMAND{{end}} 103 104 {{ .Short | trim }} 105 106 {{- if gt .Aliases 0}} 107 108 Aliases: 109 {{.NameAndAliases}} 110 111 {{- end}} 112 {{- if .HasExample}} 113 114 Examples: 115 {{ .Example }} 116 117 {{- end}} 118 {{- if .HasFlags}} 119 120 Options: 121 {{ wrappedFlagUsages . | trimRightSpace}} 122 123 {{- end}} 124 {{- if hasManagementSubCommands . }} 125 126 Management Commands: 127 128 {{- range managementSubCommands . }} 129 {{rpad .Name .NamePadding }} {{.Short}} 130 {{- end}} 131 132 {{- end}} 133 {{- if hasSubCommands .}} 134 135 Commands: 136 137 {{- range operationSubCommands . }} 138 {{rpad .Name .NamePadding }} {{.Short}} 139 {{- end}} 140 {{- end}} 141 142 {{- if .HasSubCommands }} 143 144 Run '{{.CommandPath}} COMMAND --help' for more information on a command. 145 {{- end}} 146 ` 147 148 var helpTemplate = ` 149 {{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`