package argimport ()// the width of the left columnconst colWidth = 25// Fail prints usage information to p.Config.Out and exits with status code 2.func ( *Parser) ( string) { .FailSubcommand()}// FailSubcommand prints usage information for a specified subcommand to p.Config.Out,// then exits with status code 2. To write usage information for a top-level// subcommand, provide just the name of that subcommand. To write usage// information for a subcommand that is nested under another subcommand, provide// a sequence of subcommand names starting with the top-level subcommand and so// on down the tree.func ( *Parser) ( string, ...string) error { := .WriteUsageForSubcommand(.config.Out, ...)if != nil {return }fmt.Fprintln(.config.Out, "error:", ) .config.Exit(2)returnnil}// WriteUsage writes usage information to the given writerfunc ( *Parser) ( io.Writer) { .WriteUsageForSubcommand(, .subcommand...)}// WriteUsageForSubcommand writes the usage information for a specified// subcommand. To write usage information for a top-level subcommand, provide// just the name of that subcommand. To write usage information for a subcommand// that is nested under another subcommand, provide a sequence of subcommand// names starting with the top-level subcommand and so on down the tree.func ( *Parser) ( io.Writer, ...string) error { , := .lookupCommand(...)if != nil {return }var , , []*specfor , := range .specs {switch {case .positional: = append(, )case .long != "": = append(, )case .short != "": = append(, ) } }// print the beginning of the usage stringfmt.Fprintf(, "Usage: %s", .cmd.name)for , := range {fmt.Fprint(, " "+) }// write the option component of the usage messagefor , := range {// prefix with a spacefmt.Fprint(, " ")if !.required {fmt.Fprint(, "[") }fmt.Fprint(, synopsis(, "-"+.short))if !.required {fmt.Fprint(, "]") } }for , := range {// prefix with a spacefmt.Fprint(, " ")if !.required {fmt.Fprint(, "[") }fmt.Fprint(, synopsis(, "--"+.long))if !.required {fmt.Fprint(, "]") } }// When we parse positionals, we check that: // 1. required positionals come before non-required positionals // 2. there is at most one multiple-value positional // 3. if there is a multiple-value positional then it comes after all other positionals // Here we merely print the usage string, so we do not explicitly re-enforce those rules// write the positionals in following form: // REQUIRED1 REQUIRED2 // REQUIRED1 REQUIRED2 [OPTIONAL1 [OPTIONAL2]] // REQUIRED1 REQUIRED2 REPEATED [REPEATED ...] // REQUIRED1 REQUIRED2 [REPEATEDOPTIONAL [REPEATEDOPTIONAL ...]] // REQUIRED1 REQUIRED2 [OPTIONAL1 [REPEATEDOPTIONAL [REPEATEDOPTIONAL ...]]]varintfor , := range {fmt.Fprint(, " ")if !.required {fmt.Fprint(, "[") += 1 }if .cardinality == multiple {fmt.Fprintf(, "%s [%s ...]", .placeholder, .placeholder) } else {fmt.Fprint(, .placeholder) } }fmt.Fprint(, strings.Repeat("]", ))// if the program supports subcommands, give a hint to the user about their existenceiflen(.subcommands) > 0 {fmt.Fprint(, " <command> [<args>]") }fmt.Fprint(, "\n")returnnil}// print prints a line like this://// --option FOO A description of the option [default: 123]//// If the text on the left is longer than a certain threshold, the description is moved to the next line://// --verylongoptionoption VERY_LONG_VARIABLE// A description of the option [default: 123]//// If multiple "extras" are provided then they are put inside a single set of square brackets://// --option FOO A description of the option [default: 123, env: FOO]func print( io.Writer, , string, ...string) { := " " + fmt.Fprint(, )if != "" {iflen()+2 < colWidth {fmt.Fprint(, strings.Repeat(" ", colWidth-len())) } else {fmt.Fprint(, "\n"+strings.Repeat(" ", colWidth)) }fmt.Fprint(, ) }varstringfor , := range {if != "" {if != "" { += ", " } += } }if != "" {fmt.Fprintf(, " [%s]", ) }fmt.Fprint(, "\n")}func withDefault( string) string {if == "" {return"" }return"default: " + }func withEnv( string) string {if == "" {return"" }return"env: " + }// WriteHelp writes the usage string followed by the full help string for each optionfunc ( *Parser) ( io.Writer) { .WriteHelpForSubcommand(, .subcommand...)}// WriteHelpForSubcommand writes the usage string followed by the full help// string for a specified subcommand. To write help for a top-level subcommand,// provide just the name of that subcommand. To write help for a subcommand that// is nested under another subcommand, provide a sequence of subcommand names// starting with the top-level subcommand and so on down the tree.func ( *Parser) ( io.Writer, ...string) error { , := .lookupCommand(...)if != nil {return }var , , , []*specvarboolfor , := range .specs {switch {case .positional: = append(, )case .long != "": = append(, )if .long == "version" { = true }case .short != "": = append(, )case .short == "" && .long == "": = append(, ) } }// obtain a flattened list of options from all ancestors // also determine if any ancestor has a version option specvar []*spec := .parentfor != nil {for , := range .specs {if .long == "version" { = truebreak } } = append(, .specs...) = .parent }if .description != "" {fmt.Fprintln(, .description) }if ! && .version != "" {fmt.Fprintln(, .version) } .WriteUsageForSubcommand(, ...)// write the list of positionalsiflen() > 0 {fmt.Fprint(, "\nPositional arguments:\n")for , := range {print(, .placeholder, .help, withDefault(.defaultString), withEnv(.env)) } }// write the list of options with the short-only ones first to match the usage stringiflen()+len() > 0 || .parent == nil {fmt.Fprint(, "\nOptions:\n")for , := range { .printOption(, ) }for , := range { .printOption(, ) } }// write the list of global optionsiflen() > 0 {fmt.Fprint(, "\nGlobal options:\n")for , := range { .printOption(, ) } }// write the list of built in options .printOption(, &spec{cardinality: zero,long: "help",short: "h",help: "display this help and exit", })if ! && .version != "" { .printOption(, &spec{cardinality: zero,long: "version",help: "display version and exit", }) }// write the list of environment only variablesiflen() > 0 {fmt.Fprint(, "\nEnvironment variables:\n")for , := range { .printEnvOnlyVar(, ) } }// write the list of subcommandsiflen(.subcommands) > 0 {fmt.Fprint(, "\nCommands:\n")for , := range .subcommands { := append([]string{.name}, .aliases...)print(, strings.Join(, ", "), .help) } }if .epilogue != "" {fmt.Fprintln(, "\n"+.epilogue) }returnnil}func ( *Parser) ( io.Writer, *spec) { := make([]string, 0, 2)if .long != "" { = append(, synopsis(, "--"+.long)) }if .short != "" { = append(, synopsis(, "-"+.short)) }iflen() > 0 {print(, strings.Join(, ", "), .help, withDefault(.defaultString), withEnv(.env)) }}func ( *Parser) ( io.Writer, *spec) { := make([]string, 0, 2)if .required { = append(, "Required.") } else { = append(, "Optional.") }if .help != "" { = append(, .help) }print(, .env, strings.Join(, " "), withDefault(.defaultString))}func synopsis( *spec, string) string {// if the user omits the placeholder tag then we pick one automatically, // but if the user explicitly specifies an empty placeholder then we // leave out the placeholder in the help messageif .cardinality == zero || .placeholder == "" {return }return + " " + .placeholder}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.