Description
When using dynamic shell completion via ValidArgsFunction, splitting on colons : causes the input string toComplete to be truncated. Instead of receiving the full logical argument, the function receives only the segment after the last colon, while the prefix is moved into the args slice.
This makes implementing context-aware completions for URI-like schemes (e.g., local:/path, s3://bucket) or filesystem providers extremely brittle and non-portable across shells.
Minimum Viable Example (MVE)
package main
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
func main() {
rootCmd := &cobra.Command{
Use: "repro",
}
lsCmd := &cobra.Command{
Use: "ls <path>",
Short: "Reproduction for colon split issue",
Args: cobra.MaximumNArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
// Log inputs to a file to inspect what the shell is sending
f, _ := os.OpenFile("repro.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if f != nil {
defer f.Close()
_, _ = f.WriteString(fmt.Sprintf("args: %v, toComplete: %q\n", args, toComplete))
}
// We expect to see the full "local:/path" here to provide suggestions.
// However, in Bash, "local:" ends up in 'args' and toComplete is just the path.
return []string{"local:/tmp/file1", "local:/tmp/file2"}, cobra.ShellCompDirectiveNoFileComp
},
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("args: %v\n", args)
},
}
rootCmd.AddCommand(lsCmd)
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}
Steps to Reproduce
- Build the reproduction:
go build -o repro main.go
- Enable Bash completion:
source <(./repro completion bash)
- Type the following and press TAB:
./repro ls local:/
- Inspect the generated
repro.log.
Actual Behavior
The log shows:
args: [local :], toComplete: "/"
Bash has split the word at the colon. Cobra's completion logic follows this split, forcing the developer to manually reconstruct the original word from args and toComplete to understand the context (in this case, that the user is asking for completion from the local provider). which differs from usage with PreRunE and RunE which accept them as one argument
Expected Behavior
toComplete should ideally represent the full word as it does in PreRunE and RunE.
For example:
args: [], toComplete: "local:/"
Environment
- Cobra Version: v1.10.2
- OS: Linux
- Shell: Bash 5.2+ (with
bash-completion enabled)
Description
When using dynamic shell completion via
ValidArgsFunction, splitting on colons:causes the input stringtoCompleteto be truncated. Instead of receiving the full logical argument, the function receives only the segment after the last colon, while the prefix is moved into theargsslice.This makes implementing context-aware completions for URI-like schemes (e.g.,
local:/path,s3://bucket) or filesystem providers extremely brittle and non-portable across shells.Minimum Viable Example (MVE)
Steps to Reproduce
go build -o repro main.gosource <(./repro completion bash)./repro ls local:/repro.log.Actual Behavior
The log shows:
args: [local :], toComplete: "/"Bash has split the word at the colon. Cobra's completion logic follows this split, forcing the developer to manually reconstruct the original word from
argsandtoCompleteto understand the context (in this case, that the user is asking for completion from thelocalprovider). which differs from usage withPreRunEandRunEwhich accept them as one argumentExpected Behavior
toCompleteshould ideally represent the full word as it does inPreRunEandRunE.For example:
args: [], toComplete: "local:/"Environment
bash-completionenabled)