Preview uncommitted changes in the detail pane

For a dirty submodule, list the changed files so the user can remember
what they were doing there:

  Changes   5 files · 2M 1A 1D 1R · +37 −12
            ──────────────────────────────────
            M  render.go  src/render/  +20 −4  3d ago
            ?  scratch.txt                     5m ago

- Status.Changes: files changed against HEAD (staged and unstaged
  combined) with kind, line counts and modification time; sorted by kind,
  then by size; capped at 200 with totals over all files.
- Git provider: parse `status --porcelain=v2 -z` and one
  `diff HEAD --numstat -z -M`, only for dirty submodules.
- Detail pane: flat list with a colored status letter per file, like IDE
  source-control views; counts and age in compact columns; up to 10 files,
  every kind keeps a line, the rest is summarized as "n more".
- Fixture gains libs/work with every kind of change; mock data extended.
- Docs: F24, change preview in the UX guide, D17.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Simon Franken
2026-10-21 15:55:46 +02:00
co-authored by Claude Opus 5.5
parent 64fe34b5b0
commit 19c6f17eb2
17 changed files with 882 additions and 32 deletions
+50 -4
View File
@@ -61,12 +61,58 @@ indent ▸ name [n] status ref delta
2. One line per issue: word (colored, 10 columns) + explanation;
`in sync nothing to do` if there are none; `staged` and
`detached HEAD on pin` as information
3. `Ref` with distance and `via <rule>`
4. `Pinned`, `Checkout`, `Tip`: SHA + subject; the checkout SHA is yellow if it
3. `Changes` (only with uncommitted changes), see
[Change preview](#change-preview)
4. `Ref` with distance and `via <rule>`
5. `Pinned`, `Checkout`, `Tip`: SHA + subject; the checkout SHA is yellow if it
differs from the pin
5. "Pin is n commits behind/ahead of …" / "Pin and … have diverged": commit list
6. `Children` (count and issues below), `URL`
6. "Pin is n commits behind/ahead of …" / "Pin and … have diverged": commit list
7. `Children` (count and issues below), `URL`
#### Change preview
```
Changes 5 files · 2M 1A 1D 1R · +37 −12
──────────────────────────────────────
M render.go src/render/ +20 −4 3d ago
M README.md +3 −1 20m ago
A notes.md docs/ +14 2h ago
D old.go src/ −8
R new.go ← old.go 1d ago
? scratch.txt 5m ago
… 3 more (2M 1?)
```
- A flat list, no group headers: IDEs (VS Code, JetBrains) do the same, and
headers would use up the few lines the preview has. The letter is the
meaning, the color only supports it (N4).
- Letters and colors: `!` red bold, `M` yellow, `A` green, `D` red, `R`
cyan, `?` muted. Line counts: green `+n`, red `−n`; `bin` for binary
files, `submodule` for a moved nested pin, nothing for untracked files.
- Order: kind (`!`, `M`, `A`, `D`, `R`, `?`), then changed lines, largest
first, because the biggest edits are the ones people remember.
- Budget: 10 files. Every kind that occurs gets at least one line, the
rest is filled in sort order. `… n more (<kinds>)` summarizes the hidden
files. With 11 files all are shown: "1 more" would take the same line as
the file itself.
- The `Changes` line summarizes all files: count, files per kind, line
totals. Everything below it describes one file per line, so no line can
be mistaken for a file's detail. In a narrow pane the line totals are
dropped rather than cut.
- A muted rule (`─`, `-` in ASCII mode) separates the summary from the
files. It starts in the value column and is as wide as the summary or
the file table, whichever is wider.
- The age (muted) is the file's modification time, so the most recently
touched files stand out. Removed files have no age.
- The list starts in the value column (under `5 files`), like every other
value in the pane.
- File name bold, directory muted. Counts form a right-aligned column
directly after the widest path (max 48 columns), not at the pane's edge,
so they stay next to their file in wide panes. If space is short the age
column goes first, then the directory is cut from the left
(`…ernal/client/`), the name last. For
renames the muted part is `← old/path`.
- Untracked directories are shown as one entry (`tmp/`).
### Header
`path branch ↑↓ · n submodules · <count> <issue>… · n pin staged · n loading · fetched <age>`