Skip to content

fix: match completion prefix against unescaped names#460

Merged
jdx merged 2 commits intojdx:mainfrom
ilyagr:completion-bug
Jan 26, 2026
Merged

fix: match completion prefix against unescaped names#460
jdx merged 2 commits intojdx:mainfrom
ilyagr:completion-bug

Conversation

@ilyagr
Copy link
Contributor

@ilyagr ilyagr commented Jan 26, 2026

When using complete ... descriptions=#true, prefix matching was done against escaped strings (e.g., test\:integration) instead of unescaped names (test:integration). This caused completions to fail when user input contained an unescaped colon.

Fix by moving the filter to after the map that unescapes the names.

This bug caused a problem with mise: there was no shell completion if you entered mise test:i<tab> even if there was a test:integration task. mise run test:i<tab> was not affected, that is treated differently by mise's usage spec.


I feel that the test could be more readable, I might do that in a subsequent PR. I think all complete_word tests could use the fish syntax instead of the zsh syntax, so e.g.

"test:unit\tRun unit tests\ntest:integration\tRun integration tests\nbuild\tBuild the project\n"
// instead of 
"'test\\\\:unit'\\:'Run unit tests'\n'test\\\\:integration'\\:'Run integration tests'\n'build'\\:'Build the project'\n"

