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()
|
localName := cmd.Name()
|
||||||
useSpec := []string{localName, "[options]"}
|
useSpec := []string{localName, "[options]"}
|
||||||
for _, arg := range cmd.Arguments {
|
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())
|
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)
|
cmd.SetCobra(cc)
|
||||||
return cc
|
return cc
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,14 @@ func CommandList() []*command.Command {
|
|||||||
return registry.byPath
|
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 {
|
func Execute(version string) error {
|
||||||
log.Debug("starting execution")
|
log.Debug("starting execution")
|
||||||
cmdRoot := command.Root
|
cmdRoot := command.Root
|
||||||
@ -97,11 +105,16 @@ func Execute(version string) error {
|
|||||||
container := ccRoot
|
container := ccRoot
|
||||||
for idx, cp := range cmd.Path {
|
for idx, cp := range cmd.Path {
|
||||||
if idx == len(cmd.Path)-1 {
|
if idx == len(cmd.Path)-1 {
|
||||||
leaf := ToCobra(cmd, globalOptions)
|
if cmd.Action != nil {
|
||||||
container.AddCommand(leaf)
|
// 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())
|
log.Tracef("cobra: %s => %s", leaf.Name(), container.CommandPath())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
log.Tracef("Found command with no action: %s, assuming group parent action", cmd.Path)
|
||||||
|
}
|
||||||
|
|
||||||
query := []string{cp}
|
query := []string{cp}
|
||||||
found := false
|
found := false
|
||||||
@ -112,6 +125,11 @@ func Execute(version string) error {
|
|||||||
|
|
||||||
for _, sub := range container.Commands() {
|
for _, sub := range container.Commands() {
|
||||||
if sub.Name() == cp {
|
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
|
container = sub
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
@ -119,16 +137,35 @@ func Execute(version string) error {
|
|||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
groupName := strings.Join(query, " ")
|
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{
|
cc := &cobra.Command{
|
||||||
Use: cp,
|
Use: cp,
|
||||||
Short: fmt.Sprintf("%s subcommands", groupName),
|
Short: groupParent.Summary,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
SuggestionsMinimumDistance: 2,
|
SuggestionsMinimumDistance: 2,
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
SilenceErrors: true,
|
SilenceErrors: true,
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
ContextKeyRuntimeIndex: strings.Join(groupPath, " "),
|
ContextKeyRuntimeIndex: strings.Join(cleanPath, " "),
|
||||||
},
|
},
|
||||||
ValidArgs: []string{},
|
ValidArgs: []string{},
|
||||||
Args: func(cmd *cobra.Command, args []string) error {
|
Args: func(cmd *cobra.Command, args []string) error {
|
||||||
@ -161,15 +198,23 @@ func Execute(version string) error {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
groupParent := &command.Command{
|
if len(groupParent.Options) > 0 {
|
||||||
Path: groupPath,
|
fs := cmd.FlagSet()
|
||||||
Summary: fmt.Sprintf("%s subcommands", groupName),
|
cc.PersistentFlags().AddFlagSet(fs)
|
||||||
Description: fmt.Sprintf("Runs subcommands within %s", groupName),
|
log.Debugf("adding sub-global option set to %s", groupName)
|
||||||
Arguments: command.Arguments{},
|
|
||||||
Options: command.Options{},
|
|
||||||
}
|
}
|
||||||
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)
|
cc.SetHelpCommand(commands.Help)
|
||||||
container.AddCommand(cc)
|
container.AddCommand(cc)
|
||||||
container = cc
|
container = cc
|
||||||
|
@ -73,7 +73,6 @@ func (cmd *Command) FlagSet() *pflag.FlagSet {
|
|||||||
fs := pflag.NewFlagSet(strings.Join(cmd.Path, " "), pflag.ContinueOnError)
|
fs := pflag.NewFlagSet(strings.Join(cmd.Path, " "), pflag.ContinueOnError)
|
||||||
fs.SortFlags = false
|
fs.SortFlags = false
|
||||||
fs.Usage = func() {}
|
fs.Usage = func() {}
|
||||||
|
|
||||||
for name, opt := range cmd.Options {
|
for name, opt := range cmd.Options {
|
||||||
switch opt.Type {
|
switch opt.Type {
|
||||||
case ValueTypeBoolean:
|
case ValueTypeBoolean:
|
||||||
@ -81,7 +80,6 @@ func (cmd *Command) FlagSet() *pflag.FlagSet {
|
|||||||
if opt.Default != nil {
|
if opt.Default != nil {
|
||||||
def = opt.Default.(bool)
|
def = opt.Default.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.BoolP(name, opt.ShortName, def, opt.Description)
|
fs.BoolP(name, opt.ShortName, def, opt.Description)
|
||||||
case ValueTypeInt:
|
case ValueTypeInt:
|
||||||
def := -1
|
def := -1
|
||||||
@ -97,7 +95,6 @@ func (cmd *Command) FlagSet() *pflag.FlagSet {
|
|||||||
def = casted
|
def = casted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.IntP(name, opt.ShortName, def, opt.Description)
|
fs.IntP(name, opt.ShortName, def, opt.Description)
|
||||||
case ValueTypeDefault, ValueTypeString:
|
case ValueTypeDefault, ValueTypeString:
|
||||||
opt.Type = ValueTypeString
|
opt.Type = ValueTypeString
|
||||||
@ -112,6 +109,7 @@ func (cmd *Command) FlagSet() *pflag.FlagSet {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.runtimeFlags = fs
|
cmd.runtimeFlags = fs
|
||||||
}
|
}
|
||||||
return cmd.runtimeFlags
|
return cmd.runtimeFlags
|
||||||
|
Loading…
Reference in New Issue
Block a user