mirror of
https://github.com/spf13/cobra
synced 2024-11-24 14:47:12 +00:00
Add completion for help command (#1136)
* Don't exclude 'help' from bash completions Fixes #1000. * Provide completion for the help command 1- Show 'help' as a possible completion 2- Provide completions for the help command itself Signed-off-by: Marc Khouzam <marc.khouzam@montreal.ca> Co-authored-by: Zaven Muradyan <voithos@google.com>
This commit is contained in:
parent
ed7b60e298
commit
04318720db
4 changed files with 94 additions and 6 deletions
|
@ -389,7 +389,7 @@ fi
|
|||
func writeCommands(buf *bytes.Buffer, cmd *Command) {
|
||||
buf.WriteString(" commands=()\n")
|
||||
for _, c := range cmd.Commands() {
|
||||
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
||||
if !c.IsAvailableCommand() && c != cmd.helpCommand {
|
||||
continue
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf(" commands+=(%q)\n", c.Name()))
|
||||
|
@ -582,7 +582,7 @@ func writeArgAliases(buf *bytes.Buffer, cmd *Command) {
|
|||
|
||||
func gen(buf *bytes.Buffer, cmd *Command) {
|
||||
for _, c := range cmd.Commands() {
|
||||
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
||||
if !c.IsAvailableCommand() && c != cmd.helpCommand {
|
||||
continue
|
||||
}
|
||||
gen(buf, c)
|
||||
|
|
20
command.go
20
command.go
|
@ -1056,7 +1056,25 @@ func (c *Command) InitDefaultHelpCmd() {
|
|||
Short: "Help about any command",
|
||||
Long: `Help provides help for any command in the application.
|
||||
Simply type ` + c.Name() + ` help [path to command] for full details.`,
|
||||
|
||||
ValidArgsFunction: func(c *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||||
var completions []string
|
||||
cmd, _, e := c.Root().Find(args)
|
||||
if e != nil {
|
||||
return nil, ShellCompDirectiveNoFileComp
|
||||
}
|
||||
if cmd == nil {
|
||||
// Root help command.
|
||||
cmd = c.Root()
|
||||
}
|
||||
for _, subCmd := range cmd.Commands() {
|
||||
if subCmd.IsAvailableCommand() || subCmd == cmd.helpCommand {
|
||||
if strings.HasPrefix(subCmd.Name(), toComplete) {
|
||||
completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short))
|
||||
}
|
||||
}
|
||||
}
|
||||
return completions, ShellCompDirectiveNoFileComp
|
||||
},
|
||||
Run: func(c *Command, args []string) {
|
||||
cmd, _, e := c.Root().Find(args)
|
||||
if cmd == nil || e != nil {
|
||||
|
|
|
@ -183,10 +183,12 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
|
|||
}
|
||||
|
||||
if flag == nil {
|
||||
// Complete subcommand names
|
||||
// Complete subcommand names, including the help command
|
||||
for _, subCmd := range finalCmd.Commands() {
|
||||
if subCmd.IsAvailableCommand() && strings.HasPrefix(subCmd.Name(), toComplete) {
|
||||
completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short))
|
||||
if subCmd.IsAvailableCommand() || subCmd == finalCmd.helpCommand {
|
||||
if strings.HasPrefix(subCmd.Name(), toComplete) {
|
||||
completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -629,3 +629,71 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) {
|
|||
t.Errorf("expected: %q, got: %q", expected, output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompleteHelp(t *testing.T) {
|
||||
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
|
||||
child1Cmd := &Command{
|
||||
Use: "child1",
|
||||
Run: emptyRun,
|
||||
}
|
||||
child2Cmd := &Command{
|
||||
Use: "child2",
|
||||
Run: emptyRun,
|
||||
}
|
||||
rootCmd.AddCommand(child1Cmd, child2Cmd)
|
||||
|
||||
child3Cmd := &Command{
|
||||
Use: "child3",
|
||||
Run: emptyRun,
|
||||
}
|
||||
child1Cmd.AddCommand(child3Cmd)
|
||||
|
||||
// Test that completion includes the help command
|
||||
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "")
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
expected := strings.Join([]string{
|
||||
"child1",
|
||||
"child2",
|
||||
"help",
|
||||
":0",
|
||||
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
|
||||
|
||||
if output != expected {
|
||||
t.Errorf("expected: %q, got: %q", expected, output)
|
||||
}
|
||||
|
||||
// Test sub-commands are completed on first level of help command
|
||||
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "help", "")
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
expected = strings.Join([]string{
|
||||
"child1",
|
||||
"child2",
|
||||
"help", // "<program> help help" is a valid command, so should be completed
|
||||
":4",
|
||||
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
|
||||
|
||||
if output != expected {
|
||||
t.Errorf("expected: %q, got: %q", expected, output)
|
||||
}
|
||||
|
||||
// Test sub-commands are completed on first level of help command
|
||||
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "help", "child1", "")
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
expected = strings.Join([]string{
|
||||
"child3",
|
||||
":4",
|
||||
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
|
||||
|
||||
if output != expected {
|
||||
t.Errorf("expected: %q, got: %q", expected, output)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue