fix(zsh): consistently single-quote choice values containing spaces#635
Conversation
Previously, zsh's auto-quoting heuristic produced inconsistent quoting
styles: a choice value containing shell metacharacters like `A B & C`
was inserted as `'A B & C'`, but a value containing only spaces like
`Alice Alice` was inserted as `Alice\ Alice`. Both are valid, but the
inconsistency is jarring.
Now the generated zsh completion script:
- Strips user-supplied quoting from `words` via `${(Q)...}` before
invoking `usage complete-word`, so previously-typed args like
`'A B & C'` match their choice definitions.
- Builds a parallel `inserts` array where each value is pre-quoted with
`${(q-)val}` (single quotes for values needing quoting, raw
otherwise), then passes it to `_describe` with `-Q` to bypass zsh's
built-in auto-quoting.
- Forces `compstate[insert]=menu` when any value is pre-quoted, so the
longest-common-prefix heuristic doesn't insert just a stray opening
quote.
Fixes #634
There was a problem hiding this comment.
Code Review
This pull request enhances Zsh completion by improving the handling of choices containing spaces and ensuring proper quoting/unquoting of arguments. It introduces a regression test and updates the Zsh completion templates to use the (q-) flag for quoting choices and the (Q) flag for unquoting input words. Review feedback suggests making shell variables local to prevent environment pollution, replacing fragile manual character unescaping with Zsh's robust ${(Q)...} parameter expansion, and refactoring duplicated logic within the completion templates.
Greptile SummaryThis PR fixes inconsistent zsh completion quoting for choice values containing spaces or shell metacharacters by switching
Confidence Score: 5/5Safe to merge — the change is well-scoped to zsh completion output, manually verified end-to-end, and covered by both unit and integration tests. The core logic in No files require special attention. Important Files Changed
Reviews (3): Last reviewed commit: "chore: regenerate cli/assets/completions..." | Re-trigger Greptile |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #635 +/- ##
==========================================
- Coverage 78.94% 75.34% -3.60%
==========================================
Files 49 49
Lines 7284 7389 +105
Branches 7284 7389 +105
==========================================
- Hits 5750 5567 -183
- Misses 1147 1217 +70
- Partials 387 605 +218 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b07823f. Configure here.
…late Replaces the inline shell parser that hand-rolled escape-aware splitting of `value:description` strings with a tab-separated `<display>\t<insert>` format emitted directly by `usage complete-word --shell zsh`. Now the Rust side decides how to shell-quote each value (single quotes when needed, raw otherwise) and the shell side is reduced to a four-line loop that pushes the two columns into parallel arrays. `-U` is added to `_describe` so it doesn't re-filter the already-prefix-filtered matches returned by `complete-word`, which would otherwise discard them because their literal text starts with `'`. Behavior is unchanged from the previous commit's fix for #634; this is purely a structural cleanup.
The per-bin completion script (`complete_zsh`) and the shebang-fallback handler (`complete_zsh_init`) both emit the same loop that reads `<display>\t<insert>` columns and hands them to `_describe`. Factor that into `render_completion_loop` so a future change to the matching or quoting logic only has to be made in one place. Behavior unchanged.

Summary
Alice Alice) are now inserted by zsh completion as'Alice Alice', matching the existing behavior for values with shell metacharacters like'A B & C'. Previously zsh's auto-quoting heuristic chose backslash-style for one and single-quote style for the other.wordsvia${(Q)...}before invokingusage complete-word, so completion of subsequent args works even when earlier args were already entered quoted.compstate[insert]=menuwhen any value is pre-quoted, so the longest-common-prefix heuristic doesn't insert just a stray opening quote.Fixes #634
Test plan
cargo test --all --all-features— all tests pass except a pre-existingtest_bash_completion_init_integrationfailure unrelated to this change (system bash lackscomplete -D).test_zsh_completion_quotes_choices_with_spacesvalidates the generated script's parsing/quoting logic._misecompletion against this branch) —mise run test <TAB>producesmise run test 'A B & C', andmise run test 'A B & C' <TAB>producesmise run test 'A B & C' 'Alice Alice'with a clean menu showingAlice Alice Bob Bob Carol Carol.simple d<TAB>still expands tosimple dev.Note
Medium Risk
Changes the zsh completion output format and generated zsh completion scripts, which could break existing consumers or edge-case completion behaviors if any scripts assumed the previous single-column output.
Overview
Fixes zsh completions to consistently insert values with spaces/metacharacters using single-quote quoting by switching
usage complete-word --shell zshoutput to two tab-separated columns: a_describe-escaped display string and a shell-quoted insert string.Updates generated zsh completion scripts to parse the new
<display>\t<insert>format, pass unquoted user input via${(Q)words[@]}, use_describe ... -U -Qto insert the pre-quoted value verbatim, and forcecompstate[insert]=menuwhen any insert is pre-quoted; snapshots and integration/unit tests are updated and expanded to cover these behaviors.Reviewed by Cursor Bugbot for commit e0fb91a. Bugbot is set up for automated code reviews on this repo. Configure here.