File completion is triggered even when `cobra.ShellCompDirectiveNoFileComp` is used
bartekpacia opened this issue ยท 2 comments
Hi ๐๐ป This is my first issue in this repo. Thanks to everyone who spends their free time maintaining this amazing module. I respect and appreciate it very much.
I think I've found a bug in Cobra's shell completion, which results in Zsh's default "file completion" being always activated when all flags and arguments are used. I created a reproducible example and a video:
Bug video demo
repro.mp4
Reproducer
Build with:
go build -o go-cobra ./main.go
Code:
package main
import (
"fmt"
"os"
"slices"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
func main() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
var rootCmd = &cobra.Command{
Use: "go-cobra",
Short: "A brief description of your application",
ValidArgsFunction: cobra.NoFileCompletions,
}
var runCmd = &cobra.Command{
Use: "run",
Short: "Run app on device",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("run called")
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
completions := []string{"app1", "app2", "app3"}
for _, arg := range args {
for i, completion := range completions {
if arg == completion {
completions = slices.Delete(completions, i, i+1)
}
}
}
return completions, cobra.ShellCompDirectiveNoFileComp
},
}
func init() {
rootCmd.AddCommand(runCmd)
runCmd.Flags().AddFlag(&pflag.Flag{
Name: "device",
Usage: "Select device to run on",
})
runCmd.RegisterFlagCompletionFunc(
"device",
func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{"emulator-5554", "Barteks-iPhone"}, cobra.ShellCompDirectiveNoFileComp
},
)
}
I set cobra.ShellCompDirectiveNoFileComp
everywhere I could, but file completion is triggered at the end anyway.
I'd very much appreciate a fix to this problem, or confirmation if this is a bug.
The definition of the flag seems problematic.
It should be defined like this:
runCmd.Flags().String(
"device",
"",
"Select device to run on",
)
I was able to figure this out by using the __complete
command manually to see what was happening to shell completion:
$ ./go-cobra __complete run --device Barteks-iPhone ''
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x18 pc=0x104609788]
goroutine 1 [running]:
github.com/spf13/pflag.(*FlagSet).Set(0x140000c2100, {0x10464f76f, 0x6}, {0x16b9135ab, 0xe})
/Users/kmarc/go/pkg/mod/github.com/spf13/pflag@v1.0.5/flag.go:463 +0x78
github.com/spf13/pflag.(*FlagSet).Parse.func1(0x1046c0ee0?, {0x16b9135ab?, 0x16b9135a4?})
/Users/kmarc/go/pkg/mod/github.com/spf13/pflag@v1.0.5/flag.go:1138 +0x40
[...]
See this doc: https://github.com/spf13/cobra/blob/main/site/content/completions/_index.md#debugging
Thank you very much โ this helped! :-)