Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions defaultActions.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/rsteube/carapace/internal/common"
"github.com/rsteube/carapace/internal/config"
"github.com/rsteube/carapace/internal/env"
"github.com/rsteube/carapace/internal/export"
"github.com/rsteube/carapace/internal/man"
"github.com/rsteube/carapace/pkg/match"
Expand Down Expand Up @@ -480,3 +481,36 @@ func ActionPositional(cmd *cobra.Command) Action {
return a.Invoke(c).ToA()
})
}

// ActionCommands completes (sub)commands of given command.
// `Context.Args` is used to traverse the command tree further down. Use `Action.Shift` to avoid this.
//
// carapace.Gen(helpCmd).PositionalAnyCompletion(
// carapace.ActionCommands(rootCmd),
// )
func ActionCommands(cmd *cobra.Command) Action {
return ActionCallback(func(c Context) Action {
if len(c.Args) > 0 {
for _, subCommand := range cmd.Commands() {
for _, name := range append(subCommand.Aliases, subCommand.Name()) {
if name == c.Args[0] { // cmd.Find is too lenient
return ActionCommands(subCommand).Shift(1)
}
}
}
return ActionMessage("unknown subcommand %#v for %#v", c.Args[0], cmd.Name())
}

batch := Batch()
for _, subcommand := range cmd.Commands() {
if (!subcommand.Hidden || env.Hidden()) && subcommand.Deprecated == "" {
group := common.Group{Cmd: subcommand}
batch = append(batch, ActionStyledValuesDescribed(subcommand.Name(), subcommand.Short, group.Style()).Tag(group.Tag()))
for _, alias := range subcommand.Aliases {
batch = append(batch, ActionStyledValuesDescribed(alias, subcommand.Short, group.Style()).Tag(group.Tag()))
}
}
}
return batch.ToA()
})
}
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
- [ToMultiPartsA](./carapace/invokedAction/toMultiPartsA.md)
- [DefaultActions](./carapace/defaultActions.md)
- [ActionCallback](./carapace/defaultActions/actionCallback.md)
- [ActionCommands](./carapace/defaultActions/actionCommands.md)
- [ActionDirectories](./carapace/defaultActions/actionDirectories.md)
- [ActionExecCommand](./carapace/defaultActions/actionExecCommand.md)
- [ActionExecCommandE](./carapace/defaultActions/actionExecCommandE.md)
Expand Down
92 changes: 92 additions & 0 deletions docs/src/carapace/defaultActions/actionCommands.cast

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions docs/src/carapace/defaultActions/actionCommands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# ActionCommands

[`ActionCommands`] completes (sub)commands of given command.

> `Context.Args` is used to traverse the command tree further down.
> Use [Shift](../action/shift.md) to avoid this.


```go
carapace.Gen(helpCmd).PositionalAnyCompletion(
carapace.ActionCommands(cmd),
)
```

![](./actionCommands.cast)

[`ActionCommands`]:https://pkg.go.dev/github.com/rsteube/carapace#ActionCommands
2 changes: 2 additions & 0 deletions example/cmd/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func init() {
rootCmd.AddCommand(actionCmd)

actionCmd.Flags().String("callback", "", "ActionCallback()")
actionCmd.Flags().String("commands", "", "ActionCommands()")
actionCmd.Flags().String("directories", "", "ActionDirectories()")
actionCmd.Flags().String("execcommand", "", "ActionExecCommand()")
actionCmd.Flags().String("execcommandE", "", "ActionExecCommand()")
Expand Down Expand Up @@ -48,6 +49,7 @@ func init() {
}
return carapace.ActionMessage("values flag is not set")
}),
"commands": carapace.ActionCommands(rootCmd).Split(),
"directories": carapace.ActionDirectories(),
"execcommand": carapace.ActionExecCommand("git", "remote")(func(output []byte) carapace.Action {
lines := strings.Split(string(output), "\n")
Expand Down
38 changes: 38 additions & 0 deletions example/cmd/action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,44 @@ func TestAction(t *testing.T) {
Expect(carapace.ActionMessage("values flag is not set").
Usage("ActionCallback()"))

s.Run("action", "--commands", "s").
Expect(carapace.ActionValuesDescribed(
"special", "",
"subcommand", "subcommand example",
).Suffix(" ").
NoSpace().
Tag("other commands").
Usage("ActionCommands()"))

s.Run("action", "--commands", "subcommand ").
Expect(carapace.Batch(
carapace.ActionValuesDescribed(
"a1", "subcommand with alias",
"a2", "subcommand with alias",
"alias", "subcommand with alias",
).Tag("other commands"),
carapace.ActionValuesDescribed(
"group", "subcommand with group",
).Style(style.Blue).Tag("group commands"),
).ToA().
Prefix("subcommand ").
Suffix(" ").
NoSpace().
Usage("ActionCommands()"))

s.Run("action", "--commands", "subcommand unknown ").
Expect(carapace.ActionMessage(`unknown subcommand "unknown" for "subcommand"`).NoSpace().
Usage("ActionCommands()"))

s.Run("action", "--commands", "subcommand hidden ").
Expect(carapace.ActionValuesDescribed(
"visible", "visible subcommand of a hidden command",
).Prefix("subcommand hidden ").
Suffix(" ").
NoSpace().
Tag("commands").
Usage("ActionCommands()"))

s.Run("action", "--values", "first", "--callback", "").
Expect(carapace.ActionMessage("values flag is set to: 'first'").
Usage("ActionCallback()"))
Expand Down
1 change: 1 addition & 0 deletions example/cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func TestRoot(t *testing.T) {
"interspersed", "interspersed example",
"multiparts", "multiparts example",
"special", "",
"subcommand", "subcommand example",
).Tag("other commands"),
).ToA())

Expand Down
22 changes: 22 additions & 0 deletions example/cmd/subcommand.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cmd

import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)

