Commit a2722c2
## Summary
When diffnav is configured as `pager.diff` (per the README), git pipes
the output of every `git diff` invocation through diffnav, including
non-unified-diff variants like `git diff --stat`, `--shortstat`,
`--name-only`, and `--name-status`. Those produce summary text with no
`diff --git ` markers, which causes two latent bugs:
1. **Panic.** The `bluekeyes/go-gitdiff` parser returns zero files, the
TUI tries to render a scrollbar over an empty viewport, and the program
panics with `runtime error: integer divide by zero` in `RenderScrollbar`
([pkg/ui/common/scrollbar.go:18](https://github.com/dlvhdr/diffnav/blob/main/pkg/ui/common/scrollbar.go#L18)).
2. **Escape-sequence leak.** Before the panic, bubbletea's
terminal-capability handshake leaks `[?2026\$p[?2027\$p` query bytes to
the user's stdout — the symptom in the bug report.
## Fix
Detect non-unified-diff input early in `cmd/root.go` (after stdin is
fully read, before opening the TTY) and pass it through verbatim. The
caller sees the same output they would have without diffnav as the
configured pager — same behaviour as `cat`/the implicit
pager-fallthrough that other TUI pagers use for non-diff input.
Detection is a `strings.Contains(input, "diff --git ")` check, extracted
into a small `isUnifiedDiff` helper for unit testing. Both `git diff`
and `git show` always emit at least one `diff --git ` header in the
unified form, so the check matches the TUI's actual input contract.
## Test plan
- [x] **8 new unit tests** in `cmd/input_test.go` covering:
- `git diff` (unified)
- `git show` (preamble + unified)
- `git diff --stat`
- `git diff --shortstat`
- `git diff --name-only`
- `git diff --name-status`
- `git log` (no patch)
- empty input
- [x] **Empirically reproduced on Windows** with the canonical `--stat`
output:
- **Pre-fix**: `[?2026\$p[?2027\$p` bytes leak, then `runtime error:
integer divide by zero` panic.
- **Post-fix**: stat output is printed verbatim and diffnav exits 0.
- [x] **Real unified-diff input still routes to the TUI** (verified by
piping `gh_dash_pr.diff` test fixture into the post-fix binary — TUI
starts, hits the same pre-existing panic the upstream test environment
hits, confirming the input is reaching the renderer).
## Notes
- The two pre-existing `pkg/ui/panes/filetree` test failures on `main`
(`TestNoLastPath`, `TestCollapseTree`) are unrelated lipgloss-styling
differences and not touched by this PR.
- This is a strict superset: any input that previously rendered now
still renders; only inputs the renderer would have crashed on now exit
gracefully.
- Closes #115. Should also fix the `git log` symptom from #28
(re-emerged after the recent v2 rewrite, since `git log` without `-p`
produces no `diff --git ` line and would hit the same path).
## AI usage disclosure (per AI_POLICY.md)
Tool: Claude Code (Opus 4.7).
Extent: pattern analysis (root cause for the panic + escape leak), code
drafting for the `isUnifiedDiff` helper and the early-return path, and
the test cases. I reviewed every change manually, ran `go build`, `go
test ./cmd/...`, and reproduced the pre-/post-fix behaviour locally on
Windows before pushing. Happy to walk through any line on request.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7934a39 commit a2722c2
3 files changed
Lines changed: 105 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
202 | 202 | | |
203 | 203 | | |
204 | 204 | | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
205 | 213 | | |
206 | 214 | | |
207 | 215 | | |
| |||
0 commit comments