# CLI Completion

`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](https://pub.dev/packages/completion) and the excellent [tab tab package](https://github.com/mklabs/tabtab) for JS CLIs.

It works on bash and zsh on Linux, macOS, and Windows.

## How It Works

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](#the-installation-process).

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](#how-parsing-completion-works).

### The Installation Process

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.

### How Parsing Completion Works

`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.

### Use Cases

You can find below some completion use cases that is handled by this package:

Completes with options and subcommands:
```bash
$ 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_command
```

Completes partially written commands and options:
```bash
$ example_cli some|
some_command        -- This is help for some_command
```

Hides aliases and hidden options and commands:
```bash
$ 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 negated
```
 
Completes with values of option with "allowed" values:
```bash
example_cli some_command --discrete |
bar  -- bar help
faa  -- faa help
foo  -- foo help
```

For more use cases, check out the [integration tests](https://github.com/VeryGoodOpenSource/cli_completion/blob/main/example/test/integration/completion_integration_test.dart).
