cli_completion is a Dart package that aims to enable Dart CLI applications to receive shell completions with minimal setup. You can also customize completion suggestions programmatically.
It is inspired by Kevin Moore's package completion and the excellent tab tab package for JS CLIs.
It works on bash and zsh on Linux, macOS, and Windows.
There are several ways to achieve shell completions for CLI commands. Most of them depend on which shell you are using and, in some cases, the terminal.
The approach used by cli_completion is to create shell script files in a directory under the user's home ( $XDG_CONFIG_HOME/.dart-cli-completion or ~/.dart-cli-completion for Linux/macOS users) and then source these scripts in the shell initialization files (~/.zshrc, for example). For Windows users, completion information is stored in local app data (typically something like C:\Users\You\AppData\Local). Currently, completion will only work from a bash shell on Windows.
We call this process installation.
Then, scripts are installed and sourced (via source ~/.zshrc).
These scripts instruct the shell to call the “completion” subcommand in the CLI when the user presses <TAB>.
Then, the messages generated by that command will be sent back to the shell, which will take care of formatting it and displaying it to the user as completion suggestions.
We call this process parsing.
The class CompletionCommandRunner tries to create these files upon any command run. It does nothing if the completion files exist and displays a short error message if there is an error in the process.
To disable this behavior, set enableAutoInstall to false on your CompletionCommandRunner subclass.
CompletionCommandRunner is responsible for handling the completion sub-command and reading some particular environment variables that contain the state of the user input upon tab press.
Once it parses the user input, it reads the ArgParser grammar to create valid suggestions.
You can find below some completion use cases that is handled by this package:
Completes with options and subcommands:
$ example_cli |
--rootFlag -- A flag: in the root command
some_command -- This is help for some_command
some_other_command -- This is help for some_other_commandCompletes partially written commands and options:
$ example_cli some|
some_command -- This is help for some_commandHides aliases and hidden options and commands:
$ example_cli some_command|
--continuous -- A continuous option: any value is allowed
--discrete -- A discrete option with "allowed" values (mandatory)
--help -- Print this usage information.
--inverseflag -- A flag that the default value is true
--multi-c -- An continuous option that can be passed multiple times
--multi-d -- An discrete option that can be passed multiple times
--trueflag -- A flag that cannot be negatedCompletes with values of option with "allowed" values:
example_cli some_command --discrete |
bar -- bar help
faa -- faa help
foo -- foo helpFor more use cases, check out the integration tests.