From 8d5a5220c9b2dfc7c6c1e69d1eaed7bb41079bf5 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Wed, 24 Sep 2025 14:57:58 -0500 Subject: rearrange --- usage.go | 180 +++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/usage.go b/usage.go index d091bcb..c69f2d2 100644 --- a/usage.go +++ b/usage.go @@ -36,96 +36,6 @@ func (p *Parser) WriteUsage(w io.Writer) { p.WriteUsageForSubcommand(w, p.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 (p *Parser) WriteUsageForSubcommand(w io.Writer, subcommand ...string) error { - cmd, err := p.lookupCommand(subcommand...) - if err != nil { - return err - } - - var positionals, longOptions, shortOptions []*spec - for _, spec := range cmd.specs { - switch { - case spec.positional: - positionals = append(positionals, spec) - case spec.long != "": - longOptions = append(longOptions, spec) - case spec.short != "": - shortOptions = append(shortOptions, spec) - } - } - - // print the beginning of the usage string - fmt.Fprintf(w, "Usage: %s", p.cmd.name) - for _, s := range subcommand { - fmt.Fprint(w, " "+s) - } - - // write the option component of the usage message - for _, spec := range shortOptions { - // prefix with a space - fmt.Fprint(w, " ") - if !spec.required { - fmt.Fprint(w, "[") - } - fmt.Fprint(w, synopsis(spec, "-"+spec.short)) - if !spec.required { - fmt.Fprint(w, "]") - } - } - - for _, spec := range longOptions { - // prefix with a space - fmt.Fprint(w, " ") - if !spec.required { - fmt.Fprint(w, "[") - } - fmt.Fprint(w, synopsis(spec, "--"+spec.long)) - if !spec.required { - fmt.Fprint(w, "]") - } - } - - // 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 ...]]] - var closeBrackets int - for _, spec := range positionals { - fmt.Fprint(w, " ") - if !spec.required { - fmt.Fprint(w, "[") - closeBrackets += 1 - } - if spec.cardinality == multiple { - fmt.Fprintf(w, "%s [%s ...]", spec.placeholder, spec.placeholder) - } else { - fmt.Fprint(w, spec.placeholder) - } - } - fmt.Fprint(w, strings.Repeat("]", closeBrackets)) - - // if the program supports subcommands, give a hint to the user about their existence - if len(cmd.subcommands) > 0 { - fmt.Fprint(w, " []") - } - - fmt.Fprint(w, "\n") - return nil -} - // print prints a line like this: // // --option FOO A description of the option [default: 123] @@ -341,3 +251,93 @@ func synopsis(spec *spec, form string) string { } return form + " " + spec.placeholder } + +// 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 (p *Parser) WriteUsageForSubcommand(w io.Writer, subcommand ...string) error { + cmd, err := p.lookupCommand(subcommand...) + if err != nil { + return err + } + + var positionals, longOptions, shortOptions []*spec + for _, spec := range cmd.specs { + switch { + case spec.positional: + positionals = append(positionals, spec) + case spec.long != "": + longOptions = append(longOptions, spec) + case spec.short != "": + shortOptions = append(shortOptions, spec) + } + } + + // print the beginning of the usage string + fmt.Fprintf(w, "Usage: %s", p.cmd.name) + for _, s := range subcommand { + fmt.Fprint(w, " "+s) + } + + // write the option component of the usage message + for _, spec := range shortOptions { + // prefix with a space + fmt.Fprint(w, " ") + if !spec.required { + fmt.Fprint(w, "[") + } + fmt.Fprint(w, synopsis(spec, "-"+spec.short)) + if !spec.required { + fmt.Fprint(w, "]") + } + } + + for _, spec := range longOptions { + // prefix with a space + fmt.Fprint(w, " ") + if !spec.required { + fmt.Fprint(w, "[") + } + fmt.Fprint(w, synopsis(spec, "--"+spec.long)) + if !spec.required { + fmt.Fprint(w, "]") + } + } + + // 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 ...]]] + var closeBrackets int + for _, spec := range positionals { + fmt.Fprint(w, " ") + if !spec.required { + fmt.Fprint(w, "[") + closeBrackets += 1 + } + if spec.cardinality == multiple { + fmt.Fprintf(w, "%s [%s ...]", spec.placeholder, spec.placeholder) + } else { + fmt.Fprint(w, spec.placeholder) + } + } + fmt.Fprint(w, strings.Repeat("]", closeBrackets)) + + // if the program supports subcommands, give a hint to the user about their existence + if len(cmd.subcommands) > 0 { + fmt.Fprint(w, " []") + } + + fmt.Fprint(w, "\n") + return nil +} -- cgit v1.2.3