var subcommandCmd = &cobra.Command{
Use: "subcommand",
Short: "subcommand example",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(subcommandCmd).Standalone()

subcommandCmd.AddGroup(
&cobra.Group{ID: "group", Title: ""},
)

rootCmd.AddCommand(subcommandCmd)
}
19 changes: 19 additions & 0 deletions example/cmd/subcommand_alias.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package cmd

import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)

var subcommand_aliasCmd = &cobra.Command{
Use: "alias",
Short: "subcommand with alias",
Aliases: []string{"a1", "a2"},
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(subcommand_aliasCmd).Standalone()

subcommandCmd.AddCommand(subcommand_aliasCmd)
}
19 changes: 19 additions & 0 deletions example/cmd/subcommand_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package cmd

import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)

var subcommand_groupCmd = &cobra.Command{
Use: "group",
Short: "subcommand with group",
GroupID: "group",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(subcommand_groupCmd).Standalone()

subcommandCmd.AddCommand(subcommand_groupCmd)
}
19 changes: 19 additions & 0 deletions example/cmd/subcommand_hidden.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package cmd

import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)

var subcommand_hiddenCmd = &cobra.Command{
Use: "hidden",
Short: "hidden subcommand",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(subcommand_hiddenCmd).Standalone()

subcommandCmd.AddCommand(subcommand_hiddenCmd)
}
18 changes: 18 additions & 0 deletions example/cmd/subcommand_hidden_visible.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package cmd

import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)

var subcommand_hidden_visibleCmd = &cobra.Command{
Use: "visible",
Short: "visible subcommand of a hidden command",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(subcommand_hidden_visibleCmd).Standalone()

subcommand_hiddenCmd.AddCommand(subcommand_hidden_visibleCmd)
}
25 changes: 1 addition & 24 deletions internalActions.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"path/filepath"
"strings"

"github.com/rsteube/carapace/internal/common"
"github.com/rsteube/carapace/internal/env"
"github.com/rsteube/carapace/internal/pflagfork"
"github.com/rsteube/carapace/pkg/style"
Expand Down Expand Up @@ -133,22 +132,6 @@ func actionFlags(cmd *cobra.Command) Action {
}).Tag("flags")
}

func actionSubcommands(cmd *cobra.Command) Action {
return ActionCallback(func(c Context) Action {
batch := Batch()
for _, subcommand := range cmd.Commands() {
if (!subcommand.Hidden || env.Hidden()) && subcommand.Deprecated == "" {
group := common.Group{Cmd: subcommand}
batch = append(batch, ActionStyledValuesDescribed(subcommand.Name(), subcommand.Short, group.Style()).Tag(group.Tag()))
for _, alias := range subcommand.Aliases {
batch = append(batch, ActionStyledValuesDescribed(alias, subcommand.Short, group.Style()).Tag(group.Tag()))
}
}
}
return batch.ToA()
})
}

func initHelpCompletion(cmd *cobra.Command) {
helpCmd, _, err := cmd.Find([]string{"help"})
if err != nil {
Expand All @@ -162,12 +145,6 @@ func initHelpCompletion(cmd *cobra.Command) {
}

Gen(helpCmd).PositionalAnyCompletion(
ActionCallback(func(c Context) Action {
lastCmd, _, err := cmd.Find(c.Args)
if err != nil {
return ActionMessage(err.Error())
}
return actionSubcommands(lastCmd)
}),
ActionCommands(cmd),
)
}
2 changes: 1 addition & 1 deletion traverse.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ loop:
LOG.Printf("completing positionals and subcommands for arg %#v\n", context.Value)
batch := Batch(storage.getPositional(cmd, len(context.Args)))
if cmd.HasAvailableSubCommands() && len(context.Args) == 0 {
batch = append(batch, actionSubcommands(cmd))
batch = append(batch, ActionCommands(cmd))
}
return batch.ToA(), context
}
Expand Down