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