// describeCommandUsage describes a command's usage. func describeCommandUsage(app *Application, cmd *Command, args []parameters.Argument, opts []parameters.Option) string { desc := "USAGE:\n" desc += fmt.Sprintf( " %s %s", app.UsageName, cmd.Name, ) if len(opts) > 0 { desc += " [OPTIONS...]" } if len(args) > 0 { for _, arg := range args { lb := "" rb := "" if !arg.Required { lb = "[" rb = "]" } desc += fmt.Sprintf(" %s%s%s", lb, arg.Name, rb) } } if cmd.Description != "" { wrapper := wordwrap.Wrapper(78, true) desc += "\n\n" + wordwrap.Indent(wrapper(cmd.Description), " ", true) } return desc }
// DescribeApplication describes an Application to provide usage information. func DescribeApplication(app *Application) string { var help string if app.Logo != "" { help += fmt.Sprintf("%s\n", app.Logo) } help += fmt.Sprintf("%s version %s\n\n", app.Name, app.Version) help += fmt.Sprintf("%s\n", describeApplicationUsage(app)) options := findApplicationOptions(app) if len(options) > 0 { help += fmt.Sprintf("\n%s", parameters.DescribeOptions(options)) } if len(app.Commands) > 0 { help += fmt.Sprintf("\n%s", DescribeCommands(app.Commands)) help += fmt.Sprintf( "\n Run `$ %s COMMAND --help` for more information about a command.\n", app.UsageName, ) } if len(app.Help) > 0 { help += "\nHELP:\n" help += wordwrap.Indent(app.Help, " ", true) + "\n" } return help }
// DescribeArguments describes an array of Arguments, formatting them in a helpful way. func DescribeArguments(arguments []Argument) string { desc := "ARGUMENTS:\n" // Create array and map for specific output ordering argDescKeys := []string{} argDescMap := make(map[string]string) // Generate the list of names and description to allow specific output ordering. for _, arg := range arguments { argDescKeys = append(argDescKeys, arg.Name) argDescMap[arg.Name] = arg.Description } // Sort option names, so they are output in alphabetical order. sort.Sort(argumentNameSort(argDescKeys)) // Find maximum option names width for spacing. var width int for _, name := range argDescKeys { len := len(name) if len+2 > width { width = len + 2 } } for _, names := range argDescKeys { // Get space for the right-side of the command name. spacing := width - len(names) // Wrap the description onto new lines if necessary. wrapper := wordwrap.Wrapper(78-width, true) wrapped := wrapper(argDescMap[names]) // Indent and prefix to product the result. prefix := fmt.Sprintf(" %s%s", names, strings.Repeat(" ", spacing)) desc += wordwrap.Indent(wrapped, prefix, false) + "\n" } return desc }
// DescribeCommands describes an array of Commands to provide usage information. func DescribeCommands(commands []Command) string { desc := "COMMANDS:\n" // Create array and map for specific output ordering. cmdKeys := []string{} cmdMap := make(map[string]Command) var width int for _, cmd := range commands { cmdKeys = append(cmdKeys, cmd.Name) cmdMap[cmd.Name] = cmd len := len(cmd.Name) if len > width { width = len + 2 } } sort.Strings(cmdKeys) for _, name := range cmdKeys { cmd := cmdMap[name] // Get space for the right-side of the command name. spacing := width - len(name) // Wrap the description onto new lines if necessary. wrapper := wordwrap.Wrapper(78-width, true) wrapped := wrapper(cmd.Description) // Indent and prefix to produce the result. prefix := fmt.Sprintf(" %s%s", cmd.Name, strings.Repeat(" ", spacing)) desc += wordwrap.Indent(wrapped, prefix, false) + "\n" } return desc }
// DescribeCommand describes a Command on an Application to provide usage information. func DescribeCommand(app *Application, cmd *Command) string { var help string arguments := findCommandArguments(cmd) options := findCommandOptions(app, cmd) help += fmt.Sprintf("%s\n", describeCommandUsage(app, cmd, arguments, options)) if len(arguments) > 0 { help += fmt.Sprintf("\n%s", parameters.DescribeArguments(arguments)) } if len(options) > 0 { help += fmt.Sprintf("\n%s", parameters.DescribeOptions(options)) } if len(cmd.Help) > 0 { help += "\nHELP:\n" help += wordwrap.Indent(cmd.Help, " ", true) + "\n" } return help }
// DescribeOptions describes an array of Options, formatting them in a helpful way. func DescribeOptions(options []Option) string { desc := "OPTIONS:\n" // Create array and map for specific output ordering optDescKeys := []string{} optDescMap := make(map[string]string) // Generate the list of names, so that output can be formatted correctly, and in the correct // order (i.e. alphabetical), and with sorted names for each option individually. for _, opt := range options { var names []string for _, name := range opt.Names { if len(name) > 1 { name = "--" + name } else { name = "-" + name } names = append(names, name) } // Sort the names so that short names appear first in the output. sort.Sort(stringLengthSort(names)) // Join the names into on comma-separated string. key := strings.Join(names, ", ") // Describe option value if opt.ValueMode == OptionValueOptional { key += "[" } if opt.ValueMode == OptionValueOptional || opt.ValueMode == OptionValueRequired { key += "=" + opt.ValueName } if opt.ValueMode == OptionValueOptional { key += "]" } optDescKeys = append(optDescKeys, key) optDescMap[key] = opt.Description } // Sort option names, so they are output in alphabetical order. sort.Sort(optionNameSort(optDescKeys)) // Find maximum option names width for spacing. var width int for _, names := range optDescKeys { len := len(names) if len+2 > width { width = len + 2 } } for _, names := range optDescKeys { // Get space for the right-side of the command name. spacing := width - len(names) // Wrap the description onto new lines if necessary. wrapper := wordwrap.Wrapper(78-width, true) wrapped := wrapper(optDescMap[names]) // Indent and prefix to product the result. prefix := fmt.Sprintf(" %s%s", names, strings.Repeat(" ", spacing)) desc += wordwrap.Indent(wrapped, prefix, false) + "\n" } return desc }