mirror of
https://github.com/max-sixty/worktrunk.git
synced 2026-09-14 20:00:38 +08:00
codex/remove-codex-cloud-specific-tests
100 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
96c6c846f7 |
fix(shell): register completions under the --cmd name, not clap's (#3817)
## Problem
`wt config shell init <shell> --cmd <name>` renames the shell wrapper
and its lazy completion loader, but the registration that loader evals
comes from clap, which derives every identifier in it from its own
compile-time `Command` name (`wt`) — not from `argv[0]` and not from
`--cmd`. The two halves never agreed:
```console
$ wt config shell init zsh --cmd wot | grep _clap
if ! (( $+functions[_clap_dynamic_completer_wot] )); then
_clap_dynamic_completer_wot "$@"
$ COMPLETE=zsh wt | grep -oE '_clap_dynamic_completer_[a-z_]*' | sort -u
_clap_dynamic_completer_wt
```
Nothing completed, and because the guard never became true the
completion script was regenerated and re-evaluated on *every* TAB. Same
shape in bash (`_clap_complete_*`); PowerShell emitted
`Register-ArgumentCompleter -Native -CommandName wt`, so the `--cmd`
name was never registered at all. The documented `--cmd=git-wt` case
(the Windows Terminal conflict) was broken too — including for a binary
genuinely installed under that name, since clap's name comes from the
declaration rather than `argv[0]`.
There is a second, sharper edge: zsh's registration ends with `compdef
<completer> <cmd>`, so the first TAB on `wot` also bound worktrunk's
completer to plain `wt` — handing completions to the *other* `wt` that
`--cmd` exists to step around.
fish and nushell were unaffected. Both register a completer that shells
out to the binary rather than depending on a clap-emitted identifier, so
the reporter's "unverified" row for fish is a pass.
## Solution
The bash, zsh, and PowerShell loaders now pass the name they bind in
`WORKTRUNK_COMPLETE_NAME`, and `registration_name()` in
`src/completion.rs` emits the registration under that name (validated
through the same `validate_shell_command_name` guard `--cmd` uses, since
the value lands verbatim in generated shell code). The fallback is
`binary_name()`, which covers a binary installed as `git-wt` and invoked
directly. The templates apply clap's own `-` → `_` escaping to the
function they call, so `--cmd git-wt` guards on `_clap_complete_git_wt`
rather than the invalid `_clap_complete_git-wt`.
That fixes all four shells and the stray `compdef` in one place, rather
than pinning the templates to clap's internal naming:
```console
$ WORKTRUNK_COMPLETE_NAME=wot COMPLETE=zsh wt | grep -oE '_clap_dynamic_completer_[a-z_]*|compdef .*' | sort -u
_clap_dynamic_completer_wot
compdef _clap_dynamic_completer_wot wot
```
## Testing
Two reproduction tests in `tests/integration_tests/completion.rs`, both
failing before the change:
- `test_init_custom_cmd_defines_clap_completer_in_bash` drives the whole
chain through a real bash — generate the init script with `--cmd`, call
the loader it defines, then assert clap's completer function exists
afterwards. Printed `MISSING` before, `DEFINED` after. Cases for `wot`
and `git-wt`.
- `test_completion_registration_uses_shell_integration_cmd_name` covers
zsh and PowerShell, which CI can't drive: the identifier the init script
references must be the one the registration defines, and the `compdef` /
`-CommandName` target must be the `--cmd` name.
`cargo test --lib --bins` and `cargo test --test integration` are
otherwise green (one unrelated failure locally,
`test_copy_ignored_preserves_file_executable_permissions`, from this
sandbox's `umask 0002`), and `cargo clippy --all-targets --all-features`
/ `cargo fmt --check` are clean.
---
Closes #3816 — automated triage
---------
Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
|
||
|
|
bdd7113c95 | fix(shell): catch a failing --execute body in the nushell wrapper (#3734) | ||
|
|
78010166bd |
fix(shell): bypass rm aliases in the nushell wrapper's cleanup (#3732)
## Problem The nushell wrapper's temp-file cleanup called a bare `rm -f`. Nushell resolves aliases at parse time, and `config.nu` runs before the `$nu.vendor-autoload-dirs` file the wrapper installs into — so a user's `alias rm = ...` is already in scope when the wrapper's `def` is parsed, and intercepts the cleanup. #3714 fixed the same shadowing in the bash and zsh wrappers with `command rm`; nushell has no `command` builtin, so it was left out. Two failures, both verified end-to-end against nushell 0.114.1 (the version CI pins) driving the real rendered wrapper: | `alias rm =` | before | after | |---|---|---| | *(none)* | exit 0, stdout returned, 0 temp files left | unchanged | | `^false` | exit 1, **stdout empty**, **3 temp files leaked** | exit 0, stdout returned, 0 left | | `^echo TRASHED` | `TRASHED -f /tmp/...` lines **injected into stdout**, **3 temp files leaked** | exit 0, stdout returned, 0 left | The `^false` row is the serious one. Cleanup sits between `let output = (open $stdout_file --raw)` and the function's return, and nushell 0.98+ raises `ShellError` on a non-zero external exit — so an `rm` alias that fails, prompts, or isn't installed on that machine aborts the wrapper before it returns, and the command's stdout is silently discarded. Only stdout is affected; stderr has already streamed to the terminal, which is why the symptom hides on `wt switch` (its output is on stderr) and shows on `wt config show`. ## Solution Consolidate the two cleanup calls into one, after the last read of any temp file, and branch at runtime on `$nu.os-info.family`: ```nu if $nu.os-info.family == "windows" { try { rm -f $cd_file $exec_file $stdout_file } } else { try { ^rm -f $cd_file $exec_file $stdout_file } } ``` `^rm` bypasses alias expansion entirely — the Unix fix is complete, not partial. Windows keeps the builtin because `^rm` is external-only and Windows has no external `rm`; `try` covers both branches so cleanup can never abort the wrapper again. Branching at *runtime* rather than forking the template by build platform is what keeps this cheap: `wt config shell init nu` renders one text on every platform, so there's a single `init_nu` snapshot and no platform-specific rendering to maintain. <details><summary>Options considered and rejected</summary> - **`` `rm` `` (backtick-quoted)** — bypasses the alias, but `` `rm` `` with `PATH` emptied reports ``Command `rm` not found``, and `` `rm` `` with no args prints `/usr/bin/rm: missing operand`. It resolves to the *external*, so it's just `^rm` spelled differently — same Windows gap, no benefit. - **`hide rm`** — works inside the `def`, but `hide` is a parse-time keyword that leaks into the enclosing scope. For an autoloaded file that scope is the user's session, so installing shell integration would silently unbind their own `rm` alias. Same leak inside a `do {}` closure. Worse than the bug. - **`try` alone, no `^rm`** — cross-platform and kills the abort, but leaves the alias running: a `trash` alias still trashes worktrunk's temp files on every invocation, and an `rm -i`-style alias still prompts. - **Forking the template by build platform** — same end state on each platform, at the cost of platform-specific `init_nu` snapshots. The runtime branch gets there without them. </details> ## Testing `test_nu_wrapper_cleanup_survives_rm_alias` in `tests/integration_tests/shell_wrapper.rs` runs the real wrapper through a PTY with `alias rm = ^false` declared ahead of it, against a dedicated `TMPDIR`, and asserts both symptoms: the wrapper's stdout comes back non-empty, and the temp dir is empty afterwards. It fails on the current template (marker absent — the wrapper aborted) and passes with the fix. Also run locally: `cargo test --lib --bins`, and the full `shell_wrapper` + `config_show` + `test_docs_are_in_sync` integration set with `--features shell-integration-tests` (201 passed). ## Not fixed here A user alias to a *custom command or builtin* whose signature rejects `-f` — e.g. `alias rm = print "…"` — makes the whole wrapper file fail to parse, leaving `wt` undefined rather than merely broken. That's pre-existing (today's template has two bare `rm -f` calls) and survives this change, because the Windows branch is still parsed on Unix even though it never runs. Eliminating it means emitting no bare `rm` at all on Unix, which is the template fork above. Flagged on #3730 rather than bundled in here. --- Closes #3730 — automated triage Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com> |
||
|
|
e949ed5fda | fix(shell): use command rm in wrapper cleanup to bypass rm aliases (#3714) | ||
|
|
1eded27943 |
Simplify forge, shell integration, and removal internals (#3662)
This consolidates cross-cutting models that had accumulated parallel representations, while preserving the CLI and config interfaces. ## What changed - Forge identity now flows through one `ForgeKind`, with boundary-safe network-host classification shared by CI, remote references, and structured repository metadata. Branded SSH aliases such as `github-personal` remain outside provider dispatch and receive an actionable `forge.platform` diagnostic when forge data is requested. - Worktree removal now uses one owned target type and rechecks uncached worktree topology immediately before compare-and-swap branch deletion, retaining branches that gained a live or locked checkout. - Shell integration no longer implements the retired single-file directive writer. Stale wrappers receive repair guidance, execution fails closed, and child processes cannot inherit the retired sourceable-file capability. - Zsh and Git-version probes are shared, while dead mocks, redundant dependency edges, serializer detours, pass-through types, and duplicate tests are removed. The removal guard deliberately distinguishes live, stale-prunable, and locked registrations. The detached cleanup path performs the same record-aware check before deleting a branch ref. ## Testing `cargo run -- hook pre-merge --yes` passed after merging current `origin/main`: 4,489 tests, Clippy, formatting, lockfile checks, docs, doctests, and snapshot review. > _This was written by Claude Code on behalf of max_. |
||
|
|
eba35d039c | fix(shell): stop PowerShell wrapper leaking a stray exit-code line to stdout (#3425) | ||
|
|
c2b7ab683e |
fix(shell): guard fish lazy-load wrapper against completion-mode recursion (#3250)
Follow-up to #3241, requested in #3240. #3241 made the completion files **wt itself writes** resolve the binary, so they no longer re-enter the fish lazy-load stub. But the stub (`functions/wt.fish`) is still unguarded, leaving one narrow residual case: a **stale third-party completion** that calls the bare `wt` command with `COMPLETE` set — e.g. an old Homebrew `vendor_completions.d/wt.fish` left on disk from before an upgrade — re-enters the stub and recurses to fish's call-stack limit until the package is rebuilt. This adds the same `COMPLETE` short-circuit that bash and zsh already use, so the stub delegates straight to the binary in completion mode regardless of which completion file is active: ```fish function wt if set -q COMPLETE command wt $argv # bypass the stub, let the binary emit completions return end command wt config shell init fish | source ... end ``` This makes fish immune to stale third-party completions, matching bash/zsh. ## Changes - `templates/fish_wrapper.fish` — add the `COMPLETE` guard to the lazy-load stub. - `src/shell/mod.rs` — `test_fish_wrapper_guards_completion_mode` regression test (#3240). - Regenerated the `configure_shell_fish_dry_run` snapshot. Closes #3240. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: worktrunk-bot <worktrunk-bot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
03dbf5f70e |
fix: use builtin cd in fish shell integration (#3160)
## Problem `wt switch <branch>` reported a successful switch but then failed to change directory under fish when the [`kidonng/zoxide.fish`](https://github.com/kidonng/zoxide.fish) plugin is active, printing `zoxide: no match found` / `Error: Directory not found` even though the worktree exists (#3159). The fish integration changed directory with a bare `cd -- "$target"`. `zoxide.fish` replaces `cd` with a zoxide query function. With `cd -- "$target"` it receives two arguments (`--` and the path), so its single-directory fast path (`argc -eq 1`) is skipped and it falls through to fuzzy-query mode, which finds no match for `-- /path/to/worktree`. The bash and zsh wrappers were already immune because they use `builtin cd`; only fish used a bare `cd`. ## Solution Use `builtin cd -- "$target"` in `templates/fish.fish`, bypassing any user `cd` override (verified: in fish `cd` is a regular function that `builtin cd` skips). The `--` is retained for consistency with the bash/zsh wrappers; the target is an absolute path written by the binary, so it can never be flag-injected. ## Testing - Added `test_fish_init_uses_builtin_cd` in `src/shell/mod.rs`, which fails on the old template (`cd -- "$target"`) and passes after the fix. - Updated the fish init snapshots (`src/shell/snapshots/...init_fish.snap`, `tests/snapshots/...init_fish.snap`). - Verified fish `3.7.0` behavior directly: `cd` is a function, `builtin cd` and `builtin cd --` both succeed, and `builtin cd` bypasses a user-defined `cd` function (the simulated override was not invoked). - `cargo test --test integration test_docs_are_in_sync` passes. --- Closes #3159 — automated triage Co-authored-by: worktrunk-bot <worktrunk-bot@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> |
||
|
|
ad43df7656 | feat(completions): ship dynamic registration for package installs (#3105) | ||
|
|
62a7a6c0a5 |
fix(shell): shell-correct (PowerShell + fish) escaping for the --execute payload (#2843)
## What `wt switch -x <cmd> -- <args>` builds the `--execute` payload as a single shell-escaped string. When shell integration is active that string is written to the EXEC directive file and evaluated by the user's shell wrapper. wt escaped it with POSIX single-quote escaping (`shell_escape::unix::escape`) unconditionally — but two wrappers do not have POSIX single-quote semantics: - **PowerShell** evaluates the EXEC file with `Invoke-Expression`; the POSIX `'\''` quoting idiom is invalid PowerShell, which wants embedded quotes doubled (`''`). This completes the PowerShell-escaping follow-up that #2815 explicitly deferred. - **fish** evaluates it with `eval`; inside `'…'` fish treats `\` as an escape character (`\\`→`\`, `\'`→`'`), unlike POSIX where `\` is literal. A POSIX-escaped payload containing a backslash is mis-evaluated under fish — `a\\b` silently loses a backslash, and a trailing backslash makes fish abort the whole `eval` with a quote-balance parse error. ## Approach Escaping now keys on the active directive shell. A `ShellEscapeMode` enum (`Literal` / `Posix` / `PowerShell` / `Fish`) replaces the old `shell_escape: bool` parameter on `expand_template`; `directive_shell_escape_mode()` reads the `WORKTRUNK_SHELL` env var (the PowerShell wrapper already exported it; the fish wrapper now does too). Only the `--execute` payload is shell-aware — hooks and aliases always run through `Cmd::shell` (`sh` / Git Bash) and stay POSIX; filesystem-path templates stay `Literal`. ## For reviewers - `src/shell_exec.rs` — the new escaping section: `ShellEscapeMode`, `directive_shell_escape_mode()`, `powershell_escape()`, `fish_escape()`, `shell_escape_for()`. - `src/output/global.rs` — `escape_legacy_cd` consolidated onto the same shell decision. - `src/commands/worktree/switch.rs` — the `--execute` block escapes via the active-shell escaper. - `templates/fish.fish` — exports `WORKTRUNK_SHELL=fish` so wt can identify the wrapper. - The diff is large (~+1250/−210) but the substantive change is ~150 lines; the rest is the mechanical `bool`→enum migration across `expand_template` call sites plus `cargo fmt` reflow of the now-longer calls. ## Non-breaking For every non-PowerShell, non-fish user, behavior is byte-identical: `WORKTRUNK_SHELL` absent ⇒ `Posix` ⇒ the previous `shell_escape::unix::escape`. The pre-existing POSIX snapshots are unchanged. ## Testing `cargo run -- hook pre-merge --yes` clean (3790 tests). The fish escaper was round-tripped through the actual fish binary (4.7.1) — adversarial inputs (consecutive, leading, and trailing backslashes; embedded quotes; `$(…)`; backticks; newlines; empty) all deliver byte-exact, and the original bug reproduces without the fix. New integration tests cover both the new-protocol EXEC path and the legacy `cd` directive under `WORKTRUNK_SHELL=powershell` and `=fish`; unit tests cover `powershell_escape` and `fish_escape` directly. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
3ddfc84f58 | fix(shell): use builtin cd to bypass cd aliases (e.g. zoxide) (#2644) | ||
|
|
fdc6df61b9 |
fix(nushell): switch wrapper to @complete attribute on untyped rest (#2458)
Per fdncred's recommendation in nushell/nushell#18128, replaces the parameter-level `[...args: string@\"nu-complete wt\"]` with a function-level `@complete` attribute on an untyped `[...args]` rest. The completer signature moves from `[context: string]` (with manual `split row \" \"` reconstruction) to `[spans: list<string>]`, which nushell pre-tokenizes — net deletion of seven lines of fragile token reassembly. Untyped rest is the form nushell routes through its normal external-argument handling, so once nushell/nushell#18131 ships in stable nu the wrapper will automatically benefit from `--flag=\"value\"` quote stripping and `~` expansion without further changes. Until then `--flag=\"value\"` still arrives at the binary with literal quotes — a pre-existing bug, not a regression introduced here. Supersedes #2437 (the body-level regex strip workaround). ## Test plan - [x] `cargo test --test integration --features shell-integration-tests` — 1717 passed (including all four nu wrapper cases) - [x] `pre-commit run --all-files` — clean - [x] Smoke-tested the rendered template parses cleanly under nu 0.112.1 - [ ] Hand-verify subcommand completion at trailing space (e.g. `wt switch <TAB>`) in an interactive nu session — couldn't drive reedline via PTY in test, but fdncred's example in nushell/nushell#18128 implies `spans` is populated at the cursor position Ref nushell/nushell#18128, nushell/nushell#18131 Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
60f571d279 |
Remove global backslash snapshot filter + fix nushell multi-line exec (#2134)
The test snapshot framework had a global `\\` → `/` filter (`tests/common/mod.rs`) intended to normalize Windows paths before path-specific filters ran. It silently corrupted intentional backslashes in output: - **JSON-encoded ANSI escapes** (`\u001b` → `/u001b`) in `wt list --format=json` and diff snapshots. The snapshots had been capturing corrupted JSON for a long time. - **Shell line continuations** (`command \` → `command /`) in `wt config shell init` snapshots, masking template regressions. Worktrunk emits forward-slash paths via `path_slash` everywhere, so the blanket normalization wasn't carrying its weight. Dropped it; a follow-up comment points future contributors at `add_repo_and_worktree_path_filters` if any test ever produces a raw Windows path. 14 JSON/diff snapshots and 3 init snapshots regenerated with the real output (visible in the diff: `/u001b` → `\u001b`, `cmd /` → `cmd \`). While here: nushell wrapper executed the exec directive file line-by-line (`^sh -c $directive` in a loop), so multi-line `--execute` payloads ran as separate shell sessions — variables didn't persist, `cd` didn't affect later lines, etc. Switched to a single `^sh -c $script` invocation matching bash/zsh/fish `source` semantics. > _This was written by Claude Code on behalf of Maximilian_ --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
b174658e29 |
Split directive file into CD (raw path) and EXEC (shell) files (#2118)
The shell wrapper previously used a single `WORKTRUNK_DIRECTIVE_FILE` where wt wrote shell commands (`cd '/path'`, arbitrary `--execute` payloads). This meant the cd path went through shell parsing — any content wt wrote was sourced as shell. This splits the protocol into two files with different trust levels: - **`WORKTRUNK_DIRECTIVE_CD_FILE`** — raw path, read with `cd -- "$(< file)"`. No shell parsing, no escaping, no injection surface. Safe to pass through to alias/hook child processes. - **`WORKTRUNK_DIRECTIVE_EXEC_FILE`** — arbitrary shell (from `--execute`), sourced by the wrapper. Scrubbed from alias/hook child environments so hook bodies cannot inject shell into the parent session. When a nested `wt` inside an alias body tries `--execute` without the EXEC file, the command is dropped with a warning linking to #2101 for user feedback. The old `WORKTRUNK_DIRECTIVE_FILE` is silently honored for one release (users who upgrade wt without restarting their shell). Bash, zsh, fish, and PowerShell self-update on restart; nushell requires `wt config shell install`. Closes #2101 > _This was written by Claude Code on behalf of @max-sixty_ --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
fd00dbd8bf |
fix(fish): prevent getcwd error after worktree removal in Zellij (#1787)
Replace `cat` (external subprocess) with `string collect` (fish builtin) when reading the directive file in the fish shell wrapper. After worktree removal via the fast path, the shell's CWD inode follows the `rename()` into `.git/wt/trash/`. Spawning any subprocess from this CWD can trigger `shell-init: error retrieving current directory` — on macOS, `/bin/sh` calls `getcwd()` during initialization, and in terminal multiplexers like Zellij the error is visible to the user. Using a fish builtin avoids subprocess spawning entirely. The `sleep 1` delay in the background removal command remains as defense in depth, but the primary fix is eliminating the subprocess. bash/zsh wrappers already use `source` (a builtin) and are unaffected. > _This was written by Claude Code on behalf of @max-sixty_ Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
6093b61241 | fix(nushell): use source in Home Manager module and export template defs (#1476) | ||
|
|
cbd5e4da50 |
feat: add nushell tab completions (#1220)
## Summary
- Add `nu-complete wt` completer function to the nushell init template,
wiring it to the wrapper's rest parameter via `@"nu-complete wt"`
- The completer calls the binary with `COMPLETE=nu` and parses
tab-separated output into nushell's `{value, description}` record format
- Add `"nu"` to multi-shell completion test loops (help, version,
single-dash, deprecated flags) and a dedicated subcommand snapshot test
Thanks to @omerxx for reporting in #1215.
Closes #1215
## Limitations
Nushell's completion engine bypasses custom completers when the current
token starts with `-`, so flag completions (e.g. `wt switch --<TAB>`)
don't appear. Subcommand and value completions work correctly. This is a
nushell engine limitation (nushell/nushell#14504), not something we can
fix in our template.
## Test plan
- [x] Unit tests pass (`cargo test --lib --bins`) — snapshot updated
- [x] Integration tests pass (`cargo test --test integration`) — 1121
tests
- [x] Shell integration test (`cargo test --test integration --features
shell-integration-tests -- test_nushell_completion_subcommands`)
- [x] Lints pass (`pre-commit run --all-files`)
- [x] Manual verification in nushell 0.110.0: `wt <TAB>` shows
subcommands, `wt switch <TAB>` shows branches with descriptions
> _This was written by Claude Code on behalf of @max-sixty_
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
|
||
|
|
eecb5c7e1e |
fix(nushell): enable stdout piping for list while preserving directives (#1081)
## Summary - Split the nushell wrapper into two code paths: `list` gets direct passthrough (binary as last expression, stdout flows through pipes), everything else captures stdout to a temp file and processes directives before returning output - Fixes `wt list --format json | from json` which previously failed because nushell's typed pipeline model requires the function's last expression to be the return value - No tradeoffs — the two command sets (streaming vs directives) are disjoint, so each path is optimal for its commands ## Background Nushell's pipeline model differs from POSIX shells: a function's "output" is its return value (last expression), not bytes written to fd1. When an external command isn't the last expression, stdout goes to the terminal as a side effect but doesn't flow through `|`. This means post-processing (directive handling, exit code capture) after the binary call prevents stdout from reaching the pipeline. The wrapper comment documents the nushell limitation with references to nushell/nushell#12643. ## Test plan - [x] All 530 unit tests pass - [x] All 1052 integration tests pass - [x] All lints pass (`pre-commit run --all-files`) - [ ] Manual: `wt list --format json | from json` works in nushell - [ ] Manual: `wt list` shows progressive table rendering in nushell - [ ] Manual: `wt switch` still changes directory in nushell Closes #1062 > _This was written by Claude Code on behalf of @max-sixty_ --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
516f90bac4 |
fix(shell): PowerShell wrapper swallows -D flag as -Debug (#1057)
* fix(shell): PowerShell wrapper swallows -D flag as -Debug (#885) The `[Parameter(ValueFromRemainingArguments)]` attribute promoted the wrapper to an "advanced function", which adds common parameters like -Debug and -Verbose. PowerShell then consumed `-D` as `-Debug` instead of passing it to wt.exe — so `wt remove -D` silently lost the flag. Replace with `$args` (automatic variable for simple functions) which passes all arguments through unchanged. Co-Authored-By: Claude <noreply@anthropic.com> * fix(test): use .ps1 mock for cross-platform PowerShell test The shell script mock (#!/bin/sh) doesn't work on Windows. Use a .ps1 script instead — pwsh can invoke it directly with &, and pwsh is already required for this test. Co-Authored-By: Claude <noreply@anthropic.com> * style: apply cargo fmt to PowerShell test Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
5a10dcc788 |
fix(shell): harden nushell wrapper and improve diagnostics (#1059)
* fix(shell): harden nushell wrapper and improve diagnostics
- Move LAST_EXIT_CODE capture inside do{} block so it reflects the
actual command exit code, not a subsequent operation
- Wrap directive processing in try/catch to ensure temp file cleanup
on error
- Include nushell vendor autoload paths in scan_for_detection_details
so `wt config show` reports nushell integration status
- Add "nu" to the supported shells hint shown on unsupported shells
- Fix detection tests to use actual nushell config line patterns
- Document why non-cd directives delegate to sh -c
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(shell): remove try/catch from nushell directive cleanup
Drop error-path cleanup for the temp directive file. On error, the file
persists in /tmp as a useful debugging artifact (the OS cleans it up).
This matches bash and fish which already use a single rm on the happy
path with no error wrapping.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
|
||
|
|
c7128ce11b | Add nushell support (#964) | ||
|
|
9394261ad4 |
fix(fish): use env for inline variable assignment in shell wrapper (#1000)
* fix(fish): use `env` for inline variable assignment in shell wrapper The fish shell wrapper used `VAR=value command` syntax which requires fish 3.1+. Use `env VAR=value command` which works on all fish versions. Closes #999 Co-Authored-By: Claude <noreply@anthropic.com> * fix: drop `command` from env invocation in fish wrapper `env` can't invoke fish builtins like `command`. Since $WORKTRUNK_BIN is already an absolute path (from `type -P`), we can invoke it directly. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
3d69cec1a7 |
fix(docs): correct broken worktrunk.dev URLs in templates (#882)
- fish_wrapper.fish: /docs/shell-integration → /config/#shell-integration - config.example.toml: /config.md#project-configuration/ → /config/#project-configuration - Remove worktrunk.dev from lychee exclusions so future broken links are caught Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
a081f29972 |
fix(powershell): use WORKTRUNK_BIN for test isolation + more Windows tests (#674)
* test: add cross-platform PTY infrastructure for Windows shell tests
Make shell integration tests cross-platform using portable_pty's ConPTY
support on Windows.
Changes:
- tests/common/mod.rs: Remove Unix-only gate from shell module
- tests/common/shell.rs: Add Windows env vars, PowerShell -Command flag,
fix PATH separator for PowerShell
- tests/integration_tests/shell_wrapper.rs: Add PowerShell support to
build_shell_script and exec_in_pty_interactive, add Windows-only
PowerShell test cases
The Windows tests are gated with #[cfg(windows)] and will run when CI
has Windows runners with PowerShell available.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: gate remaining Unix-only shell tests with #[cfg(unix)]
Three more tests use `shell_command` which is Unix-only:
- test_zsh_completion_produces_correct_output
- test_wrapper_help_redirect_captures_all_output
- test_wrapper_help_interactive_uses_pager
These tests require zsh/bash/fish which aren't available on Windows.
The Windows PowerShell tests at the end of the file remain ungated.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: gate all Unix shell tests with #[cfg(unix)]
Comprehensive update to gate all tests that use bash/zsh/fish shells
with #[cfg(unix)] to prevent them from running on Windows CI.
Tests gated:
- All parameterized shell tests (bash/zsh/fish cases)
- Bash-specific tests (completions, job control, shell integration)
- Zsh-specific tests (wrapper function, job control)
- Fish-specific tests (completions, multiline commands)
- README example tests that use Unix shells
Windows PowerShell tests at the end of the file remain active on
Windows via their existing #[cfg(windows)] attributes.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): gate Unix-only imports and statics for Windows CI
When all Unix shell tests are gated with #[cfg(unix)], the imports and
static variables they use become unused on Windows, causing clippy errors.
Add #[cfg(unix)] to:
- Imports: canonicalize, wait_for_file_content, assert_snapshot, fs,
PathBuf, LazyLock, shell
- Statics: TMPDIR_REGEX, TMPDIR_PLACEHOLDER_COLLAPSE_REGEX, WORKSPACE_REGEX,
COMMIT_HASH_REGEX, JOB_CONTROL_REGEX
- Methods: assert_no_job_control_messages, normalized
- Function: generate_completions
Co-Authored-By: Claude <noreply@anthropic.com>
* test(windows): temporarily ignore PowerShell PTY tests
PowerShell PTY tests timeout in CI (60+ seconds). The issue is likely
that Get-Command finds Windows Terminal's wt.exe instead of the test
binary, causing the completion setup to hang.
Mark tests as ignored pending investigation. The test infrastructure
and cross-platform PTY support remain in place.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): gate assert_success method for Windows CI
The assert_success() method (added in #668) is only used by Unix shell
tests. Gate it with #[cfg(unix)] to fix Windows clippy dead_code error.
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(tests): organize shell tests by platform
- Group Unix-only imports in single #[cfg(unix)] block
- Move Windows tests into `mod windows_tests` with single #[cfg(windows)]
- Add documentation explaining test organization by platform
- Remove individual #[cfg(windows)] from each Windows test
This makes it clearer which tests run on which platform and reduces
the number of scattered cfg attributes.
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(tests): organize shell_wrapper tests by platform with module-level gating
- Replace 46 individual #[cfg(unix)] annotations with single module-level gate
- Restructure from nested `mod tests { mod windows_tests }` to sibling modules:
- `#[cfg(unix)] mod unix_tests` - 47 bash/zsh/fish tests
- `#[cfg(windows)] mod windows_tests` - 4 PowerShell tests
- Rename 30 snapshot files to match new module path (__tests__ → __unix_tests__)
This makes platform organization explicit at the module level rather than
scattered across individual test functions.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(powershell): use WORKTRUNK_BIN env var for test isolation
The PowerShell template was ignoring WORKTRUNK_BIN and always using
Get-Command to find wt. This caused test timeouts on Windows CI when
Windows Terminal's wt.exe was found first.
Now checks $env:WORKTRUNK_BIN first (like bash/zsh/fish templates do),
falling back to Get-Command only when not set.
Also re-enables the 4 PowerShell PTY tests that were marked #[ignore].
Co-Authored-By: Claude <noreply@anthropic.com>
* test(windows): add 8 more PowerShell integration tests
New tests:
- test_powershell_execute_exit_code_propagation - verifies exit codes
- test_powershell_branch_with_slashes - Windows path handling
- test_powershell_branch_with_dashes_underscores - branch name variants
- test_powershell_wrapper_function_registered - wrapper function check
- test_powershell_completion_registered - completion setup
- test_powershell_step_for_each - multi-worktree operations
- test_powershell_help_output - help text rendering
- test_powershell_worktrunk_bin_env - env var preservation
Total Windows tests: 12 (up from 4)
Co-Authored-By: Claude <noreply@anthropic.com>
* test(windows): add 6 more PowerShell tests
New tests:
- test_powershell_merge - merge operations
- test_powershell_switch_with_execute - execute flag with PowerShell command
- test_powershell_switch_existing - switch without --create
- test_powershell_list_json - JSON output format
- test_powershell_config_show - config diagnostics
- test_powershell_version - version output
Total Windows tests: 18 (42% of Unix test count)
Co-Authored-By: Claude <noreply@anthropic.com>
* style: cargo fmt
* test(windows): add 12 more PowerShell tests to reach 70% coverage
New tests:
- test_powershell_shell_integration_hint_suppressed
- test_powershell_select_basic
- test_powershell_switch_between_worktrees
- test_powershell_long_branch_name
- test_powershell_remove_by_name
- test_powershell_list_verbose
- test_powershell_config_shell_init
- test_powershell_switch_nonexistent_branch
- test_powershell_step_next
- test_powershell_step_prev
- test_powershell_special_branch_name
- test_powershell_hook_show
Total Windows tests: 30 (70% of 43 Unix tests)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: update PowerShell init snapshot to match template changes
Co-Authored-By: Claude <noreply@anthropic.com>
* test(windows): mark PowerShell tests as ignored pending PTY investigation
All 30 PowerShell PTY tests timeout in Windows CI (~60s each). Investigation:
What was fixed:
- PowerShell template now uses WORKTRUNK_BIN env var (like bash/zsh/fish)
- This was needed because Windows Terminal's wt.exe was being found first
What still doesn't work:
- Tests still timeout, suggesting a deeper PTY + PowerShell issue
- Likely causes: ConPTY implementation, profile loading, env isolation
The test infrastructure and 30 tests are in place for when the issue is resolved.
Enable by removing #[ignore] attributes in windows_tests module.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(windows): add diagnostic tests to debug PowerShell PTY timeouts
Added 6 diagnostic tests that are NOT ignored to help identify where
PowerShell PTY interactions fail:
1. test_diag_01_pwsh_spawn_basic - Can we spawn pwsh via ConPTY?
2. test_diag_02_pwsh_with_env - Do env vars work?
3. test_diag_03_pwsh_env_clear - Does env_clear() work?
4. test_diag_04_pwsh_multiline_script - Do multi-line scripts work?
5. test_diag_05_wt_binary_direct - Can we run wt directly via PTY?
6. test_diag_06_pwsh_invokes_wt - Can pwsh invoke the wt binary?
These will print diagnostic output in CI to help pinpoint where hangs occur.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(windows): add more diagnostic tests for PTY debugging
Added 3 more diagnostic tests:
- test_diag_07_drop_writer_before_read - Tests if explicitly dropping writer helps
- test_diag_08_cmd_exe_basic - Tests cmd.exe (simpler than PowerShell)
- test_diag_09_wt_with_writer_drop - Tests wt binary with writer dropped
Previous diagnostics showed the read blocking forever. Testing if
dropping the master writer before reading helps on ConPTY.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(windows): add more PTY diagnostics (std::process, wait-first, nonblocking)
Added 3 more diagnostic tests:
- test_diag_10_no_pty_cmd_works - Tests std::process::Command (no PTY)
- test_diag_11_wait_then_read - Tests waiting for child exit first
- test_diag_12_nonblocking_read - Tests non-blocking read with polling
These help isolate if the issue is PTY-specific or something else.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): add Windows env vars to configure_pty_command()
The PTY tests were timing out on Windows because configure_pty_command()
called env_clear() but didn't restore critical Windows environment
variables needed for processes to run:
- SystemRoot / windir - Critical for DLL loading
- SystemDrive - Drive letter (usually C:)
- USERPROFILE - Windows equivalent of HOME
- TEMP / TMP - Temp directory paths
- COMSPEC - Path to cmd.exe
- PSModulePath - PowerShell module paths
The exit code 0xC0000138 (STATUS_DLL_NOT_FOUND) in diagnostic tests
confirmed processes were crashing due to missing env vars.
Also added DIAG13 and DIAG14 tests to verify the fix.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): make pty module cross-platform
Changed pty module gate from #[cfg(unix)] to #[cfg(feature = "shell-integration-tests")]
since portable_pty supports Windows via ConPTY.
Also removed unused PathBuf import in DIAG14.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): handle Windows ConPTY read blocking in PTY helpers
On Windows ConPTY, read_to_string() blocks forever because the pipe
doesn't close properly even after the child process exits.
Fix by:
1. Starting the read in a background thread
2. Waiting for child to exit
3. Dropping the master PTY to signal EOF
4. Joining the read thread with a 5-second timeout
This is encapsulated in a new `read_pty_output()` helper that handles
platform-specific reading. Unix continues to use the simpler direct read.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): fix Child trait bounds for Windows PTY
The spawn_command() returns Box<dyn Child + Send + Sync>, so the
read_pty_output helper must accept the same trait bounds.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(windows): remove PTY diagnostic tests, document ConPTY limitations
The diagnostic tests served their purpose - they identified that ConPTY
(Windows Console Pseudo Terminal) has fundamental limitations:
- ConPTY does not properly close the read pipe when child process exits
- This causes read_to_string() to block forever waiting for EOF
- Even cmd.exe /C "echo hello" hangs when reading via ConPTY
- Dropping the PTY master sends CTRL+C to the child (exit code 0xC000013A)
The actual PowerShell tests remain #[ignore] with a detailed TODO
explaining the ConPTY limitations and potential future solutions.
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(tests): implement proper ConPTY handling with cursor response
Based on research into ConPTY behavior, implement proper handling:
1. Keep writer alive during reading to respond to cursor queries
2. Read in chunks instead of read_to_string() (blocks forever on ConPTY)
3. Detect ESC[6n cursor position requests and respond with ESC[1;1R
4. Close master on separate thread while continuing to drain output
Key insight: ConPTY doesn't close the output pipe when child exits.
The pipe is owned by the pseudoconsole, not the child. We must:
- Drain output continuously
- Answer cursor position queries (PSEUDOCONSOLE_INHERIT_CURSOR)
- Call ClosePseudoConsole on a different thread than the reader
References:
- https://learn.microsoft.com/en-us/windows/console/closepseudoconsole
- https://github.com/microsoft/terminal/discussions/17716
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): drop writer before reading on Unix to signal EOF
On Unix PTYs, dropping the writer signals EOF to the child's stdin.
The previous change moved the writer into read_pty_output but used
`let _ = writer;` which doesn't drop immediately (it happens at end
of scope). This caused snapshot tests to fail because the child
wasn't seeing EOF at the right time.
Fix: Use `drop(writer)` explicitly on Unix.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(windows): enable PowerShell PTY tests now that ConPTY works
Enable test_powershell_switch_create and test_powershell_command_failure
to verify the ConPTY cursor response handling works with the actual
PowerShell shell wrapper.
The remaining PowerShell tests can be enabled once these pass.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): use ConPTY-aware reader in exec_in_pty_interactive
The exec_in_pty_interactive function in shell_wrapper.rs had its own
PTY reading logic that didn't include the ConPTY handling required
for Windows. This caused the PowerShell tests to timeout because:
1. It called read_to_string() which blocks waiting for EOF
2. ConPTY doesn't close the pipe when child exits - it stays open
until the pseudoconsole is torn down
Fixed by:
1. Making read_pty_output() public in common/pty.rs
2. Using read_pty_output() in exec_in_pty_interactive instead of
direct read_to_string()
This ensures all PTY-based tests use the same ConPTY handling code.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(powershell): make completion registration more robust
The PowerShell completion registration was failing with:
"Cannot run a document in the middle of a pipeline"
This happened because piping executable output directly in PowerShell
can fail in certain configurations/terminals (like ConPTY).
Fixed by:
1. Capturing output to a variable first, then piping
2. Adding a catch block so completion errors don't break the wrapper
3. Redirecting stderr to null during completion generation
The wrapper function still works even if completion registration fails.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): add Windows env vars to exec_in_pty_interactive
The PowerShell tests were failing with "The specified module could not
be found" because exec_in_pty_interactive was missing critical Windows
environment variables after env_clear().
Added the same Windows env vars that configure_pty_command() sets:
- SystemRoot/windir - needed for system DLL loading
- SystemDrive - needed for many programs
- TEMP/TMP - for temporary files
- COMSPEC - cmd.exe path
- PSModulePath - for PowerShell modules
Without SystemRoot, child processes can't find system DLLs and fail
to load even though the executable path is correct.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(windows): add basic PowerShell diagnostic test
Adding a simpler PowerShell test to debug why the shell integration
tests are failing. This test runs a minimal PowerShell command
directly without the shell wrapper to isolate the issue.
If this test passes but the wrapper tests fail, the issue is with
how we build/execute the wrapper script. If this test fails too,
it's a more fundamental PowerShell/ConPTY issue.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): remove unused import
Co-Authored-By: Claude <noreply@anthropic.com>
* test(windows): add debug output to PowerShell test
Adding detailed debug output to see exactly what script is being
generated and what output/exit code we're getting. This will help
identify why the PowerShell wrapper tests are failing while simple
PowerShell commands work fine.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: remove PowerShell script block wrapper that suppresses output
The `& { } 2>&1` wrapper was causing ConPTY to lose the script output.
Run the script directly instead - stderr naturally appears in the PTY.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: use -File instead of -Command for PowerShell in PTY tests
Write the PowerShell script to a temp file and execute via -File.
Using -Command with long scripts may cause issues with ConPTY output capture.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add debug Write-Host statements to trace PowerShell execution
Adding debug markers at key points:
- Script starting
- Env vars set
- Loading wrapper
- Wrapper loaded
- About to call wt
- wt returned
This will show where script execution fails or output is lost.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add debug output inside PowerShell wt wrapper function
Trace execution inside the wt() function to see:
- Arguments received
- Resolved binary path
- File existence check
- Before/after binary execution
This will show where the output is lost.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add stderr redirect and exception handling to debug binary execution
Wrap binary execution in try/catch and redirect stderr to stdout.
This should capture any errors from the wt.exe binary.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: capture wt binary output into variable and write explicitly
Capture output into variable to check:
- Output length
- Output type
- Then pipe to Write-Host
This will show if the binary produces any output at all.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add working directory debug output to diagnose no-output issue
Check current directory and whether .git exists:
- At script start
- Inside wt function
Binary produces 0 output - likely working directory issue.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: simplify binary execution - don't capture output to variable
Run binary directly with `& $wtBin @Arguments` without capturing
to variable. Let output go directly to console.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: use System.Diagnostics.Process for explicit process execution
Bypass PowerShell's `&` operator and use .NET Process class directly.
This gives explicit control over stdin/stdout/stderr and working directory.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): propagate PowerShell exit code via explicit exit
The wt wrapper function sets $global:LASTEXITCODE but when running
via -File, the script process doesn't return that exit code unless
there's an explicit 'exit $LASTEXITCODE' at the end.
This fixes test_powershell_command_failure which expects exit code 1.
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: remove PowerShell debug output
The ConPTY fix is working. Remove the debug statements that were added
during investigation.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(windows): enable all PowerShell PTY tests
Now that ConPTY pipe closure is handled correctly, all PowerShell tests
should work. The System.Diagnostics.Process approach reliably captures
output and exit codes in ConPTY environments.
Removes #[ignore] from 19 PowerShell tests.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(powershell): properly escape arguments for Windows command line
When using System.Diagnostics.Process, arguments must be properly
escaped for the Windows CommandLineToArgvW parsing rules:
- Arguments with spaces/quotes/backslashes need quoting
- Internal double quotes must be escaped as \"
- Backslashes before quotes must be doubled
Add _wt_escape_arg helper function to handle this correctly.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): remove double-quoting in PowerShell test scripts
The test scripts were using format strings like "$env:WORKTRUNK_BIN = '{}'"
but powershell_quote() already adds single quotes. This resulted in
double-quoted paths like "''path''" which caused PowerShell ParserError.
Fixed by removing the quotes from the format strings.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): fix PowerShell select and step for-each tests
- Fix test_powershell_select_basic: wt select is not available on
Windows, so test the error behavior instead of non-existent --list
- Fix argument escaping: quote `--` in PowerShell since it's a
stop-parsing token that PowerShell consumes instead of passing through
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): prevent PTY read thread join from blocking forever
On Windows ConPTY, the reader thread's blocking read() may not return
even after ClosePseudoConsole is called. The previous code would then
hang forever on read_thread.join().
Fix by dropping the read_thread instead of joining it. The thread will
be cleaned up when the test process exits. We already have the output
from the channel (or timed out trying to get it), so joining serves
no purpose except causing hangs.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): handle ConPTY thread deadlocks and skip flaky verbose test
Two fixes for Windows ConPTY test reliability:
1. Don't join either close_thread or read_thread in read_pty_output.
These can form a deadlock: ClosePseudoConsole waits for reader to
drain, reader waits for ClosePseudoConsole to close the pipe.
"Leaking" threads is acceptable for test code.
2. Skip test_powershell_list_verbose - it triggers a ConPTY race
condition where the output pipe doesn't properly close when the
child exits. The --verbose flag produces enough output to trigger
this timing issue. Other PowerShell tests pass because they produce
less output.
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: remove ISSUE.md research document
Co-Authored-By: Claude <noreply@anthropic.com>
* simplify(shell): remove Process workaround from PowerShell template
The System.Diagnostics.Process approach was added to work around ConPTY
output issues in our test harness (portable_pty). Real PowerShell terminals
work fine with the standard `& $wtBin @Arguments` call.
Removed:
- _wt_escape_arg helper function
- System.Diagnostics.Process for output redirection
- Manual stdout/stderr handling
Now uses: `& $wtBin @Arguments` which is PowerShell's standard splatting
operator, matching how bash/zsh/fish templates work.
Co-Authored-By: Claude <noreply@anthropic.com>
* Revert "simplify(shell): remove Process workaround from PowerShell template"
This reverts commit
|
||
|
|
1f55823c3d |
fix(powershell): handle multiple binaries with same name (#652)
On Windows, `Get-Command wt -CommandType Application` can return multiple results when both Windows Terminal's wt.exe and worktrunk's wt.exe exist. This caused two errors: 1. `Cannot convert 'System.Object[]' to the type 'System.String'` 2. `The term 'wt.exe wt.exe' is not recognized...` Fix by using `Select-Object -First 1` to get the first match from PATH, which is the standard PowerShell pattern for this situation. Relates to #648 Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
f649a65061 | Replace possessive pronouns with articles in user-facing text | ||
|
|
62dfad1562 |
fix: move fish shell integration to functions/ for Homebrew compatibility (#580)
* fix: move fish shell integration to functions/ for Homebrew compatibility Fish shell integration now installs to ~/.config/fish/functions/wt.fish instead of ~/.config/fish/conf.d/wt.fish. The functions/ directory is autoloaded on first command invocation, ensuring PATH is fully configured (including Homebrew) before the wt function loads. Changes: - Fish template now writes to functions/ (autoloaded on first use) - `wt config show` detects legacy conf.d installations and shows migration hint - `wt config shell install` removes legacy conf.d file during migration - `wt config shell uninstall` cleans up both locations - Fish template now suppresses `type -P` stderr when command not found - Shell count in uninstall output counts unique shells (not files) Fixes #566 Co-Authored-By: Claude <noreply@anthropic.com> * refactor: simplify fish wrapper to match bash/zsh pattern - Reduce fish wrapper from ~30 lines to ~10 lines - Wrapper now just calls `wt config shell init fish | source` - WORKTRUNK_BIN handling moves to the full function (sourced at runtime) - Remove incorrect WORKTRUNK_DIRECTIVE_FILE= checks (never written to files) - Update docs link in wrapper comment - Fix tests to use realistic wrapper content Co-Authored-By: Claude <noreply@anthropic.com> * fix: prevent infinite recursion in fish wrapper when wt not in PATH When `wt` isn't in PATH, `command wt` fails but `source` with empty input succeeds (exit 0). The `or return` wouldn't trigger, causing the wrapper to recurse into itself infinitely. Fix by capturing $pipestatus[1] (the exit status of the first command in the pipeline) and returning that status if non-zero. Co-Authored-By: Claude <noreply@anthropic.com> * test: add test for fish wrapper behavior when wt not in PATH This tests the WRAPPER file (fish_wrapper.fish) specifically, not the full function. The wrapper tries to source the full function at runtime. When wt isn't in PATH, it should return 127 (not infinite loop). The existing test (test_fish_binary_not_found_clear_error) tests the FULL function which has its own WORKTRUNK_BIN check. Co-Authored-By: Claude <noreply@anthropic.com> * refactor: show deprecated message when uninstalling legacy fish conf.d When uninstalling fish shell integration, the deprecated conf.d location now shows a clearer message: ○ Removed ~/.config/fish/conf.d/wt.fish (deprecated; now using ~/.config/fish/functions/wt.fish) Instead of the generic: ✓ Removed shell extension for fish @ ~/.config/fish/conf.d/wt.fish This helps users understand that conf.d was a legacy location. Co-Authored-By: Claude <noreply@anthropic.com> * fix: mock claude in config_show test for CI consistency The test was failing in CI because `claude` isn't installed there, causing a different message format. Now uses mock CI tools to ensure consistent output across all environments. Co-Authored-By: Claude <noreply@anthropic.com> * fix: trim both sides when comparing fish wrapper content The fish wrapper template has a trailing newline. When comparing existing content with expected content, we trim the existing file content but not the generated content. This causes the comparison to fail on Windows where line ending handling differs. Fixes Windows CI failure in test_configure_shell_fish_all_already_configured. Co-Authored-By: Claude <noreply@anthropic.com> * test: add coverage for fish legacy detection with functions/ dir This test covers the code path where fish functions/ directory exists but wt.fish doesn't, while legacy conf.d/wt.fish does exist. This exercises a different code path in render_shell_status() than the existing test_config_show_detects_fish_legacy_conf_d test: - Existing test: functions/ doesn't exist → fish is "skipped" - New test: functions/ exists but empty → fish is "configured" with WouldCreate Both should show the migration hint for the legacy conf.d location. Co-Authored-By: Claude <noreply@anthropic.com> * test: add dry-run install test for fish shell This test exercises show_install_preview() which displays the fish wrapper content and completions with gutter formatting when running: wt config shell install fish --dry-run The test verifies: - "Will create" messages are shown (not "Created") - Fish wrapper content is displayed in gutter - Fish completions content is displayed in gutter - No files are actually created Co-Authored-By: Claude <noreply@anthropic.com> * fix: update fish dry-run snapshot for syntax highlighting change The snapshot had a minor syntax highlighting difference where the fish `or` keyword was highlighted differently. Accept the updated rendering. Co-Authored-By: Claude <noreply@anthropic.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * refactor: make Windows .exe suffix handling Windows-only Use #[cfg(windows)] to compile the .exe suffix check only on Windows, where it's meaningful. This removes dead code from non-Windows builds. Co-Authored-By: Claude <noreply@anthropic.com> * test: update fish dry-run snapshot for or syntax highlighting Co-Authored-By: Claude <noreply@anthropic.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * config: exclude snapshot files from typos checking ANSI escape codes in snapshots create false positives (e.g., the fish shell 'or' keyword wrapped in [34m...[0m gets flagged as a typo for 'ore'). Co-Authored-By: Claude <noreply@anthropic.com> * refactor: simplify error handling in configure_shell - Use .ok() for file reads after exists() check - treat read failures as 'not configured' rather than hard errors (race conditions are rare) - Simplify error messages for write operations - just show path and error - Remove verbose 'Failed to...' prefixes from error messages These error paths are unlikely (permission errors, race conditions) and don't warrant dedicated test coverage. Co-Authored-By: Claude <noreply@anthropic.com> * fix: refactor Windows cfg block to avoid clippy blocks_in_conditions Move the let bindings into a block scope instead of using them in an if-condition block, which clippy on Windows flags as a lint violation. Co-Authored-By: Claude <noreply@anthropic.com> * style: use 'To X, run Y' pattern for migration hints Follow CLI output formatting guidelines - command at end for easy copying. Co-Authored-By: Claude <noreply@anthropic.com> * Fix fish wrapper error handling and legacy cleanup - Add source_status check to fish wrapper to catch sourcing failures - Refactor cleanup_legacy_fish_conf_d with early returns and error handling - Move dry-run check before legacy cleanup to prevent file deletion - Add regression test for dry-run with legacy fish conf.d file --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> |
||
|
|
4b8d3b4899 |
Inline shell helper function to fix Claude Code compatibility (#292)
Claude Code's shell snapshots filter out underscore-prefixed functions, which caused `_wt_exec` to be missing while `wt` was captured. This broke the `wt` command in Claude Code sessions with "command not found: _wt_exec". The fix inlines the directive file handling directly into the `wt` function for bash, zsh, and fish (PowerShell already used this pattern). This makes the shell wrapper self-contained with no external dependencies. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
5656ed4e1b |
Remove unnecessary piped stdout bypass from shell wrappers (#278)
The shell wrappers had a check to bypass shell integration when stdout was piped (e.g., `wt list | jq`). This was needed for an older output system that didn't cleanly separate stdout from stderr. With the current output system: - `table()` → stdout (data) - `print()` → stderr (status messages) - Directives → file (cd commands) This separation means piping works correctly with shell integration active. Removing the bypass actually improves behavior for cases like `wt switch feature | tee log.txt` where you want both piped output AND shell effects (cd). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
7146ab0d3d |
Refactor shell function names to avoid conflicts
Add `safe_fn` Askama filter to convert command names with hyphens to underscores in shell function identifiers. Rename generic `wt_exec` functions to `_<cmd>_exec` format (e.g., `_wt_exec`, `_git_wt_exec`) to prevent naming conflicts when multiple commands are loaded. Update all shell templates (bash, zsh, fish, posix) and add test coverage for hyphenated command names. |
||
|
|
87321281d4 |
Replace --internal flag with WORKTRUNK_DIRECTIVE_FILE environment variable (#269)
* Replace --internal flag with WT_DIRECTIVE_FILE environment variable * Rename directive file environment variable to WORKTRUNK_DIRECTIVE_FILE * Update stale comments referencing directive scripts Codex review identified comments that still referenced "directive scripts" after migrating to file-based directive passing. Updated to reference "data output" which is the current terminology. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Address documentation review feedback - Add WORKTRUNK_DIRECTIVE_FILE to env var tables (cli.rs, config.md) - Update stale "directive mode" terminology in test comments to use "shell integration" or "data output" as appropriate - Regenerate help snapshot 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Refactor progressive table output to use output module Remove finalize_non_tty method and simplify non-TTY output path to use output::table() directly, consistent with buffered mode. Add WORKTRUNK_SHELL environment variable support for PowerShell-specific path escaping. Update documentation and templates accordingly. * Preserve directive script exit code in PowerShell Add logic to use the directive script's exit code when wt succeeds, and add redaction for WORKTRUNK_DIRECTIVE_FILE in test snapshots. --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
b4e2f2e4ed |
Fix shell wrapper piping and simplify process detachment (#258)
Detached processes now use process_group(0) instead of nohup, allowing them to survive PTY closure while remaining responsive. Shell wrappers now detect piping via `[[ ! -t 1 ]]` and bypass the wrapper when stdout isn't a terminal, enabling commands like `wt list --format=json | jq`. Updated shell templates (bash, zsh, fish, PowerShell) to check for redirected output and run the binary directly in those cases. Removed dev-detach dependency in favor of portable PTY for shell integration tests. Simplified output routing by removing data_raw() function and consolidating data output handling. Added FAQ entry explaining JSON output routing and piping behavior. |
||
|
|
d3c9bf650b |
Add git-wt binary for Windows (#177)
* Add git-wt binary for Windows (wt conflicts with Windows Terminal)
- Add `git-wt` binary behind `--features git-wt` feature flag
- Add `--cmd` option to `config shell init/install` (defaults to argv[0])
- Shell templates now use `{{ cmd }}` for binary name throughout
- Fix `--source` flag to use correct binary with `cargo run --bin`
- Extract `add_standard_env_redactions()` for DRY snapshot settings
- Document Windows workaround in FAQ
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix rustdoc link in argv[0] doc comment
* Fix Windows binary name detection stripping .exe extension
Use `file_stem()` instead of `file_name()` to strip the `.exe` extension
on Windows. This fixes `test_configure_shell_already_exists` which was
failing because the config line detection compared `wt` (in file) with
`wt.exe` (from argv[0]).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
|
||
|
|
6922780d5e |
Add Windows support via Git Bash with PowerShell fallback (#122)
* Add Windows support via Git Bash with PowerShell fallback
Implements cross-platform shell execution for Windows:
- New `shell_exec` module providing unified shell abstraction
- Unix: uses `sh -c`
- Windows: prefers Git Bash (checks $MSYSTEM, standard paths,
derives from git.exe), falls back to PowerShell
- Cached detection via OnceLock for performance
- Updated shell execution points to use ShellConfig:
- execute_streaming() in output/handlers.rs
- spawn_detached_windows() in commands/process.rs
- InteractiveOutput::execute() in output/interactive.rs
- help_pager.rs (skips less default without POSIX shell)
- Added PowerShell shell integration:
- New Shell::PowerShell variant with config paths
- templates/powershell.ps1 with documented limitations
- Basic wt wrapper and tab completion support
Design: Git Bash enables same bash hook syntax on all platforms.
PowerShell fallback works for basic commands but has limitations
(no directory change, hooks using bash syntax won't work).
Closes #121
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add which crate and Windows-specific tests
- Use `which` crate for cleaner executable path detection
- Add Windows-specific unit tests for CI:
- Shell detection (Git Bash vs PowerShell)
- Command execution validation
- POSIX syntax support verification
- Add documentation about Windows limitations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix clippy collapsible_if and improve error message
- Collapse nested if statement in find_git_bash() to satisfy clippy
- Update home directory error message to mention Windows environment variable
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix Windows clippy errors and add PowerShell integration detection
- Gate Command import with #[cfg(unix)] in process.rs
- Gate Stdio and ShellConfig imports with #[cfg(unix)] in interactive.rs
- Add PowerShell profile detection to is_integration_configured()
- Fix collapsible_if warnings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix PowerShell tab completion to use clap's generated script
Previously we had a custom Register-ArgumentCompleter that didn't
properly interface with clap's completion system. Now we let clap
generate its completion script and eval it, which handles:
- Proper cursor position tracking
- Tab-separated output format with help text
- Correct argument passing with -- separator
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add warnings for Windows users without Git Bash
When installing PowerShell shell integration on Windows without Git Bash:
- Show warning about limited functionality
- List specific limitations (no directory change, bash hooks won't work)
- Suggest installing Git for Windows
Also:
- Include PowerShell in auto-detected shells on Windows
- Add is_windows_without_git_bash() helper to ShellConfig
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Improve Windows test assertions
- Check stdout contains expected output instead of just "not empty"
- Remove fallback assertions that would pass even if wrong stream used
- Simplify POSIX redirection test command
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Document PowerShell stdout redirection limitation
PowerShell doesn't support redirecting stdout to stderr (*>&2 fails).
Document this known limitation with link to PowerShell issue #7620.
The practical impact is limited since:
- Users are warned at shell install time about PowerShell limitations
- Hooks using bash syntax need Git Bash anyway
- Most hook output is informational
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add PowerShell directory change support via --internal=powershell
PowerShell can now change directories after `wt switch` using the same
pattern as zoxide/fnm/starship:
1. `--internal` now takes an optional shell type: `--internal=posix` (default)
or `--internal=powershell`
2. PowerShell wrapper passes `--internal=powershell` and captures stdout
3. Binary outputs `Set-Location 'path'` for PowerShell, `cd 'path'` for POSIX
4. Wrapper executes the directive via Invoke-Expression
Changes:
- Add DirectiveShell enum (Posix, Powershell) to cli.rs
- Update OutputMode::Directive to carry shell type
- Add shell-specific path escaping in directive.rs
- Rewrite PowerShell template to use directive mode
- Update install warning (only hooks limitation now, not cd)
- Add tests for PowerShell path formatting
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix Windows implementation weaknesses
- Fix PowerShell backtick escaping (backticks are literal in single quotes)
- Sanitize Windows-illegal characters in log filenames (< > : " \ | ? *)
- Use dirs crate for non-English Windows Documents folder
- Support both PowerShell Core and Windows PowerShell 5.1 profiles
- Add require_equals to --internal flag to fix CLI parsing
- Fix PowerShell wrapper stderr handling (don't merge with stdout)
- Redirect hook stdout to stderr on non-POSIX shells via Stdio::from(io::stderr())
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Address Codex review findings
- Handle Windows reserved device names (CON, PRN, AUX, NUL, COM1-9, LPT1-9)
in filename sanitization by prefixing with underscore
- Propagate exit code in PowerShell wrapper so $? and $LASTEXITCODE are
consistent for scripts and CI
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Enable shell integration tests on Windows with runtime shell detection
- Remove Unix-only restriction from test common module
- Add shell_available() function to detect available shells at runtime
- Add skip_if_shell_unavailable! macro to skip tests for unavailable shells
- Enable shell-integration-tests feature on Windows CI
- Tests automatically skip unavailable shells (zsh, fish on Windows)
This allows bash tests to run on Windows via Git Bash while gracefully
skipping zsh/fish tests that require those shells.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix Windows reserved device name detection
Code review found that COM0 and LPT0 were incorrectly being treated as
reserved device names. Only COM1-9 and LPT1-9 are reserved on Windows,
not COM0/LPT0.
Changes:
- Change `is_ascii_digit()` to `matches!(c, '1'..='9')` in sanitize_for_filename
- Add comprehensive test coverage for reserved device names
- Add explanatory comment for Windows process detachment
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Gate Unix-only test modules to fix Windows CI
The shell integration tests and progressive output tests use Unix-specific
features (PTY, dev-detach binary with setsid). Gate these modules with
#[cfg(unix)] so they don't compile on Windows, fixing dead code warnings.
Changes:
- Gate shell module with #[cfg(all(unix, feature = "shell-integration-tests"))]
- Gate progressive_output module with #[cfg(unix)]
- Gate e2e_shell.rs, e2e_shell_post_start.rs, shell_wrapper.rs with #[cfg(all(unix, ...))]
- Gate list_progressive.rs with #[cfg(unix)]
Windows shell integration support is planned for a future PR.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Gate test utilities module to Unix-only to fix Windows CI
The tests/common/mod.rs module is only used by integration tests which
are gated to Unix-only. On Windows, the common module was being compiled
but had no consumers, causing dead code warnings that failed CI.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
|
||
|
|
334f6d9927 |
fix: reset ANSI state before returning to shell
Colored output on stderr left terminal in non-default state. Reset ANSI formatting before emitting shell script to stdout to ensure clean terminal state for subsequent commands. Also remove color forcing logic from shell templates as it's now handled consistently by the binary. |
||
|
|
f01cf931a4 |
Prevent zsh completion grouping of branches with identical descriptions
Add `list-grouped false` zstyle to prevent zsh from grouping completions with identical descriptions onto a single line. When multiple branches share the same timestamp, zsh's `_describe` function normally groups them together (e.g., "release main -- + 12m") to save space. This zstyle forces each branch to display on its own line while preserving the value/description association. Also document the issue in ISSUE.md with technical analysis, attempted solutions, and open questions about zsh completion behavior. |
||
|
|
6ae9d0f939 |
Fix zsh _describe syntax and add validation tests
The sed command was incorrectly passing arguments to the -V flag, which does not accept arguments in zsh's _describe function. The -V flag only sets a flag for unsorted groups; the actual nosort behavior is handled internally by _describe when passed to compadd. Add validation tests to catch invalid _describe syntax patterns in future changes, including checks for improper flag arguments and invalid option combinations. |
||
|
|
0301d4bf1b |
Fix stderr redirection in fish shell wrapper
Fish's command substitution `(...)` runs in an isolated pipeline where stderr doesn't inherit caller redirects. Replace with pipeline capture using `| read` so stderr flows through normally and respects redirects like `wt --help &>file`. Add `--internal` flag handling to skip pager in directive mode, ensuring help output goes to stderr without paging when called from the shell wrapper. Add comprehensive integration tests verifying stderr/stdout redirection works correctly across bash, zsh, and fish shells. |
||
|
|
a80a5eaa96 |
Fix shell completion to bypass shell function (#105)
* Add test for zsh lazy completion function definition Test that _wt_lazy_complete correctly defines the clap completer function when triggered. This catches a bug where the shell function shadows the binary, causing the completion script to be eval'd in the wrong context. The test simulates the real user scenario where WORKTRUNK_BIN is not set and wt is found in PATH, which is when the bug manifests. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix zsh lazy completion to bypass shell function The _wt_lazy_complete function was calling ${WORKTRUNK_BIN:-wt} to generate completions, but when WORKTRUNK_BIN is unset, wt resolves to the shell function (not the binary). The shell function runs wt_exec which evals the completion script internally but doesn't re-emit it, causing the outer eval to receive nothing. The fix uses command to bypass the shell function and call the binary directly: eval "$(COMPLETE=zsh command "${WORKTRUNK_BIN:-wt}" ...)" This error manifested as: _wt_lazy_complete:5: command not found: _clap_dynamic_completer_wt 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Add test for bash lazy completion function definition Test that _wt_lazy_complete correctly defines the clap completer function when triggered. This catches the same bug as zsh where the shell function shadows the binary. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix bash lazy completion to bypass shell function Same fix as zsh: use `command` builtin to ensure the binary is called instead of the shell function when generating completions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix completion to bypass wt_exec when COMPLETE is set The shell function wt() was passing completion output through wt_exec, which evals stdout as shell script. But with COMPLETE set, the binary outputs completion candidates (not shell script), causing bash to try executing them as commands. Fix: Detect COMPLETE env var in shell function and call binary directly, bypassing --internal and wt_exec. This check must be in the shell layer because clap's completion handler runs before argument parsing. Also rewrites completion tests to be black-box: - Use `complete -p wt` / `$_comps[wt]` to verify registration - Dynamically discover completion function names - Don't reference internal function names like _clap_complete_wt 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Preserve recency ordering in zsh completions Zsh's _describe function sorts completions alphabetically by default. This patch post-processes clap's generated completion script to add: - `-V wt` creates an unsorted group - `-o nosort` explicitly disables sorting This preserves our recency-based ordering (most recently used worktrees first) instead of alphabetical sort, matching fish's behavior. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
50e5cf171d |
fix(fish): Handle empty WORKTRUNK_BIN in completions (#83)
The fish completion script was failing with "The expanded command was empty" when WORKTRUNK_BIN was set but empty. The `set -q` check only verifies the variable exists, not that it has a value. Fix by using `test -n "$WORKTRUNK_BIN"` which correctly handles both unset and empty variables, eliminating the need for separate existence checks. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
fa512406e4 | Fix: Correctly load wt binary in Fish shell integration | ||
|
|
c24f5bfecb |
feat(shell): Stream stderr to terminal directly
Initializes the shell to redirect stderr directly to the terminal, improving real-time error visibility. |
||
|
|
42de37e9b4 |
Streamline --source execution in shell wrappers
The `--source` flag now directly uses `cargo run` instead of `cargo build` and then setting `WORKTRUNK_BIN`. This simplifies the logic and removes the need to restore `WORKTRUNK_BIN` after execution. |
||
|
|
72a00e4629 |
Remove config shell completions subcommand
This removes the `wt config shell completions` subcommand, as Bash and Zsh completions are inline in their respective init scripts, and Fish completions are now written directly to `~/.config/fish/completions/wt.fish` during `wt config shell install` (which uses `$WORKTRUNK_BIN` to bypass the shell wrapper). |
||
|
|
c14a20c9a7 |
refactor: Simplify shell integration protocol for robustness
Updates the `--internal` flag's output format from NUL-terminated directives to a shell script emitted on stdout at the end of execution. User-facing messages now stream exclusively to stderr in real-time. This change: - Eliminates the need for FIFOs and background processes in shell wrappers, simplifying implementation. - Ensures all user messages stream directly to the terminal, improving real-time feedback. - Uses standard POSIX single-quote escaping for paths, making it more robust against injection. - Aligns with proven patterns like direnv (stderr for logs, stdout for script). Removes support for Elvish, Nushell, PowerShell, and Xonsh shells due to their complexities in implementing the previous streaming NUL-byte directive protocol. Bash, Zsh, and Fish are now simpler and more reliably supported. Updates documentation, code comments, and integration tests to reflect the new protocol. |
||
|
|
0fe75642ed |
feat(zsh): Advise on compinit if missing during install
Adds a warning to `wt config shell install` for zsh users if their `~/.zshrc` does not enable `compinit`. Zsh completions require `compinit` to be sourced, but it's not enabled by default. The advisory message is only shown during `install` (not `init`) and only when: - The user explicitly runs `wt install zsh`. - The user runs `wt install` (all shells) and their current shell is zsh. The `wt config shell init zsh` output no longer warns about missing compinit, as that output is sourced on every shell startup and shouldn't produce warnings. Instead, it now includes an inline comment in the generated shell script. This commit also adds a new `shell::detect_zsh_compinit()` function to probe for `compinit`'s presence and `shell::is_current_shell_zsh()` to check the current shell. |
||
|
|
ca931796f2 |
Fix: Suppress bash job control notifications in wt_exec
This changes the `wt_exec` function to disable both `START` and `DONE` job notifications in bash. Previously, only `START` notifications (`[1] 12345`) were suppressed via stderr redirection. This update adds logic to also suppress `DONE` notifications (`[1]+ Done ...`) by temporarily disabling `monitor` mode (`set +m`). A detailed comment block is added to explain the two distinct bash job notification mechanisms and how each is suppressed, along with references to bash documentation and community discussions. |
||
|
|
35766787c5 |
Improve Bash/Zsh lazy completion for config shell init
Refactors `config shell init` for Bash and Zsh to: - Use a simpler lazy loading mechanism. Completions are generated on the first TAB press and then delegated to the `clap` completer. - Output directly into the init script, removing the need for separate completion files (`~/.zfunc/_wt` and `~/.local/share/bash-completion/completions/wt`). - Update `config shell install` and `config shell uninstall` to reflect these changes in messages and behavior. - Add warnings for Zsh users if `compinit` is not loaded before the `worktrunk` init script. |
||
|
|
3806b65d9b |
feat: Enhance shell completion management and installation
This commit introduces a comprehensive set of improvements for shell completion management. It includes: - Writing completions to native shell directories for better integration. - Implementing lazy Zsh completions for easier setup. - Configuring shell completions during the installation process. - Removing completion files during shell uninstallation. - Grouping shell configuration with completions in the install output. - Using XDG base directories for completion paths. - Using `home_dir()` for `completion_path` to properly handle missing `HOME`. This also includes various style improvements, updated test snapshots, and documentation regarding zsh completion installation issues. |
||
|
|
1407051e35 |
fix: Make bash completion nosort option conditional for macOS (#37)
The `nosort` option for bash's `complete` command is only available in Bash 4.4+. macOS ships with Bash 3.2 due to licensing, which causes CI failures with `bash: complete: nosort: invalid option name`. Check the bash version before using nosort and fall back to not using it on older versions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com> |