<!-- SPDX-License-Identifier: GPL-2.0-or-later -->
# Testing the shell completions

The completion scripts are generated by `generate-completions.py` from the
metadata `nvme utils dump-command-metadata` emits. All three shells (bash, zsh,
PowerShell) receive the same command/option data; differences in behavior are
limited to differences in each shell's completion framework capabilities.

The automated suites (`test-bash-completion.sh`, `test-zsh-completion.sh`,
`test-powershell-completion.ps1`) cover the generator's routing and value data.
They cannot fully test how the live completion system *renders* results, so the
checklists below should also be verified by hand in a live shell after
regenerating.

## Loading the completion

**bash**

```sh
source completions/bash-nvme-completion.sh
```

**zsh** — clear the completion cache first so a regenerated `_nvme` is picked up:

```sh
rm -f ~/.zcompdump*
fpath=($PWD/completions $fpath)
autoload -Uz compinit && compinit -u
compdef _nvme nvme
```

**PowerShell** — dot-source the script (or add the line to your `$PROFILE`):

```powershell
. completions/nvme-completion.ps1
```

## How completion is triggered

In bash and zsh, <kbd>Tab</kbd> lists or cycles through candidates. In
PowerShell, <kbd>Tab</kbd> cycles through candidates one at a time and
<kbd>Ctrl+Space</kbd> shows the full list. Note that
<kbd>Ctrl+Space</kbd> may not work in VS Code's integrated terminal
because VS Code binds that key to IntelliSense; test in a standalone
PowerShell terminal or rebind the VS Code shortcut. The checklists below
show `<tab>` generically — use whichever trigger is appropriate for the
shell under test.

## All shells

These behaviors are identical in bash, zsh, and PowerShell.

- [ ] **Top-level commands** — `nvme <tab>` lists builtins (`list`,
      `format`, …), plugin names (`feat`, `id`, …), and `help`/`version`.
- [ ] **Prefix filter** — `nvme write-<tab>` narrows to `write-zeroes`,
      `write-uncor`, ….
- [ ] **Command alias** — `nvme fw ac<tab>` offers `activate` (alias of
      `commit`); `nvme fw activate <tab>` completes `commit`'s options.
- [ ] **Plugin sub-commands** — `nvme feat <tab>` lists the plugin's
      sub-commands; `nvme ocp <tab>` does too (routing is not hard-coded to one
      plugin).
- [ ] **Sub-command alias** — `nvme dera <tab>` offers both `smart-log-add` and
      its alias `stat`.
- [ ] **Options plus device** — `nvme id ctrl <tab>` (no leading `-`) offers
      short options, long options, and the device candidate together.
- [ ] **A command without global options** — `nvme intel lat-stats-tracking
      <tab>` offers `-e`/`--enable`, `-d`/`--disable`, `-h`/`--help`, and
      the device candidate, but *not* `--output-format`.
- [ ] **Enumerated value** — `nvme id ctrl --output-format <tab>`,
      `nvme id ctrl -o <tab>`, and `nvme id ctrl --output-format=<tab>` all
      list `normal json binary tabular`.
- [ ] **Value from a hint** — `nvme feat power-meas --sel <tab>` lists
      `0 1 2 3`.
- [ ] **Command-local value** — `nvme fw commit --action <tab>` lists
      `replace … set-active …`.
- [ ] **File-valued option** — `nvme fw download --fw <tab>` completes
      filenames.
- [ ] **help completes a command** — `nvme help <tab>` lists command names (the
      same set as top-level `nvme <tab>`), since `nvme help CMD` prints that
      command's help.
- [ ] **No device for help/version** — `nvme help <tab>` offers no device;
      `nvme version <tab>` offers nothing at all.
- [ ] **Prefix ambiguity** — `nvme id ctrl --output-format<tab>` (no trailing
      space) offers both `--output-format` and `--output-format-version`;
      neither is swallowed by an exact-prefix match.

## Bash & zsh

These items apply to both Unix shells but not PowerShell.

- [ ] **Long options only** — `nvme id ctrl --<tab>` offers only long options
      (`--output-format`, `--help`, …).
- [ ] **Short and long options** — `nvme id ctrl -<tab>` offers both short
      (`-o`, `-v`, …) and long options.
- [ ] **No device when one is present** — `nvme id ctrl /dev/nvme0 <tab>` does
      not offer a second device.
- [ ] **help takes one argument** — `nvme help id ctrl <tab>` offers nothing
      (no filename fall-back past it).
- [ ] **version takes no argument** — `nvme version <tab>` offers nothing at all
      (no options, no commands, no filenames).

## Zsh-specific

- [ ] **Menu completion cycling** — with `MENU_COMPLETE` or `AUTO_MENU`,
      completing `--output-forma<tab>` inserts `--output-format=` as a menu
      selection; a further `<tab>` cycles to `--output-format-version=` instead
      of descending to values. Type the first value character
      (`--output-format=j`) or accept the entry to reach values. This is the
      shell's native menu behavior, not the generated script.
- [ ] **Possibility count** — `nvme <tab>` may report far more "possibilities"
      than lines displayed (e.g. "452 possibilities" for ~153 commands).
      `_describe` pads multi-column grids with empty alignment matches; the
      displayed entries are correct.

## PowerShell-specific

- [ ] **Device hint** — `nvme id ctrl <tab>` offers `/dev/nvme` as a static
      hint (not a filesystem glob). The user types the rest (e.g. `0`, `0n1`).
- [ ] **`--` or `-` alone may not trigger completion** — the framework may
      treat a bare `--` as a parameter separator and not invoke the completer.
      A bare `-` may also not trigger depending on PSReadLine version and
      settings. Typing at least one character past the dashes (e.g. `--h` or
      `-o`) works fine.
- [ ] **File fallback on empty return** — when the completer returns nothing
      (e.g. `nvme version <tab>`), PowerShell's framework falls back to file
      completion. This cannot be suppressed from a native-command completer.

## Automated suites

`test-bash-completion.sh` drives the real bash dispatcher and inspects the real
`COMPREPLY`, so it tests what actually runs.

`test-zsh-completion.sh` must stub the zsh completion builtins (`_values`,
`_describe`, `compadd`, `_arguments`) to capture what the script offers; it
verifies the generator's routing and value lists but not how the live
completion system renders them.

`test-powershell-completion.ps1` calls `TabExpansion2` against the loaded
completer, which exercises the real completion path end-to-end.
