Documentation
¶
Overview ¶
Package complete provides a library for writing shell-agnostic tab completion.
Full documentation is located in the README. Otherwise, follow the below examples and API docs to get started!
Example (Barebones) ¶
Barebones tab completion for a very naive 'cp' program
package main import ( "github.com/coxley/complete" "github.com/coxley/complete/predict" ) func main() { // Barebones 'cp' completion comp := complete.New2(complete.NopParser(complete.Command{ Sub: nil, Flags: complete.Flags{ "--force": predict.Nothing, "--help": predict.Nothing, "--version": predict.Nothing, "--target-directory": predict.Dirs("*"), }, // This is the default when there are no sub-commands set Args: predict.Files("*"), })) if comp.Complete() { return } }
Output:
Example (Barebones_SubCommands) ¶
Barebones tab completion for a very naive 'git' program
package main import ( "github.com/coxley/complete" "github.com/coxley/complete/args" "github.com/coxley/complete/predict" ) func main() { comp := complete.New2(complete.NopParser(complete.Command{ Sub: complete.Commands{ "switch": complete.Command{ Flags: complete.Flags{ "--quiet": predict.Nothing, }, Args: predict.Func(func(a args.Args) []string { return []string{"branch1", "branch2", "master"} }), }, "commit": complete.Command{ Flags: complete.Flags{ "--message": predict.Nothing, "--author": predict.Func(func(a args.Args) []string { // Maybe this looks up authors that have previously committed // and suggests them return nil }), }, Args: predict.Func(func(a args.Args) []string { // This could return valid pathspecs return nil }), }, }, GlobalFlags: complete.Flags{ "--help": predict.Nothing, "--version": predict.Nothing, }, // Args will default to sub-commands if not set })) if comp.Complete() { return } }
Output:
Example (Cobra) ¶
Cobra commands can be given directly into [cmpcobra.New] to generate a skeleton for you.
Individual flags and commmands can have their prediction logic overriden.
package main import ( "github.com/spf13/cobra" "github.com/coxley/complete" "github.com/coxley/complete/args" "github.com/coxley/complete/cmpcobra" "github.com/coxley/complete/predict" ) func main() { cmd := &cobra.Command{ Use: "toggle-log-levels", Short: "Toggle log levels on a remote service for a period of time", // These will be included in suggestions ValidArgs: []string{"debug", "info", "warn", "error"}, // We're not using the cobra completions so don't suggest it in help output CompletionOptions: cobra.CompletionOptions{ DisableDefaultCmd: true, }, } flags := cmd.Flags() flags.StringP("service", "s", "all", "Service to toggle logs on") // Override the default prediction value for string flags cmpcobra.RegisterFlag(cmd, "service", predict.Func(func(a args.Args) []string { return []string{"service1", "service2", "service3"} })) comp := complete.New2(cmpcobra.New(cmd)) if comp.Complete() { return } }
Output:
Example (CobraDynamic) ¶
CLI that returns information about a service, but the information available changes depending on the type of service.
Dynamic tab completion can take into account other arguments to influence suggestions. In this case, we change the --field recommendations based on the service positional argument.
package main import ( "fmt" "maps" "os" "slices" "github.com/spf13/cobra" "github.com/coxley/complete" "github.com/coxley/complete/args" "github.com/coxley/complete/cmpcobra" "github.com/coxley/complete/cmplog" "github.com/coxley/complete/predict" ) // These services are either "request-oriented" or "message-broker-oriented" and have // different metadata. var services = map[string]map[string]string{ "server1": { "grpc_addr": "some.host:50051", }, "server2": { "grpc_addr": "other.host:50051", }, "consumer1": { "pubsub_topic": "some_topic", "pubsub_subscription": "some_topic/some_subscription", }, "consumer2": { "pubsub_topic": "other_topic", "pubsub_subscription": "other_topic/other_subscription", }, } // CLI that returns information about a service, but the information available // changes depending on the type of service. // // Dynamic tab completion can take into account other arguments to influence // suggestions. In this case, we change the --field recommendations based on the // service positional argument. func main() { cmd := &cobra.Command{ Use: "svc_registry", Args: cobra.ExactArgs(1), ValidArgs: slices.Collect(maps.Keys(services)), RunE: run, } cmd.Flags().StringArrayP("field", "f", nil, "service fields to print") cmpcobra.RegisterFlag(cmd, "field", predict.Func(predictFields)) // If tab-completion takes place, exit if complete.New2(cmpcobra.New(cmd)).Complete() { return } // Otherwise proceed as usual if err := cmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) } } func run(cmd *cobra.Command, args []string) error { // Print each requested field from the service registry svc := args[0] fields := services[svc] wanted, err := cmd.Flags().GetStringArray("field") if err != nil { return err } for _, f := range wanted { fmt.Printf("%s:\t%q\n", f, fields[f]) } return nil } // predictFields returns the available fields for a given service if it's been // specified on the command-line func predictFields(args args.Args) []string { root, ok := args.ParsedRoot.(*cobra.Command) if !ok { cmplog.Log("root cobra command not parsed") } posArgs := root.Flags().Args() if len(posArgs) == 0 { // No suggestions to give if a service hasn't been specified return nil } validFields := services[posArgs[0]] return slices.Collect(maps.Keys(validFields)) }
Output:
Index ¶
- Variables
- type Argsdeprecated
- type Command
- type CommandParser
- type Commander
- type Commands
- type Complete
- type Flags
- type Parserdeprecated
- type PredictFuncdeprecated
- type Predictordeprecated
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // Deprecated: See [predict.Or] PredictOr = predict.Or // Deprecated: See [predict.Nothing] PredictNothing = predict.Nothing // Deprecated: See [predict.Anything] PredictAnything = predict.Anything // Deprecated: See [predict.Dirs] PredictDirs = predict.Dirs // Deprecated: See [predict.Files] PredictFiles = predict.Files // Deprecated: See [predict.Set] PredictSet = predict.Set )
var Log = cmplog.Log
Functions ¶
This section is empty.
Types ¶
type CommandParser ¶
CommandParser should generate a fully-structured Command and parse arguments into an object that predictors can use.
func NopParser ¶
func NopParser(command command.Command) CommandParser
NopParser returns a CommandParser that returns nil when parsing.
type Complete ¶
Complete structs define completion for a command with CLI options
func New ¶
New creates a new complete command.
'name' is unused, but is kept for backward-compatibility with posener/complete. It used to be used for installation of the completion script, but we prefer using os.Args[0] to allow the user to control what they name their binaries.
func New2 ¶
func New2(cp CommandParser) *Complete
New2 returns a completer structured by the CommandParser
By accepting an args.Parser, predictors can gain extra insight to the command at large to influence their suggestions. The result of args.Parser.Parse is stored in args.Args.ParsedRoot before any predictors run.
Suggestions are printed to os.Stdout.
func New2F ¶
func New2F(w io.Writer, cp CommandParser) *Complete
New2F returns a completer that writes suggestions to 'w'
func (*Complete) Complete ¶
Complete determines if the user needs suggestions, and returns true if so. Programs should exit when true.
Environment variables that control our logic:
- COMP_LINE: prompt of the user
- COMP_POINT: cursor position wher tab was pressed
- COMP_INSTALL=1: install completion script into the user's shell
- COMP_UNINSTALL=1: uninstall completion script from the user's shell
- COMP_YES=1: don't prompt when installing or uninstall
type Parser
deprecated
Deprecated: See args.Parser
type PredictFunc
deprecated
type PredictFunc = oldFunc
Deprecated: See predict.Func
type Predictor
deprecated
Deprecated: See predict.Predictor
Directories
¶
Path | Synopsis |
---|---|
Package cmptest includes helper functions to validate tab completion
|
Package cmptest includes helper functions to validate tab completion |
examples
|
|
install
Package install provide installation functions of command completion.
|
Package install provide installation functions of command completion. |