188 lines
10 KiB
Markdown
188 lines
10 KiB
Markdown
# Shell completion
|
|
|
|
Status: initial scope and all four product decisions selected; implementation
|
|
has not started. Provide canonical suggestions with alias-aware interpretation
|
|
for Bash, Zsh, and Fish through explicitly installed completion support.
|
|
|
|
## Purpose
|
|
|
|
Provide useful shell completion for core-only applications and applications with
|
|
optional integrations. Reuse installed command declarations and CommandKit's
|
|
routing rules so consumers need little completion-specific wiring.
|
|
|
|
Completion helps an operator construct an invocation. It does not execute the
|
|
selected application command. Preserve application ownership of runtime behavior
|
|
and upstream ownership of configuration and prompt semantics.
|
|
|
|
## Current baseline
|
|
|
|
Reviewed baseline: `2301872` (`Stop flag interpretation at unknown flags`).
|
|
|
|
- Core captures declarations and builds a routing snapshot containing canonical
|
|
commands and separate application aliases.
|
|
- [Neutral metadata](../../internal/commandmeta/metadata.go) describes command
|
|
names, descriptions, flags, boolean/value distinctions, repetition, required
|
|
flags, and operand cardinality. It has no completion choices or path hints.
|
|
- The [Cobra adapter](../../internal/cobra/parse.go) constructs a backend tree
|
|
for parsing and help. CommandKit owns execution and presentation outside that
|
|
tree; enabling Cobra's default completion command alone is insufficient.
|
|
- [Alias routing](../../route.go) resolves complete command paths and coordinates
|
|
canonical parsing with entered spellings. Completion must also handle partial
|
|
words and an empty current word.
|
|
- Invocation reporting controls ordinary output and diagnostics. Shell completion
|
|
queries need machine-readable replies independent of flags in the unfinished
|
|
command line.
|
|
- The core module uses Cobra v1.10.1 and pflag v1.0.9. Cobra supplies script
|
|
generators and completion callbacks for Bash, Zsh, Fish, and PowerShell.
|
|
See its [versioned completion documentation](https://github.com/spf13/cobra/blob/v1.10.1/site/content/completions/_index.md).
|
|
|
|
[ADR 0013](../adr/0013-application-alias-routing.md) owns the separation between
|
|
alias routes and canonical commands. [ADR 0014](../adr/0014-invocation-reporting.md)
|
|
owns invocation reporting. This roadmap defines completion within those
|
|
boundaries; it does not establish a replacement command model.
|
|
|
|
## Target experience
|
|
|
|
An operator generates and loads a shell integration script, then receives
|
|
suggestions for installed commands, applicable canonical flags, and declared
|
|
value choices or paths. The selected script-generation grammar is:
|
|
|
|
```text
|
|
app completion bash
|
|
app completion zsh
|
|
app completion fish
|
|
```
|
|
|
|
Consumers explicitly install a core completion declaration through the existing
|
|
installation API. The completion namespace is reserved only when installed.
|
|
Keep the machine query hidden from ordinary help, with collision validation for
|
|
its selected path. Installation must not replace an application-owned command.
|
|
|
|
Script generation writes to the caller-selected result stream. Shell setup
|
|
instructions explain loading the script; automatic modification of shell startup
|
|
files is outside the initial implementation.
|
|
|
|
The initial MVP suggests canonical command names and flag spellings. Completed aliases
|
|
already entered by the operator are interpreted to identify the canonical target.
|
|
For example, with `jobs` routing to `workspace jobs`, completing after
|
|
`app jobs ` can suggest the canonical children of `workspace jobs`.
|
|
Completion should preserve the text the operator has already entered.
|
|
|
|
Matching partial canonical names, resolving completed aliases, and interpreting
|
|
an alias-only discovery prefix are distinct cases. Initially, an alias-only
|
|
prefix with no canonical target offers no command continuations. For example,
|
|
if `legacy inspect` is an alias but `legacy` has no canonical target,
|
|
`app legacy <TAB>` offers no command continuations. After the complete alias is
|
|
entered, completion uses its canonical target. Applicable flag suggestions can
|
|
still follow the existing discovery context.
|
|
|
|
Suggested continuations must form a valid next step when inserted into the
|
|
entered route. Do not append canonical words that would create an invalid route.
|
|
Alias discovery may be omitted from the initial MVP; this is a scope choice,
|
|
not a permanent limitation of CommandKit. Suggesting alias names or alias-path
|
|
continuations remains [potential future work](deferred.md#alias-completion-and-discovery).
|
|
|
|
### Flag suggestions
|
|
|
|
Initially suppress already supplied singleton flags from flag-name suggestions.
|
|
Canonical and aliased occurrences count as the same flag. Keep repeatable flags
|
|
available. Keep all four reporting flags (`--quiet`, `--verbose`, `--debug`, and
|
|
`--progress`) available because later occurrences can intentionally change or
|
|
reset their settings.
|
|
|
|
Suggestion filtering leaves accepted syntax unchanged. Operators can still type
|
|
singleton flags again under the existing repetition rules. If an operator has
|
|
already entered a repeated flag, continue completing its value according to its
|
|
hint even when its name would have been omitted from suggestions.
|
|
|
|
## Selected initial scope
|
|
|
|
Provide canonical command and flag suggestions, descriptions where supported by
|
|
the selected shells, alias-aware interpretation, static value choices, and
|
|
file/directory hints. Apply the same declaration facilities to application-owned
|
|
commands and optional integrations.
|
|
|
|
Support Bash, Zsh, and Fish using the existing backend generators, with validation
|
|
in each shell. PowerShell is outside the initial supported shell set because
|
|
there is no current consumer need; this does not preclude future support.
|
|
|
|
Static suggestions should come from captured metadata. Completion should not
|
|
invoke ordinary handlers, input/state factories, or acquisition callbacks to
|
|
obtain it. Application startup and declaration-factory effects remain owned by
|
|
the consumer, just as they do for help.
|
|
|
|
Dynamic discovery of configured prompt names, remote resources, or other live
|
|
values is a possible later extension. Deferring it avoids selecting provider
|
|
lifetimes and latency behavior before a concrete consumer need; it is not a
|
|
permanent prohibition on dynamic completion.
|
|
|
|
## Ownership and implementation approach
|
|
|
|
Core owns completion context, alias interpretation, and neutral suggestions.
|
|
The internal backend adapter owns Cobra-specific types, directives, script
|
|
emission, and protocol details. Prefer the existing backend facilities where
|
|
compatible with CommandKit's grammar. Verify the adapter approach with a small
|
|
end-to-end prototype before fixing private interfaces.
|
|
|
|
A completion request identifies completed words and the current partial word,
|
|
including an empty word after a space. Interpret only what is needed to locate
|
|
suggestions. Ordinary required-value validation and input conversion must not
|
|
reject a partially constructed invocation before completion can help fill it.
|
|
Reuse token and flag interpretation helpers where practical without changing
|
|
normal execution grammar or treating incomplete input as an executable command.
|
|
|
|
Account for command-local flags, aliases, consumed values, `--`, attached values,
|
|
boolean assignments, short clusters, repeatable flags, and operand positions.
|
|
Keep provenance sufficient to return a replacement for the word being edited.
|
|
Completion candidates are suggestions, not an additional input validator.
|
|
|
|
When both an operand and a flag are valid, use the operand's hint for an
|
|
empty current word after a space. Offer flag names when the operator starts
|
|
the word with `-` in a context where flags are accepted.
|
|
|
|
Value choices and path hints belong in CommandKit-owned public metadata. Carry
|
|
them through declaration capture and neutral metadata to the adapter. Arbitrary
|
|
converter functions cannot reliably reveal their accepted values. Adding a list
|
|
of suggestions must not silently restrict the values a converter accepts.
|
|
|
|
Provide declarative static choices with optional descriptions, file/directory
|
|
hints, and an explicit way to request no value suggestions. Unannotated values
|
|
default to no value suggestions; applicable commands and flags still complete.
|
|
Filename completion requires a path hint. This keeps unrelated filenames out of
|
|
identifier and numeric completions. The implementation plan specifies how hints
|
|
fit into existing binding declarations.
|
|
|
|
Initially use one hint strategy per value position: static choices, files,
|
|
directories, or no value suggestions. Optional choice descriptions belong to the
|
|
static-choice strategy. Combined choices and filesystem suggestions can be
|
|
considered later if consumers need them; the initial API need not define their
|
|
merging or deduplication behavior.
|
|
|
|
Verify the same strategy works for separated and attached flag values, such as
|
|
`app serve --config ./par<TAB>` and `app serve --config=./par<TAB>`. For the
|
|
attached form, preserve `--config=` and complete its value correctly. Validate
|
|
the resulting command line in each supported shell.
|
|
|
|
Keep ordinary script generation under the existing reporting policy. A hidden
|
|
shell query is a protocol exchange: flags in the command being completed are
|
|
request data, so `--quiet` must not erase its reply and `--debug` must not append
|
|
ordinary diagnostics to it. When an unrecognized or incomplete command line
|
|
leaves no inferable completion context, return a valid empty reply that disables filename fallback. Reserve
|
|
protocol errors for failures in the query itself. Specify their wire behavior
|
|
and output ownership in the implementation plan. A completion request must not
|
|
accidentally run the target command.
|
|
Hidden protocol names are implementation details unless deliberately published.
|
|
|
|
## Delivery plan
|
|
|
|
The [implementation plan](implementation.md) owns the sprint sequence, API and
|
|
protocol design, and validation steps. The target includes behavioral coverage
|
|
and shell-level validation through the public consumer path in Bash, Zsh, and
|
|
Fish.
|
|
|
|
## Deferred scope
|
|
|
|
Alias discovery remains a potential extension beyond the MVP. Dynamic discovery
|
|
remains deferred until a concrete consumer need justifies its callback,
|
|
cancellation, error-handling, and provider-lifetime design.
|