mirror of
https://github.com/spf13/cobra
synced 2025-05-05 21:07:24 +00:00
Add a hook function called when searching a command to be executed
This hook function is useful when we want to dynamically add commands. Signed-off-by: Wataru Ishida <ishida.wataru@lab.ntt.co.jp>
This commit is contained in:
parent
be77323fc0
commit
741bcadda3
1 changed files with 33 additions and 12 deletions
45
command.go
45
command.go
|
@ -54,6 +54,9 @@ type Command struct {
|
||||||
// ValidArgs is list of all valid non-flag arguments that are accepted in bash completions
|
// ValidArgs is list of all valid non-flag arguments that are accepted in bash completions
|
||||||
ValidArgs []string
|
ValidArgs []string
|
||||||
|
|
||||||
|
// Dynamic
|
||||||
|
Dynamic func(name string) (bool, error)
|
||||||
|
|
||||||
// Expected arguments
|
// Expected arguments
|
||||||
Args PositionalArgs
|
Args PositionalArgs
|
||||||
|
|
||||||
|
@ -191,7 +194,6 @@ type Command struct {
|
||||||
versionTemplate string
|
versionTemplate string
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
|
|
||||||
// particularly useful when testing.
|
// particularly useful when testing.
|
||||||
func (c *Command) SetArgs(a []string) {
|
func (c *Command) SetArgs(a []string) {
|
||||||
c.args = a
|
c.args = a
|
||||||
|
@ -518,23 +520,29 @@ func isFlagArg(arg string) bool {
|
||||||
// Find the target command given the args and command tree
|
// Find the target command given the args and command tree
|
||||||
// Meant to be run on the highest node. Only searches down.
|
// Meant to be run on the highest node. Only searches down.
|
||||||
func (c *Command) Find(args []string) (*Command, []string, error) {
|
func (c *Command) Find(args []string) (*Command, []string, error) {
|
||||||
var innerfind func(*Command, []string) (*Command, []string)
|
var innerfind func(*Command, []string) (*Command, []string, error)
|
||||||
|
|
||||||
innerfind = func(c *Command, innerArgs []string) (*Command, []string) {
|
innerfind = func(c *Command, innerArgs []string) (*Command, []string, error) {
|
||||||
argsWOflags := stripFlags(innerArgs, c)
|
argsWOflags := stripFlags(innerArgs, c)
|
||||||
if len(argsWOflags) == 0 {
|
if len(argsWOflags) == 0 {
|
||||||
return c, innerArgs
|
return c, innerArgs, nil
|
||||||
}
|
}
|
||||||
nextSubCmd := argsWOflags[0]
|
nextSubCmd := argsWOflags[0]
|
||||||
|
|
||||||
cmd := c.findNext(nextSubCmd)
|
cmd, err := c.findNext(nextSubCmd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
if cmd != nil {
|
if cmd != nil {
|
||||||
return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd))
|
return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd))
|
||||||
}
|
}
|
||||||
return c, innerArgs
|
return c, innerArgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
commandFound, a := innerfind(c, args)
|
commandFound, a, err := innerfind(c, args)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
if commandFound.Args == nil {
|
if commandFound.Args == nil {
|
||||||
return commandFound, a, legacyArgs(commandFound, stripFlags(a, commandFound))
|
return commandFound, a, legacyArgs(commandFound, stripFlags(a, commandFound))
|
||||||
}
|
}
|
||||||
|
@ -558,23 +566,33 @@ func (c *Command) findSuggestions(arg string) string {
|
||||||
return suggestionsString
|
return suggestionsString
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Command) findNext(next string) *Command {
|
func (c *Command) findNext(next string) (*Command, error) {
|
||||||
matches := make([]*Command, 0)
|
matches := make([]*Command, 0)
|
||||||
for _, cmd := range c.commands {
|
for _, cmd := range c.commands {
|
||||||
if cmd.Name() == next || cmd.HasAlias(next) {
|
if cmd.Name() == next || cmd.HasAlias(next) {
|
||||||
cmd.commandCalledAs.name = next
|
cmd.commandCalledAs.name = next
|
||||||
return cmd
|
return cmd, nil
|
||||||
}
|
}
|
||||||
if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) {
|
if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) {
|
||||||
matches = append(matches, cmd)
|
matches = append(matches, cmd)
|
||||||
}
|
}
|
||||||
|
if cmd.Dynamic != nil {
|
||||||
|
valid, err := cmd.Dynamic(next)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if valid {
|
||||||
|
matches = append(matches, cmd)
|
||||||
|
cmd.Use = next
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(matches) == 1 {
|
if len(matches) == 1 {
|
||||||
return matches[0]
|
return matches[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Traverse the command tree to find the command, and parse args for
|
// Traverse the command tree to find the command, and parse args for
|
||||||
|
@ -607,7 +625,10 @@ func (c *Command) Traverse(args []string) (*Command, []string, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := c.findNext(arg)
|
cmd, err := c.findNext(arg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
if cmd == nil {
|
if cmd == nil {
|
||||||
return c, args, nil
|
return c, args, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue