diff --git a/go.mod b/go.mod index 1b0478035052bc994bb56c84ab222d9ff7e5f2bd..75e5be586496a16aa20375ef7557d4d000349a26 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.14 require ( github.com/blevesearch/bleve v1.0.14 github.com/glycerine/go-unsnap-stream v0.0.0-20190730064659-98d31706395a // indirect - github.com/google/subcommands v1.0.1 + github.com/google/subcommands v1.2.0 github.com/gorilla/mux v1.6.3-0.20181030152528-3d80bc801bb0 github.com/meskio/epubgo v0.0.0-20160213181628-90dd5d78197f github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 diff --git a/go.sum b/go.sum index 18d8077be60dc97bae6ae544494313d61588f74e..ccf4467068fc7b19686990a1bcdfa38e440c1bac 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k= -github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw= github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.6.3-0.20181030152528-3d80bc801bb0 h1:lkoCFKD1IVH+yARHTUkCerTOqKkwVVO+IyGWld86voc= diff --git a/vendor/github.com/google/subcommands/subcommands.go b/vendor/github.com/google/subcommands/subcommands.go index 9cb98e5cce7595789e5df569148596e977cd707d..39268f7362faf5b85bdeb764be91a91a0f806f5d 100644 --- a/vendor/github.com/google/subcommands/subcommands.go +++ b/vendor/github.com/google/subcommands/subcommands.go @@ -50,21 +50,30 @@ type Command interface { // A Commander represents a set of commands. type Commander struct { - commands []*commandGroup + commands []*CommandGroup topFlags *flag.FlagSet // top-level flags important []string // important top-level flags name string // normally path.Base(os.Args[0]) + Explain func(io.Writer) // A function to print a top level usage explanation. Can be overridden. + ExplainGroup func(io.Writer, *CommandGroup) // A function to print a command group's usage explanation. Can be overridden. + ExplainCommand func(io.Writer, Command) // A function to print a command usage explanation. Can be overridden. + Output io.Writer // Output specifies where the commander should write its output (default: os.Stdout). Error io.Writer // Error specifies where the commander should write its error (default: os.Stderr). } -// A commandGroup represents a set of commands about a common topic. -type commandGroup struct { +// A CommandGroup represents a set of commands about a common topic. +type CommandGroup struct { name string commands []Command } +// Name returns the group name +func (g *CommandGroup) Name() string { + return g.name +} + // An ExitStatus represents a Posix exit status that a subcommand // expects to be returned to the shell. type ExitStatus int @@ -85,10 +94,19 @@ func NewCommander(topLevelFlags *flag.FlagSet, name string) *Commander { Output: os.Stdout, Error: os.Stderr, } - topLevelFlags.Usage = func() { cdr.explain(cdr.Error) } + + cdr.Explain = cdr.explain + cdr.ExplainGroup = explainGroup + cdr.ExplainCommand = explain + topLevelFlags.Usage = func() { cdr.Explain(cdr.Error) } return cdr } +// Name returns the commander's name +func (cdr *Commander) Name() string { + return cdr.name +} + // Register adds a subcommand to the supported subcommands in the // specified group. (Help output is sorted and arranged by group name.) // The empty string is an acceptable group name; such subcommands are @@ -100,7 +118,7 @@ func (cdr *Commander) Register(cmd Command, group string) { return } } - cdr.commands = append(cdr.commands, &commandGroup{ + cdr.commands = append(cdr.commands, &CommandGroup{ name: group, commands: []Command{cmd}, }) @@ -114,6 +132,55 @@ func (cdr *Commander) ImportantFlag(name string) { cdr.important = append(cdr.important, name) } +// VisitGroups visits each command group in lexicographical order, calling +// fn for each. +func (cdr *Commander) VisitGroups(fn func(*CommandGroup)) { + sort.Sort(byGroupName(cdr.commands)) + for _, g := range cdr.commands { + fn(g) + } +} + +// VisitCommands visits each command in registered order grouped by +// command group in lexicographical order, calling fn for each. +func (cdr *Commander) VisitCommands(fn func(*CommandGroup, Command)) { + cdr.VisitGroups(func(g *CommandGroup) { + for _, cmd := range g.commands { + fn(g, cmd) + } + }) +} + +// VisitAllImportant visits the important top level flags in lexicographical +// order, calling fn for each. It visits all flags, even those not set. +func (cdr *Commander) VisitAllImportant(fn func(*flag.Flag)) { + sort.Strings(cdr.important) + for _, name := range cdr.important { + f := cdr.topFlags.Lookup(name) + if f == nil { + panic(fmt.Sprintf("Important flag (%s) is not defined", name)) + } + fn(f) + } +} + +// VisitAll visits the top level flags in lexicographical order, calling fn +// for each. It visits all flags, even those not set. +func (cdr *Commander) VisitAll(fn func(*flag.Flag)) { + if cdr.topFlags != nil { + cdr.topFlags.VisitAll(fn) + } +} + +// countFlags returns the number of top-level flags defined, even those not set. +func (cdr *Commander) countTopFlags() int { + count := 0 + cdr.VisitAll(func(*flag.Flag) { + count++ + }) + return count +} + // Execute should be called once the top-level-flags on a Commander // have been initialized. It finds the correct subcommand and executes // it, and returns an ExitStatus with the result. On a usage error, an @@ -134,7 +201,7 @@ func (cdr *Commander) Execute(ctx context.Context, args ...interface{}) ExitStat continue } f := flag.NewFlagSet(name, flag.ContinueOnError) - f.Usage = func() { explain(cdr.Error, cmd) } + f.Usage = func() { cdr.ExplainCommand(cdr.Error, cmd) } cmd.SetFlags(f) if f.Parse(cdr.topFlags.Args()[1:]) != nil { return ExitUsageError @@ -149,8 +216,9 @@ func (cdr *Commander) Execute(ctx context.Context, args ...interface{}) ExitStat } // Sorting of a slice of command groups. -type byGroupName []*commandGroup +type byGroupName []*CommandGroup +// TODO Sort by function rather than implement sortable? func (p byGroupName) Len() int { return len(p) } func (p byGroupName) Less(i, j int) bool { return p[i].name < p[j].name } func (p byGroupName) Swap(i, j int) { p[i], p[j] = p[j], p[i] } @@ -161,14 +229,18 @@ func (cdr *Commander) explain(w io.Writer) { fmt.Fprintf(w, "Usage: %s <flags> <subcommand> <subcommand args>\n\n", cdr.name) sort.Sort(byGroupName(cdr.commands)) for _, group := range cdr.commands { - explainGroup(w, group) + cdr.ExplainGroup(w, group) } if cdr.topFlags == nil { fmt.Fprintln(w, "\nNo top level flags.") return } + + sort.Strings(cdr.important) if len(cdr.important) == 0 { - fmt.Fprintf(w, "\nUse \"%s flags\" for a list of top-level flags\n", cdr.name) + if cdr.countTopFlags() > 0 { + fmt.Fprintf(w, "\nUse \"%s flags\" for a list of top-level flags\n", cdr.name) + } return } @@ -183,12 +255,12 @@ func (cdr *Commander) explain(w io.Writer) { } // Sorting of the commands within a group. -func (g commandGroup) Len() int { return len(g.commands) } -func (g commandGroup) Less(i, j int) bool { return g.commands[i].Name() < g.commands[j].Name() } -func (g commandGroup) Swap(i, j int) { g.commands[i], g.commands[j] = g.commands[j], g.commands[i] } +func (g CommandGroup) Len() int { return len(g.commands) } +func (g CommandGroup) Less(i, j int) bool { return g.commands[i].Name() < g.commands[j].Name() } +func (g CommandGroup) Swap(i, j int) { g.commands[i], g.commands[j] = g.commands[j], g.commands[i] } // explainGroup explains all the subcommands for a particular group. -func explainGroup(w io.Writer, group *commandGroup) { +func explainGroup(w io.Writer, group *CommandGroup) { if len(group.commands) == 0 { return } @@ -254,7 +326,7 @@ func (h *helper) Usage() string { func (h *helper) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) ExitStatus { switch f.NArg() { case 0: - (*Commander)(h).explain(h.Output) + (*Commander)(h).Explain(h.Output) return ExitSuccess case 1: @@ -263,7 +335,7 @@ func (h *helper) Execute(_ context.Context, f *flag.FlagSet, args ...interface{} if f.Arg(0) != cmd.Name() { continue } - explain(h.Output, cmd) + (*Commander)(h).ExplainCommand(h.Output, cmd) return ExitSuccess } } diff --git a/vendor/modules.txt b/vendor/modules.txt index 62c6d898b95d50d4cdc1eff8337a105e8d2d9d3a..da68b523ac661e1d6c6cffbeac3fca7e716078a0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -76,7 +76,7 @@ github.com/glycerine/go-unsnap-stream github.com/golang/protobuf/proto # github.com/golang/snappy v0.0.1 github.com/golang/snappy -# github.com/google/subcommands v1.0.1 +# github.com/google/subcommands v1.2.0 ## explicit github.com/google/subcommands # github.com/gorilla/mux v1.6.3-0.20181030152528-3d80bc801bb0