fix(completions): complete files after a script arg in bash & zsh - #30387
fix(completions): complete files after a script arg in bash & zsh#30387robobun wants to merge 2 commits into
Conversation
`bun myscript.ts foo<TAB>` did nothing in either shell: the dispatch in both completion scripts only ran file completion for positions 2+ when the first word was a known subcommand (`run`, `test`, etc.). When the first word is a script path, the case fell through with no default branch, so TAB silently produced no matches. Add a `*)` fallback to both scripts that calls `_files` / `compgen -f` for positional args after the script, mirroring `bun run`'s behaviour. Fixes #30386.
|
Updated 1:11 AM PT - May 8th, 2026
❌ @robobun, your commit 65f5ec3 has 3 failures in
🧪 To try this PR locally: bunx bun-pr 30387That installs a local version of the PR into your bun-30387 --bun |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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.
Inline comments:
In `@test/cli/completions.test.ts`:
- Around line 125-128: The thrown error in zshCompleteLine currently omits
stderr making failures hard to debug; update zshCompleteLine to capture both
stdout and stderr like bashComplete does: when awaiting
Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]) and exitCode
!== 0, include the captured stderr (and optionally stdout) in the thrown Error
message so the error contains the zsh driver's stderr output for diagnosis.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7abd9a34-48cb-4078-b805-59d583fa5837
📒 Files selected for processing (3)
completions/bun.bashcompletions/bun.zshtest/cli/completions.test.ts
- Replace post-TAB `sleep 0.5` + drain with a poll-until-seen loop that breaks on the expected substring or a BEL byte, with a 4s upper bound. Faster in the common case and robust under CI load. - Drop bogus pattern argument (`0.05` / `0.2`) from `zpty -r -t` calls — those aren't per-read timeouts. Add `sleep 0.02` to the wait_for else-branch so it doesn't busy-spin. - Switch `describe` to `describe.concurrent` for all three blocks. Every test spawns its own shell into its own tempDir — no shared state, and the concurrency roughly halves total test time. - Use `compinit -D` (skip writing `~/.zcompdump`) so concurrent inner zsh processes don't race on the dump file. - Strip ANSI colour escape codes from the accumulated pty buffer BEFORE matching — zsh's list-colors can interleave `\x1b[…m` between completion chars, defeating a naive substring match. - Include stderr in the zsh-driver error message for easier diagnosis on failure (matches the bash driver).
There was a problem hiding this comment.
LGTM — the completion-script change is a minimal, low-risk fallback, and all the test-harness feedback from my earlier review (concurrent describes, compinit -D, poll-until-seen instead of sleep, corrected zpty -r args, stderr in errors) is addressed in 65f5ec3.
Extended reasoning...
Overview
This PR fixes #30386 by adding a default fallback branch to both completions/bun.bash and completions/bun.zsh so that bun <script> <arg><TAB> completes files. The production change is ~15 lines of shell across two files: a (( COMP_CWORD >= 2 )) && compgen -f block in the bash *) arm, and a new *) arm calling _files in the zsh case $line[1] dispatch — both mirroring what the existing run branch already does. The bulk of the diff (~265 lines) is a new test file, test/cli/completions.test.ts, that drives bash via COMP_WORDS/COMPREPLY and zsh via zpty, plus bash -n/zsh -n syntax checks.
Security risks
None. Shell tab-completion scripts are sourced into the user's interactive shell and only affect what candidates appear when the user presses TAB; they do not execute the completed command. The added code calls standard completion builtins (compgen -f, _files) with the user's own current word — no new external input, no eval, no privilege boundary. The test file spawns local bash/zsh subprocesses in temp dirs with no network or credential access.
Level of scrutiny
Low for the production change: completion scripts are pure UX, the worst-case failure mode is "TAB suggests the wrong things" or "TAB still does nothing," and the new branches follow the exact pattern already used by _bun_run_completion's other) state. Moderate for the new zpty-based test harness, which is the most intricate part — but it has already been through one review round and the author addressed every point.
Other factors
I previously left three inline comments on this PR. Reviewing the post-65f5ec3 diff against each:
- 🔴
sleep 0.5+ blind drain → replaced with a poll-until-seen loop that breaks on the expected substring or BEL, with ANSI stripping and a 4s ceiling. Addressed (thread marked resolved). - 🟡 bogus
0.05/0.2positional args tozpty -r -t→ removed;wait_for()and the post-TAB loop now useelse sleep 0.02for the poll interval, and the drain loop drops the trailing arg. Addressed (thread not marked resolved on GitHub, but the code change is in). - 🟡
describe→describe.concurrent+compinit -D→ all three describe blocks are now.concurrent, and the inner zsh usescompinit -Dto avoid~/.zcompdumpraces. Addressed (thread not marked resolved on GitHub, but the code change is in).
CodeRabbit's stderr-in-error nit is also addressed. The bug-hunting system found no issues. No CODEOWNERS cover completions/ or test/cli/. Given the trivial production change and the fully-addressed test feedback, this is safe to approve without further human review.
|
Superseded by #36629, which carries the same bash and zsh |
Fixes #30386.
Repro
Cause
Both
completions/bun.zshandcompletions/bun.bashdispatch on the firstword after
bun. When it's a known subcommand (run,test,add, …) theper-subcommand branch handles positions 2+ appropriately — the
runbranch,for example, explicitly calls
_files. When the first word is a scriptpath (
bun myscript.ts …), no branch matches and the case falls throughwith no default, so TAB at positions 2+ silently produces no matches.
completions/bun.zsh, line 767completions/bun.bash, line 164Fix
Add a default branch to both scripts that completes files for positions 2+
when the first word isn't a recognised subcommand. Mirrors what
_bun_run_completion'sother)state already does:bun.zsh: new*)arm of the outercase $line[1]calls_files.bun.bash: in the*)arm ofcase ${COMP_WORDS[1]}, whenCOMP_CWORD >= 2also runcompgen -f -- "${cur_word}".Total diff: 15 lines of shell.
Verification
test/cli/completions.test.ts(new — there was no existing test file forshell completions) covers both shells:
_bun_completionswith a simulated
COMP_WORDS/COMP_CWORD, inspectCOMPREPLY:bun myscript.ts foo<TAB>→["foo-bar.txt", "foo-file.txt"](was:[])zptyto drive an interactive zsh thatsources the completion, send
<line><TAB>, read the PTY buffer:bun myscript.ts foo<TAB>auto-completes tofoo-(was: BEL bell,no change)
bun run myscript.ts foo<TAB>still auto-completes (regression guard)bash -n/zsh -non both scripts to catch futuretypos at source-load time.
Without the patch (on
bun bd): 3 tests fail —[bash] bun <script> <arg>,[bash] bun <script> <arg1> <arg2>,[zsh] bun <script> <arg>. With thepatch: all 7 pass.