# Shell Completions

RSConstruct generates shell completion scripts that provide tab-completion for commands, subcommands, flags, and argument values.

## Generating Completions

```bash
# Generate for the default shell (configured in rsconstruct.toml)
rsconstruct complete

# Generate for a specific shell
rsconstruct complete bash
rsconstruct complete zsh
rsconstruct complete fish
```

To install, source the output in your shell profile:

```bash
# Bash (~/.bashrc)
eval "$(rsconstruct complete bash)"

# Zsh (~/.zshrc)
eval "$(rsconstruct complete zsh)"

# Fish (~/.config/fish/config.fish)
rsconstruct complete fish | source
```

## Configuration

The default shell(s) for `rsconstruct complete` (with no argument) are configured in `rsconstruct.toml`:

```toml
[completions]
shells = ["bash"]
```

## What Gets Completed

### Commands and subcommands

All top-level commands (`build`, `processors`, `analyzers`, `config`, etc.) and their subcommands complete automatically via clap.

### Processor type names (pnames)

These commands complete with processor type names from the plugin registry (e.g., `ruff`, `pylint`, `cc_single_file`):

- `rsconstruct processors defconfig <TAB>`
- `rsconstruct build --processors <TAB>` / `rsconstruct build -p <TAB>`
- `rsconstruct watch --processors <TAB>` / `rsconstruct watch -p <TAB>`

The list is drawn from the plugin registry at compile time.

### Processor instance names (inames)

These commands complete with instance names declared in the current project's `rsconstruct.toml` (e.g., `pylint`, `pylint.tests`, `cc_single_file`):

- `rsconstruct processors config <TAB>`
- `rsconstruct processors files <TAB>`

Instance names are extracted from `[processor.NAME]` and `[processor.NAME.SUBNAME]` headings in `rsconstruct.toml` at tab-completion time. Requires a project config in the current directory. Bash only.

### Analyzer names

These commands complete analyzer names (`cpp`, `markdown`, `python`, `tera`):

- `rsconstruct analyzers config <TAB>`
- `rsconstruct analyzers clean --analyzer <TAB>`

Analyzer names are specified via clap's `value_parser` attribute, so they work in all shells without post-processing.

### Flags and options

All `--flags` and `-f` short flags complete in all shells via clap's built-in generation.

## Implementation

Completions are generated by `clap_complete` in `src/cli.rs`. Two mechanisms provide argument-value completions:

### 1. clap `value_parser` (preferred)

For arguments with a small, fixed set of values, use `#[arg(value_parser = [...])]` on the field. This works in all shells automatically because clap embeds the values in the generated script.

Example from `AnalyzersAction::Config`:

```rust
#[arg(value_parser = ["cpp", "markdown", "python", "tera"])]
name: Option<String>,
```

### 2. Bash post-processing (processor names)

Processor names are not known to clap at derive time because they come from the `inventory` plugin registry. The function `inject_bash_processor_completions()` post-processes the generated bash script to inject processor names into the `opts` variable for specific command sections.

This only works for bash. Other shells get the base clap completions without processor name injection.

The targets for injection are identified by their case labels in the generated bash script:

- `rsconstruct__processors__config)`
- `rsconstruct__processors__defconfig)`
- `rsconstruct__processors__files)`

The function also patches `--processors` / `-p` flag completions in `build` and `watch` commands to suggest processor names instead of file paths.

## Adding Completions for New Arguments

- **Fixed set of values** (analyzer names, enum variants): Use `#[arg(value_parser = [...])]`. Works in all shells.
- **Dynamic set from registry** (processor names): Add the case label to `inject_bash_processor_completions()` targets. Only works in bash.
- **Enum types**: Use `#[arg(value_enum)]` on a clap-derived enum. Works in all shells.
