allow setting group-scoped flags
This commit is contained in:
parent
fef0a55288
commit
7b17646738
|
@ -54,7 +54,7 @@ func newCobraRoot(root *command.Command) *cobra.Command {
|
|||
}
|
||||
}
|
||||
|
||||
func ToCobra(cmd *command.Command, globalOptions command.Options) *cobra.Command {
|
||||
func ToCobra(cmd *command.Command, globalOptions command.Options, parent *cobra.Command) *cobra.Command {
|
||||
localName := cmd.Name()
|
||||
useSpec := []string{localName, "[options]"}
|
||||
for _, arg := range cmd.Arguments {
|
||||
|
@ -97,8 +97,20 @@ func ToCobra(cmd *command.Command, globalOptions command.Options) *cobra.Command
|
|||
log.Errorf("Failed setting up autocompletion for option <%s> of command <%s>", name, cmd.FullName())
|
||||
}
|
||||
}
|
||||
parent.AddCommand(cc)
|
||||
|
||||
cc.SetHelpFunc(cmd.HelpRenderer(globalOptions))
|
||||
cmdGlobalOptions := globalOptions
|
||||
if parent != cc.Root() {
|
||||
cmdGlobalOptions = subOptions(globalOptions)
|
||||
log.Tracef("Adding subflags from %s to child %s", parent.Name(), cmd.FullName())
|
||||
if p := FromCobra(parent); p != nil {
|
||||
for key, opt := range p.Options {
|
||||
cmdGlobalOptions[key] = opt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cc.SetHelpFunc(cmd.HelpRenderer(cmdGlobalOptions))
|
||||
cmd.SetCobra(cc)
|
||||
return cc
|
||||
}
|
||||
|
|
|
@ -62,6 +62,14 @@ func CommandList() []*command.Command {
|
|||
return registry.byPath
|
||||
}
|
||||
|
||||
func subOptions(m command.Options) command.Options {
|
||||
m2 := make(map[string]*command.Option, len(m))
|
||||
for id, opt := range m {
|
||||
m2[id] = opt
|
||||
}
|
||||
return m2
|
||||
}
|
||||
|
||||
func Execute(version string) error {
|
||||
log.Debug("starting execution")
|
||||
cmdRoot := command.Root
|
||||
|
@ -97,10 +105,15 @@ func Execute(version string) error {
|
|||
container := ccRoot
|
||||
for idx, cp := range cmd.Path {
|
||||
if idx == len(cmd.Path)-1 {
|
||||
leaf := ToCobra(cmd, globalOptions)
|
||||
container.AddCommand(leaf)
|
||||
log.Tracef("cobra: %s => %s", leaf.Name(), container.CommandPath())
|
||||
break
|
||||
if cmd.Action != nil {
|
||||
// nil actions come when the current command consists only
|
||||
// of metadata for a "group parent" command
|
||||
// and we don't wanna cobraize it like a regular, actionable one
|
||||
leaf := ToCobra(cmd, globalOptions, container)
|
||||
log.Tracef("cobra: %s => %s", leaf.Name(), container.CommandPath())
|
||||
break
|
||||
}
|
||||
log.Tracef("Found command with no action: %s, assuming group parent action", cmd.Path)
|
||||
}
|
||||
|
||||
query := []string{cp}
|
||||
|
@ -112,6 +125,11 @@ func Execute(version string) error {
|
|||
|
||||
for _, sub := range container.Commands() {
|
||||
if sub.Name() == cp {
|
||||
if parent := FromCobra(container); parent != nil {
|
||||
log.Tracef("pflags to %s from %s", sub.Name(), parent.FullName())
|
||||
fs := parent.FlagSet()
|
||||
sub.PersistentFlags().AddFlagSet(fs)
|
||||
}
|
||||
container = sub
|
||||
found = true
|
||||
}
|
||||
|
@ -119,16 +137,35 @@ func Execute(version string) error {
|
|||
|
||||
if !found {
|
||||
groupName := strings.Join(query, " ")
|
||||
groupPath := append(cmdRoot.Path, append(cmd.Path[0:idx], query...)...) // nolint:gocritic
|
||||
cleanPath := append(cmd.Path[0:idx], query...)
|
||||
groupPath := append(cmdRoot.Path, cleanPath...) // nolint:gocritic
|
||||
|
||||
cmdGlobalOptions := globalOptions
|
||||
|
||||
groupParent := Get(groupName)
|
||||
if groupParent == nil {
|
||||
log.Tracef("creating group parent for %s", groupPath)
|
||||
groupParent = &command.Command{
|
||||
Path: cleanPath,
|
||||
Summary: fmt.Sprintf("%s subcommands", groupName),
|
||||
Description: fmt.Sprintf("Runs subcommands within %s", groupName),
|
||||
Arguments: command.Arguments{},
|
||||
Options: command.Options{},
|
||||
}
|
||||
Register(groupParent)
|
||||
} else {
|
||||
log.Tracef("using pre-existing group parent for %s (%s)", groupPath, groupParent.Path)
|
||||
}
|
||||
|
||||
cc := &cobra.Command{
|
||||
Use: cp,
|
||||
Short: fmt.Sprintf("%s subcommands", groupName),
|
||||
Short: groupParent.Summary,
|
||||
DisableAutoGenTag: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
SilenceUsage: true,
|
||||
SilenceErrors: true,
|
||||
Annotations: map[string]string{
|
||||
ContextKeyRuntimeIndex: strings.Join(groupPath, " "),
|
||||
ContextKeyRuntimeIndex: strings.Join(cleanPath, " "),
|
||||
},
|
||||
ValidArgs: []string{},
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
|
@ -161,15 +198,23 @@ func Execute(version string) error {
|
|||
},
|
||||
}
|
||||
|
||||
groupParent := &command.Command{
|
||||
Path: groupPath,
|
||||
Summary: fmt.Sprintf("%s subcommands", groupName),
|
||||
Description: fmt.Sprintf("Runs subcommands within %s", groupName),
|
||||
Arguments: command.Arguments{},
|
||||
Options: command.Options{},
|
||||
if len(groupParent.Options) > 0 {
|
||||
fs := cmd.FlagSet()
|
||||
cc.PersistentFlags().AddFlagSet(fs)
|
||||
log.Debugf("adding sub-global option set to %s", groupName)
|
||||
}
|
||||
Register(groupParent)
|
||||
cc.SetHelpFunc(groupParent.HelpRenderer(globalOptions))
|
||||
|
||||
if container != cc.Root() {
|
||||
cmdGlobalOptions = subOptions(globalOptions)
|
||||
if p := FromCobra(container); p != nil {
|
||||
for key, opt := range p.Options {
|
||||
cmdGlobalOptions[key] = opt
|
||||
}
|
||||
}
|
||||
}
|
||||
cc.PersistentFlags().AddFlagSet(container.PersistentFlags())
|
||||
|
||||
cc.SetHelpFunc(groupParent.HelpRenderer(cmdGlobalOptions))
|
||||
cc.SetHelpCommand(commands.Help)
|
||||
container.AddCommand(cc)
|
||||
container = cc
|
||||
|
|
|
@ -73,7 +73,6 @@ func (cmd *Command) FlagSet() *pflag.FlagSet {
|
|||
fs := pflag.NewFlagSet(strings.Join(cmd.Path, " "), pflag.ContinueOnError)
|
||||
fs.SortFlags = false
|
||||
fs.Usage = func() {}
|
||||
|
||||
for name, opt := range cmd.Options {
|
||||
switch opt.Type {
|
||||
case ValueTypeBoolean:
|
||||
|
@ -81,7 +80,6 @@ func (cmd *Command) FlagSet() *pflag.FlagSet {
|
|||
if opt.Default != nil {
|
||||
def = opt.Default.(bool)
|
||||
}
|
||||
|
||||
fs.BoolP(name, opt.ShortName, def, opt.Description)
|
||||
case ValueTypeInt:
|
||||
def := -1
|
||||
|
@ -97,7 +95,6 @@ func (cmd *Command) FlagSet() *pflag.FlagSet {
|
|||
def = casted
|
||||
}
|
||||
}
|
||||
|
||||
fs.IntP(name, opt.ShortName, def, opt.Description)
|
||||
case ValueTypeDefault, ValueTypeString:
|
||||
opt.Type = ValueTypeString
|
||||
|
@ -112,6 +109,7 @@ func (cmd *Command) FlagSet() *pflag.FlagSet {
|
|||
continue
|
||||
}
|
||||
}
|
||||
|
||||
cmd.runtimeFlags = fs
|
||||
}
|
||||
return cmd.runtimeFlags
|
||||
|
|
Loading…
Reference in New Issue