Let me know if you prefer I do that refactor first to make the diff here more readable (but it's not that bad)

Update: Apparently, that'd also make Copilot happer. Here's a draft: ilyagr@fish-refactor . Again, I'm happy to reorder the commits so that the cleaner syntax comes first. The biggest win from the refactor is in the test added in this PR, but others are also easier to read IMO for somebody unfamiliar with either shell's syntax.


This was mostly debugged by AI. If the fix is not correct, it could be considered a bug report (but it seems good to me).


Note

Fixes completion prefix matching when complete ... descriptions=#true by filtering after unescaping name:description outputs.

  • In complete_word.rs, process command output lines first (unescape and split) then filter by ctoken, so prefixes match unescaped names containing colons
  • Adds test complete_word_escaped_colons_in_completions and example colon-in-completions.usage.kdl to validate colon-containing completions

Written by Cursor Bugbot for commit e24490f. This will update automatically on new commits. Configure here.

When using `complete ... descriptions=#true`, prefix matching was done
against escaped strings (e.g., `test\:integration`) instead of unescaped
names (`test:integration`). This caused completions to fail when user
input contained an unescaped colon.

Fix by moving the filter to after the map that unescapes the names.

This bug caused a problem with mise: there was no shell completion if you entered `mise test:i<tab>` even if there was a `test:integration` task. `mise run test:i<tab>` was *not* affected, that is treated differently by `mise`'s `usage` spec.
Copilot AI review requested due to automatic review settings January 26, 2026 00:16
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a bug where shell completion prefix matching failed when completion names contained colons. The issue occurred because filtering was performed on escaped strings (e.g., test\:integration) before unescaping, causing user input like test: to not match.

Changes:

  • Moved the prefix filter operation to after the unescaping step in complete_word.rs
  • Added a comprehensive test case with an example usage file to verify colon handling in completions

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
cli/src/cli/complete_word.rs Repositioned the filter to match against unescaped completion names
cli/tests/complete_word.rs Added test function to verify prefix matching works with escaped colons
examples/colon-in-completions.usage.kdl Added example usage configuration demonstrating colon-containing completions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


// Empty input should match all completions
assert_cmd("colon-in-completions.usage.kdl", &["--", "run", ""])
.stdout("'test\\\\:unit'\\:'Run unit tests'\n'test\\\\:integration'\\:'Run integration tests'\n'build'\\:'Build the project'\n");
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assertion line exceeds typical line length limits (appears to be >120 characters). Consider breaking it into multiple lines for better readability, similar to how the other assertions in this test are formatted.

Suggested change
.stdout("'test\\\\:unit'\\:'Run unit tests'\n'test\\\\:integration'\\:'Run integration tests'\n'build'\\:'Build the project'\n");
.stdout(concat!(
"'test\\\\:unit'\\:'Run unit tests'\n",
"'test\\\\:integration'\\:'Run integration tests'\n",
"'build'\\:'Build the project'\n",
));

Copilot uses AI. Check for mistakes.
@codecov
Copy link

codecov bot commented Jan 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 76.73%. Comparing base (85378c5) to head (e24490f).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #460   +/-   ##
=======================================
  Coverage   76.73%   76.73%           
=======================================
  Files          47       47           
  Lines        6250     6250           
  Branches     6250     6250           
=======================================
  Hits         4796     4796           
  Misses       1102     1102           
  Partials      352      352           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jdx
Copy link
Owner

jdx commented Jan 26, 2026

bugbot run

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

@jdx jdx merged commit b325e9f into jdx:main Jan 26, 2026
11 checks passed
jdx pushed a commit that referenced this pull request Jan 26, 2026
### 🚀 Features

- **(lint)** add more lint checks by [@jdx](https://github.com/jdx) in
[#446](#446)
- add logo to docs site by [@jdx](https://github.com/jdx) in
[#442](#442)
- add VT323 retro terminal font and --usage branding by
[@jdx](https://github.com/jdx) in
[#443](#443)
- add missing builder methods by [@jdx](https://github.com/jdx) in
[#444](#444)

### 🐛 Bug Fixes

- use pithy LLM-generated title for GitHub releases by
[@jdx](https://github.com/jdx) in
[#441](#441)
- replace unwrap calls with proper error handling in fig.rs by
[@jdx](https://github.com/jdx) in
[#454](#454)
- improve error messages with more context by
[@jdx](https://github.com/jdx) in
[#449](#449)
- skip powershell test if pwsh is not installed by
[@jdx](https://github.com/jdx) in
[#457](#457)
- match completion prefix against unescaped names by
[@ilyagr](https://github.com/ilyagr) in
[#460](#460)

### 🚜 Refactor

- simplify Spec::merge with local macros by
[@jdx](https://github.com/jdx) in
[#451](#451)

### 📚 Documentation

- add CLAUDE.md for Claude Code guidance by
[@jdx](https://github.com/jdx) in
[#452](#452)
- escape generic type parameters in macro doc comments by
[@jdx](https://github.com/jdx) in
[#453](#453)
- add rustdoc for public API functions by [@jdx](https://github.com/jdx)
in [#450](#450)
- add documentation to public API structs by
[@jdx](https://github.com/jdx) in
[#455](#455)
- add conventional commit guidance to CLAUDE.md by
[@jdx](https://github.com/jdx) in
[#459](#459)

### ⚡ Performance

- remove unnecessary clone in set_subcommand_ancestors by
[@jdx](https://github.com/jdx) in
[#448](#448)

### 🧪 Testing

- add test coverage for untested modules by
[@jdx](https://github.com/jdx) in
[#447](#447)

### 🔍 Other Changes

- remove commented-out trait implementations in mount.rs by
[@jdx](https://github.com/jdx) in
[#445](#445)
- make codecov checks informational by [@jdx](https://github.com/jdx) in
[#456](#456)

### 📦️ Dependency Updates

- lock file maintenance by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#439](#439)

### New Contributors

- @ilyagr made their first contribution in
[#460](#460)
jdx pushed a commit that referenced this pull request Jan 26, 2026
As previously advertised in #460. This
is purely a refactor, the tests are functionally unchanged.

-------------

Fish's completion output format uses tabs between name and description,
and doesn't require quoting or escaping colons. This makes test
assertions much more readable:

Before (zsh): `"'task-a'\\:'Task from default dir'"`
After (fish): `"task-a\tTask from default dir"`

This is especially valuable for completions containing colons, where
zsh's escaping becomes nearly unreadable:

Before (zsh): `"'test\\\\:unit'\\:'Run unit tests'"`
After (fish): `"test:unit\tRun unit tests"`

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Refactors CLI completion tests to use fish’s output format for simpler
assertions.
> 
> - Switches `cli/tests/complete_word.rs` from zsh to `--shell fish`
(via `cmd(...)` and `assert_cmd(...)`), updating specific tests
accordingly
> - Updates expected outputs: removes quoting/escaping, uses plain names
and tab-delimited `name description` where applicable
> - Adjusts predicates from quoted matches to unquoted (e.g.,
`contains("install")`), and updates file/special cases (colons, flags,
files) to fish formatting
> - No production code changes
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3fe0751. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Ilya Grigoriev <ilyagr@users.noreply.github.com>
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Jan 27, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [usage](https://github.com/jdx/usage) | minor | `2.13.1` → `2.15.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>jdx/usage (usage)</summary>

### [`v2.15.0`](https://github.com/jdx/usage/blob/HEAD/CHANGELOG.md#2150---2026-01-26)

[Compare Source](jdx/usage@v2.14.0...v2.15.0)

##### 🚀 Features

- **(parse)** add Parser builder for custom env var handling by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;464](jdx/usage#464)

##### 🧪 Testing

- **(cli)** use fish output format for cleaner assertions by [@&#8203;ilyagr](https://github.com/ilyagr) in [#&#8203;461](jdx/usage#461)

##### 🔍 Other Changes

- add cargo-semver-checks to detect breaking changes by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;463](jdx/usage#463)

### [`v2.14.0`](https://github.com/jdx/usage/blob/HEAD/CHANGELOG.md#2140---2026-01-26)

[Compare Source](jdx/usage@v2.13.1...v2.14.0)

##### 🚀 Features

- **(lint)** add more lint checks by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;446](jdx/usage#446)
- add logo to docs site by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;442](jdx/usage#442)
- add VT323 retro terminal font and --usage branding by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;443](jdx/usage#443)
- add missing builder methods by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;444](jdx/usage#444)

##### 🐛 Bug Fixes

- use pithy LLM-generated title for GitHub releases by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;441](jdx/usage#441)
- replace unwrap calls with proper error handling in fig.rs by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;454](jdx/usage#454)
- improve error messages with more context by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;449](jdx/usage#449)
- skip powershell test if pwsh is not installed by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;457](jdx/usage#457)
- match completion prefix against unescaped names by [@&#8203;ilyagr](https://github.com/ilyagr) in [#&#8203;460](jdx/usage#460)

##### 🚜 Refactor

- simplify Spec::merge with local macros by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;451](jdx/usage#451)

##### 📚 Documentation

- add CLAUDE.md for Claude Code guidance by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;452](jdx/usage#452)
- escape generic type parameters in macro doc comments by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;453](jdx/usage#453)
- add rustdoc for public API functions by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;450](jdx/usage#450)
- add documentation to public API structs by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;455](jdx/usage#455)
- add conventional commit guidance to CLAUDE.md by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;459](jdx/usage#459)

##### ⚡ Performance

- remove unnecessary clone in set\_subcommand\_ancestors by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;448](jdx/usage#448)

##### 🧪 Testing

- add test coverage for untested modules by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;447](jdx/usage#447)

##### 🔍 Other Changes

- remove commented-out trait implementations in mount.rs by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;445](jdx/usage#445)
- make codecov checks informational by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;456](jdx/usage#456)

##### 📦️ Dependency Updates

- lock file maintenance by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;439](jdx/usage#439)

##### New Contributors

- [@&#8203;ilyagr](https://github.com/ilyagr) made their first contribution in [#&#8203;460](jdx/usage#460)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi45MC4wIiwidXBkYXRlZEluVmVyIjoiNDIuOTIuNCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90IiwiYXV0b21hdGlvbjpib3QtYXV0aG9yZWQiLCJkZXBlbmRlbmN5LXR5cGU6Om1pbm9yIl19-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants