Skip to content

Commit

Permalink
Merge pull request #141 from rsteube/actionmultiparts-support-nesting
Browse files Browse the repository at this point in the history
ActionMultiParts: support nesting
  • Loading branch information
rsteube authored Dec 13, 2020
2 parents 3bab02b + eae9855 commit d78873a
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 5 deletions.
10 changes: 7 additions & 3 deletions action.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/spf13/cobra"
)

// Action indicates how to complete a flag or positional argument
type Action struct {
rawValues []common.Candidate
bash func() string
Expand Down Expand Up @@ -53,6 +54,7 @@ func (a Action) finalize(cmd *cobra.Command, uid string) Action {

type InvokedAction Action

// Invoke executes the callback of an action if it exists (supports nesting)
func (a Action) Invoke(args []string) InvokedAction {
return InvokedAction(a.nestedAction(args, 5))
}
Expand Down Expand Up @@ -173,6 +175,7 @@ func ActionBool() Action {
return ActionValues("true", "false")
}

// ActionDirectories completes directories
func ActionDirectories() Action {
return Action{
bash: func() string { return bash.ActionDirectories() },
Expand All @@ -185,6 +188,7 @@ func ActionDirectories() Action {
}
}

// ActionFiles completes files with optional suffix filtering
func ActionFiles(suffix string) Action {
return Action{
bash: func() string { return bash.ActionFiles(suffix) },
Expand Down Expand Up @@ -235,19 +239,19 @@ func ActionMessage(msg string) Action {
return ActionValuesDescribed("_", "", "ERR", msg)
}

// CCallbackValue is set to the currently completed flag/positional value during callback
// CallbackValue is set to the currently completed flag/positional value during callback (note that this is updated during ActionMultiParts)
var CallbackValue string

// ActionMultiParts completes multiple parts of words separately where each part is separated by some char
// ActionMultiParts completes multiple parts of words separately where each part is separated by some char (CallbackValue is set to the currently completed part during invocation)
func ActionMultiParts(divider string, callback func(args []string, parts []string) Action) Action {
return ActionCallback(func(args []string) Action {
// TODO multiple dividers by splitting on each char
index := strings.LastIndex(CallbackValue, string(divider))
prefix := ""
if len(divider) == 0 {
prefix = CallbackValue
} else if index != -1 {
prefix = CallbackValue[0 : index+len(divider)]
CallbackValue = CallbackValue[index+len(divider):] // update CallbackValue to only contain the currently completed part
}
parts := strings.Split(prefix, string(divider))
if len(parts) > 0 {
Expand Down
6 changes: 6 additions & 0 deletions docs/src/carapace/action/actionCallback.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ carapace.ActionCallback(func(args []string) carapace.Action {
})
```

- [`carapace.CallbackValue`](https://pkg.go.dev/github.com/rsteube/carapace#pkg-variables) provides access to the current (partial) value of the flag or positional argument being completed
- return [ActionValues](./actionValues.md) without arguments to silently skip completion
- return [ActionMessage](./actionMessage.md) to provide an error message (e.g. failure during invocation of an external command)
- the `args` parameter provides access to the positional arguments of the current subcommand (excluding the one currently being completed)
- [`IsCallback()`](https://pkg.go.dev/github.com/rsteube/carapace#IsCallback) indicates if the current invocation of the program is a callback (useful to skip any lengthy init steps)

## Testing

Since callbacks are simply invocations of the program they can be tested directly.
Expand Down
2 changes: 1 addition & 1 deletion docs/src/carapace/action/actionMessage.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
carapace.ActionMessage("message example")
```

> Although zsh has an actual message function for consistency [ActionValuesDescribed](./actionValuesDescribed.md) is used with values `_`, `ERR` and the message as description.
> To display the message [ActionValuesDescribed](./actionValuesDescribed.md) is used with values `_`, `ERR` and the message as description.
15 changes: 14 additions & 1 deletion example/cmd/multiparts.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,20 @@ func init() {

carapace.Gen(multipartsCmd).PositionalCompletion(ActionMultipartsTest(","))

carapace.Gen(multipartsCmd).PositionalAnyCompletion(ActionMultipartsTest("/"))
carapace.Gen(multipartsCmd).PositionalAnyCompletion(
carapace.ActionMultiParts(",", func(args, parts []string) carapace.Action {
return carapace.ActionMultiParts("=", func(args, parts []string) carapace.Action {
switch len(parts) {
case 0:
return carapace.ActionValues("a", "b", "c")
case 1:
return carapace.ActionValues("one", "two", "three")
default:
return carapace.ActionValues()
}
})
}),
)
}

func ActionMultipartsTest(divider string) carapace.Action {
Expand Down

0 comments on commit d78873a

Please sign in to comment.