Fix Fish completions to avoid filesystem fallback#1199
Conversation
📝 WalkthroughWalkthroughFish shell completion generation is refactored to prevent filesystem fallback for command, flag, and positional argument completions unless explicitly marked as path types. A new positional index helper function computes argument positions, the type contract adds completionType to flag definitions, command metadata is updated to mark path-related flags, and the generator emits appropriate Fish completion flags to control fallback behavior. ChangesFish Completion Fallback Prevention
🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
test/core/completions/generators/fish-generator.test.ts (1)
428-429: 💤 Low valueConsider breaking up the long assertion for maintainability.
The assertion spans the entire Fish completion condition string. While this ensures exact format, it's brittle—generator changes to whitespace, condition order, or quoting would break the test even if the semantic behavior is correct.
♻️ More maintainable alternative
Check the key components separately rather than the full string:
- expect(secondLine).toContain("complete -c openspec -n '__fish_openspec_using_subcommand workspace; and __fish_openspec_using_subcommand relink; and __fish_openspec_positional_index 1 2 --workspace'"); - expect(secondLine).not.toContain('-f'); + expect(secondLine).toContain('__fish_openspec_using_subcommand workspace'); + expect(secondLine).toContain('__fish_openspec_using_subcommand relink'); + expect(secondLine).toContain('__fish_openspec_positional_index 1 2 --workspace'); + expect(secondLine).not.toContain('-f');This preserves semantic correctness checks while being more resilient to formatting changes.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/core/completions/generators/fish-generator.test.ts` around lines 428 - 429, The long brittle assertion on secondLine should be split into multiple targeted checks: replace the single expect(secondLine).toContain(...) with separate expectations that secondLine contains the completion command prefix ("complete -c openspec -n"), contains "__fish_openspec_using_subcommand workspace", contains "__fish_openspec_using_subcommand relink", and contains "__fish_openspec_positional_index 1 2 --workspace", while keeping the existing expect(secondLine).not.toContain('-f'); this uses the secondLine variable in test/core/completions/generators/fish-generator.test.ts and makes the test resilient to formatting or ordering changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@test/core/completions/generators/fish-generator.test.ts`:
- Around line 428-429: The long brittle assertion on secondLine should be split
into multiple targeted checks: replace the single
expect(secondLine).toContain(...) with separate expectations that secondLine
contains the completion command prefix ("complete -c openspec -n"), contains
"__fish_openspec_using_subcommand workspace", contains
"__fish_openspec_using_subcommand relink", and contains
"__fish_openspec_positional_index 1 2 --workspace", while keeping the existing
expect(secondLine).not.toContain('-f'); this uses the secondLine variable in
test/core/completions/generators/fish-generator.test.ts and makes the test
resilient to formatting or ordering changes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0d28a349-8fdf-42aa-b558-1cdba32f0860
📒 Files selected for processing (6)
.changeset/fish-completion-no-file-fallback.mdsrc/core/completions/command-registry.tssrc/core/completions/generators/fish-generator.tssrc/core/completions/templates/fish-templates.tssrc/core/completions/types.tstest/core/completions/generators/fish-generator.test.ts
Fix Fish completions to avoid filesystem fallback
Summary
Fish shell completions for OpenSpec would fall back to suggesting filenames and directories unless
a completion rule explicitly suppressed it with
-f. This PR fixes the generator so that command,subcommand, flag, and positional completions never suggest filesystem entries unless the argument
is actually a path.
Problem
Fish has a default fallback behavior: if a completion rule does not explicitly opt out with
-f,Fish will suggest filenames after command-specific results (or instead of them). The OpenSpec Fish
generator was not emitting
-fanywhere, which caused:openspec <TAB>to show filesystem entries alongside command namesopenspec workspace <TAB>to mix subcommand names with filesystem entries--initiative,--title) to offer file suggestionsWhat changed
src/core/completions/types.tsAdded
completionType?: PositionalTypetoFlagDefinition. This field is optional and reuses theexisting
PositionalTypeunion. In practice only'path'is used: it signals that a flag's valueis a filesystem path and file completion should be preserved. All other
takesValueflags defaultto suppressing file completion.
src/core/completions/command-registry.tsAnnotated 8 flags with
completionType: 'path':new change --store-pathset change --store-pathworkspace open --store-pathcontext-store setup --pathinitiative create --store-pathinitiative show --store-pathinitiative list --store-pathinitiative ls --store-pathAll other
takesValueflags accept free-form strings or IDs and receive no annotation.src/core/completions/generators/fish-generator.tsUpdated generator rules:
-f-f-ftakesValueflags (nocompletionType): emit-r -ftakesValueflags (completionType: 'path'): emit-ronly, preserving file completionAdded
generateIndexedPositionalCompletionsto walkpositionals[]when a command definesmultiple positionals, generating one condition per index. The generator prefers
positionals[]over the legacy
acceptsPositional+positionalTypepath; both remain supported.Added
collectValueFlagsto gather all value-consuming flag names for a command so the positionalindex helper can skip their consumed tokens when counting.
src/core/completions/templates/fish-templates.tsAdded
__fish_openspec_positional_indextoFISH_STATIC_HELPERS.The function takes three kinds of arguments:
$argv[1](target): the zero-based positional index to match$argv[2](depth): how many command/subcommand name tokens precede the first positional(1 for top-level commands, 2 for subcommands)
$argv[3..](value_flags): long and short names of flags that consume the next tokenIt counts non-flag, non-consumed tokens in
commandline -opcand returns true whencount == target + depth. Thedepthoffset lets the same function handle bothopenspec init <TAB>(depth=1) andopenspec schema fork <TAB>(depth=2) withoutneeding separate helpers.
test/core/completions/generators/fish-generator.test.tscompletionLine()helper for targeted line-level assertions-fis present on command, subcommand, flag, and positionalcompletion lines
completionType: 'path'flag emits-rwithout-f-f-f-fschema fork: position 0 suggests schema names with-f; position 1 emits-fwith no sourceworkspace relink: position 0 emits-f; position 1 allows file completion (no-f)__fish_openspec_positional_indexhelper is present in generated outputBehavior changes
openspec <TAB>openspec workspace <TAB>openspec show --type <TAB>change spec+ filesystem entrieschange speconlyopenspec init --store-path <TAB>openspec schema fork <TAB>openspec schema fork core <TAB>openspec workspace relink name <TAB>Verification
The completion test suite covers all four shell generators. Bash, Zsh, and PowerShell generator
outputs are unchanged; their existing tests pass without modification.
Summary by CodeRabbit
New Features
Bug Fixes