Commit 6a1c3adf authored by renovate's avatar renovate
Browse files

Update module google/subcommands to v1.2.0

parent 110ee7a7
Pipeline #10480 passed with stages
in 1 minute and 48 seconds
...@@ -7,7 +7,7 @@ require ( ...@@ -7,7 +7,7 @@ require (
github.com/cenkalti/backoff v0.0.0-20190506075156-2146c9339422 // indirect github.com/cenkalti/backoff v0.0.0-20190506075156-2146c9339422 // indirect
github.com/coreos/go-systemd v0.0.0-20180828140353-eee3db372b31 // indirect github.com/coreos/go-systemd v0.0.0-20180828140353-eee3db372b31 // indirect
github.com/dustin/go-humanize v0.0.0-20200219035652-afde56e7acac github.com/dustin/go-humanize v0.0.0-20200219035652-afde56e7acac
github.com/google/subcommands v1.0.1 github.com/google/subcommands v1.2.0
github.com/gorilla/handlers v1.4.0 // indirect github.com/gorilla/handlers v1.4.0 // indirect
github.com/hashicorp/go-version v1.2.1 github.com/hashicorp/go-version v1.2.1
github.com/mattes/migrate v0.0.0-20180508041624-4768a648fbd9 github.com/mattes/migrate v0.0.0-20180508041624-4768a648fbd9
......
...@@ -50,21 +50,30 @@ type Command interface { ...@@ -50,21 +50,30 @@ type Command interface {
// A Commander represents a set of commands. // A Commander represents a set of commands.
type Commander struct { type Commander struct {
commands []*commandGroup commands []*CommandGroup
topFlags *flag.FlagSet // top-level flags topFlags *flag.FlagSet // top-level flags
important []string // important top-level flags important []string // important top-level flags
name string // normally path.Base(os.Args[0]) 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). 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). 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. // A CommandGroup represents a set of commands about a common topic.
type commandGroup struct { type CommandGroup struct {
name string name string
commands []Command 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 // An ExitStatus represents a Posix exit status that a subcommand
// expects to be returned to the shell. // expects to be returned to the shell.
type ExitStatus int type ExitStatus int
...@@ -85,10 +94,19 @@ func NewCommander(topLevelFlags *flag.FlagSet, name string) *Commander { ...@@ -85,10 +94,19 @@ func NewCommander(topLevelFlags *flag.FlagSet, name string) *Commander {
Output: os.Stdout, Output: os.Stdout,
Error: os.Stderr, 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 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 // Register adds a subcommand to the supported subcommands in the
// specified group. (Help output is sorted and arranged by group name.) // specified group. (Help output is sorted and arranged by group name.)
// The empty string is an acceptable group name; such subcommands are // The empty string is an acceptable group name; such subcommands are
...@@ -100,7 +118,7 @@ func (cdr *Commander) Register(cmd Command, group string) { ...@@ -100,7 +118,7 @@ func (cdr *Commander) Register(cmd Command, group string) {
return return
} }
} }
cdr.commands = append(cdr.commands, &commandGroup{ cdr.commands = append(cdr.commands, &CommandGroup{
name: group, name: group,
commands: []Command{cmd}, commands: []Command{cmd},
}) })
...@@ -114,6 +132,55 @@ func (cdr *Commander) ImportantFlag(name string) { ...@@ -114,6 +132,55 @@ func (cdr *Commander) ImportantFlag(name string) {
cdr.important = append(cdr.important, name) 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 // Execute should be called once the top-level-flags on a Commander
// have been initialized. It finds the correct subcommand and executes // have been initialized. It finds the correct subcommand and executes
// it, and returns an ExitStatus with the result. On a usage error, an // 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 ...@@ -134,7 +201,7 @@ func (cdr *Commander) Execute(ctx context.Context, args ...interface{}) ExitStat
continue continue
} }
f := flag.NewFlagSet(name, flag.ContinueOnError) f := flag.NewFlagSet(name, flag.ContinueOnError)
f.Usage = func() { explain(cdr.Error, cmd) } f.Usage = func() { cdr.ExplainCommand(cdr.Error, cmd) }
cmd.SetFlags(f) cmd.SetFlags(f)
if f.Parse(cdr.topFlags.Args()[1:]) != nil { if f.Parse(cdr.topFlags.Args()[1:]) != nil {
return ExitUsageError return ExitUsageError
...@@ -149,8 +216,9 @@ func (cdr *Commander) Execute(ctx context.Context, args ...interface{}) ExitStat ...@@ -149,8 +216,9 @@ func (cdr *Commander) Execute(ctx context.Context, args ...interface{}) ExitStat
} }
// Sorting of a slice of command groups. // 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) Len() int { return len(p) }
func (p byGroupName) Less(i, j int) bool { return p[i].name < p[j].name } 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] } 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) { ...@@ -161,14 +229,18 @@ func (cdr *Commander) explain(w io.Writer) {
fmt.Fprintf(w, "Usage: %s <flags> <subcommand> <subcommand args>\n\n", cdr.name) fmt.Fprintf(w, "Usage: %s <flags> <subcommand> <subcommand args>\n\n", cdr.name)
sort.Sort(byGroupName(cdr.commands)) sort.Sort(byGroupName(cdr.commands))
for _, group := range cdr.commands { for _, group := range cdr.commands {
explainGroup(w, group) cdr.ExplainGroup(w, group)
} }
if cdr.topFlags == nil { if cdr.topFlags == nil {
fmt.Fprintln(w, "\nNo top level flags.") fmt.Fprintln(w, "\nNo top level flags.")
return return
} }
sort.Strings(cdr.important)
if len(cdr.important) == 0 { 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 return
} }
...@@ -183,12 +255,12 @@ func (cdr *Commander) explain(w io.Writer) { ...@@ -183,12 +255,12 @@ func (cdr *Commander) explain(w io.Writer) {
} }
// Sorting of the commands within a group. // Sorting of the commands within a group.
func (g commandGroup) Len() int { return len(g.commands) } 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) 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) 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. // 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 { if len(group.commands) == 0 {
return return
} }
...@@ -254,7 +326,7 @@ func (h *helper) Usage() string { ...@@ -254,7 +326,7 @@ func (h *helper) Usage() string {
func (h *helper) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) ExitStatus { func (h *helper) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) ExitStatus {
switch f.NArg() { switch f.NArg() {
case 0: case 0:
(*Commander)(h).explain(h.Output) (*Commander)(h).Explain(h.Output)
return ExitSuccess return ExitSuccess
case 1: case 1:
...@@ -263,7 +335,7 @@ func (h *helper) Execute(_ context.Context, f *flag.FlagSet, args ...interface{} ...@@ -263,7 +335,7 @@ func (h *helper) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}
if f.Arg(0) != cmd.Name() { if f.Arg(0) != cmd.Name() {
continue continue
} }
explain(h.Output, cmd) (*Commander)(h).ExplainCommand(h.Output, cmd)
return ExitSuccess return ExitSuccess
} }
} }
......
...@@ -17,7 +17,7 @@ github.com/coreos/go-systemd/daemon ...@@ -17,7 +17,7 @@ github.com/coreos/go-systemd/daemon
github.com/dustin/go-humanize github.com/dustin/go-humanize
# github.com/golang/protobuf v1.2.0 # github.com/golang/protobuf v1.2.0
github.com/golang/protobuf/proto github.com/golang/protobuf/proto
# github.com/google/subcommands v1.0.1 # github.com/google/subcommands v1.2.0
## explicit ## explicit
github.com/google/subcommands github.com/google/subcommands
# github.com/gorilla/handlers v1.4.0 # github.com/gorilla/handlers v1.4.0
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment