Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add CompletionFunc type to help with completions #2220

Merged
merged 2 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion command.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ type Command struct {
// ValidArgsFunction is an optional function that provides valid non-flag arguments for shell completion.
// It is a dynamic version of using ValidArgs.
// Only one of ValidArgs and ValidArgsFunction can be used for a command.
ValidArgsFunction func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
ValidArgsFunction CompletionFunc

// Expected arguments
Args PositionalArgs
Expand Down
19 changes: 14 additions & 5 deletions completions.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const (
)

// Global map of flag completion functions. Make sure to use flagCompletionMutex before you try to read and write from it.
var flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){}
var flagCompletionFunctions = map[*pflag.Flag]CompletionFunc{}

// lock for reading and writing from flagCompletionFunctions
var flagCompletionMutex = &sync.RWMutex{}
Expand Down Expand Up @@ -117,22 +117,31 @@ type CompletionOptions struct {
HiddenDefaultCmd bool
}

// CompletionFunc is a function that provides completion results.
type CompletionFunc func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)

// NoFileCompletions can be used to disable file completion for commands that should
// not trigger file completions.
//
// This method satisfies [CompletionFunc] and can be used with [Command.RegisterFlagCompletionFunc]
marckhouzam marked this conversation as resolved.
Show resolved Hide resolved
func NoFileCompletions(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
return nil, ShellCompDirectiveNoFileComp
}

// FixedCompletions can be used to create a completion function which always
// returns the same results.
func FixedCompletions(choices []string, directive ShellCompDirective) func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
//
// This method returns a function that satisfies [CompletionFunc] and can be used with [Command.RegisterFlagCompletionFunc]
marckhouzam marked this conversation as resolved.
Show resolved Hide resolved
func FixedCompletions(choices []string, directive ShellCompDirective) CompletionFunc {
return func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
return choices, directive
}
}

// RegisterFlagCompletionFunc should be called to register a function to provide completion for a flag.
func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)) error {
//
// You can use [FixedCompletions] or [NoFileCompletions] as completion functions.
marckhouzam marked this conversation as resolved.
Show resolved Hide resolved
func (c *Command) RegisterFlagCompletionFunc(flagName string, f CompletionFunc) error {
flag := c.Flag(flagName)
if flag == nil {
return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' does not exist", flagName)
Expand All @@ -148,7 +157,7 @@ func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Comman
}

// GetFlagCompletionFunc returns the completion function for the given flag of the command, if available.
func (c *Command) GetFlagCompletionFunc(flagName string) (func(*Command, []string, string) ([]string, ShellCompDirective), bool) {
func (c *Command) GetFlagCompletionFunc(flagName string) (CompletionFunc, bool) {
flag := c.Flag(flagName)
if flag == nil {
return nil, false
Expand Down Expand Up @@ -519,7 +528,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
}

// Find the completion function for the flag or command
var completionFn func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
var completionFn CompletionFunc
if flag != nil && flagCompletion {
flagCompletionMutex.RLock()
completionFn = flagCompletionFunctions[flag]
Expand Down
Loading