feat: reviewed file marks and A/M/D status indicators in file tree - #54
Conversation
Add space bar toggle to mark files as reviewed (green ✓ checkmark in tree), with progress shown in status bar (✓ N/M) and mode icon strip. Change Renderer.ChangedFiles to return []FileEntry with git status info, enabling A/M/D indicators in the tree sidebar with semantic colors (green=added, red=deleted, muted=modified).
- Add FileStatus type with constants (FileAdded, FileModified, etc.) replacing raw string literals - Pre-compute status styles (StatusAdded, StatusDeleted, StatusDefault) on styles struct instead of allocating per render - Remove dead indent parameter from renderFileEntry - Move status styling to styles.fileStatusStyle() method - Build []FileEntry directly in DirectoryReader without intermediate []string allocation - Remove WHAT comments that restated the code
…truction Switch ChangedFiles to git diff --name-status -z for robust parsing of filenames with special characters. Add newFileTreeFromEntries to eliminate the roundtrip of extracting paths then re-inserting statuses. Fix tree-pane mark-reviewed to use selected row instead of stale currFile.
umputun
left a comment
There was a problem hiding this comment.
LGTM, thx. clean and well-structured as usual.
interface migration from []string to []FileEntry is complete and consistent across all 6 implementations + mock + callers. NUL-terminated parsing with --name-status -z is correct, including R100/C100 rename handling. Space marking works from both tree and diff panes, nice touch.
will merge.
There was a problem hiding this comment.
Pull request overview
This PR enhances the TUI’s file tree into a “review dashboard” by adding per-file reviewed markers and Git change-status indicators, and by upgrading the diff renderer’s file listing to return richer metadata (path + status) with robust NUL-terminated parsing.
Changes:
- Add per-file reviewed state toggled via
Space, rendered as✓in the file tree and as a✓ N/Mprogress indicator in the status bar. - Display Git file status letters (
A/M/D/R) next to filenames with color styling, backed by a newdiff.FileEntryreturn type. - Update Git changed-files parsing to use
git diff --name-status -z(NUL-terminated), improving handling of special characters and rename/copy records.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| app/ui/styles.go | Adds styles and helpers for reviewed marks and git status coloring. |
| app/ui/model.go | Wires the reviewed toggle action, shows reviewed progress in status bar, and consumes []diff.FileEntry. |
| app/ui/model_test.go | Updates renderer mocks/tests for FileEntry and adds coverage for reviewed toggling + status display. |
| app/ui/mocks/renderer.go | Updates generated mock interface to return []diff.FileEntry. |
| app/ui/filetree.go | Stores reviewed flags + per-path git statuses; renders ✓ and status letters in the tree. |
| app/ui/filetree_test.go | Adds tests for reviewed toggling and checkmark rendering. |
| app/ui/annotlist_test.go | Updates tests to pass filesLoadedMsg with []diff.FileEntry. |
| app/keymap/keymap.go | Adds ActionMarkReviewed and binds it to Space with help entry. |
| app/keymap/keymap_test.go | Updates expected default bindings to include Space -> mark_reviewed. |
| app/diff/stdin.go | Updates stdin renderer to return []diff.FileEntry. |
| app/diff/fallback.go | Updates fallback renderer to operate on []diff.FileEntry and preserve status metadata. |
| app/diff/fallback_test.go | Updates expectations for FileEntry (including status where applicable). |
| app/diff/exclude.go | Updates exclude filter to filter by FileEntry.Path while preserving status metadata. |
| app/diff/exclude_test.go | Updates tests to use []FileEntry. |
| app/diff/directory.go | Updates directory reader to return []FileEntry (paths only). |
| app/diff/directory_test.go | Updates tests to expect []FileEntry. |
| app/diff/diff.go | Introduces FileStatus/FileEntry and switches ChangedFiles() to --name-status -z parsing. |
| app/diff/diff_test.go | Updates changed-files tests to assert []FileEntry results. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // for renames/copies (R100, C100), consume two paths, use the new name | ||
| if rawStatus[0] == 'R' || rawStatus[0] == 'C' { | ||
| if i < len(fields) { | ||
| path = fields[i] | ||
| i++ | ||
| } | ||
| } | ||
| // normalize status to single letter (R100 -> R) | ||
| if len(rawStatus) > 1 { | ||
| rawStatus = rawStatus[:1] | ||
| } |
There was a problem hiding this comment.
Git.ChangedFiles now includes special handling for renames/copies in --name-status -z output, but the test suite doesn’t cover these cases. Add unit tests that create a repo change involving a rename (and ideally a copy) and assert the returned []FileEntry uses the new path and the normalized status (R/C).
| {ActionToggleLineNums, "toggle line numbers", "View"}, | ||
| {ActionToggleBlame, "toggle blame gutter", "View"}, | ||
| {ActionToggleHunk, "toggle hunk in collapsed", "View"}, | ||
| {ActionMarkReviewed, "mark file as reviewed", "View"}, |
There was a problem hiding this comment.
The help description says "mark file as reviewed", but the action actually toggles the reviewed state on/off. Consider updating the description to reflect toggling (e.g., "toggle reviewed mark") so the help text matches behavior.
| {ActionMarkReviewed, "mark file as reviewed", "View"}, | |
| {ActionMarkReviewed, "toggle reviewed mark", "View"}, |
…mputun#54) * feat: add reviewed file marks and A/M/D status indicators in file tree Add space bar toggle to mark files as reviewed (green ✓ checkmark in tree), with progress shown in status bar (✓ N/M) and mode icon strip. Change Renderer.ChangedFiles to return []FileEntry with git status info, enabling A/M/D indicators in the tree sidebar with semantic colors (green=added, red=deleted, muted=modified). * refactor: simplify reviewed marks and file status code - Add FileStatus type with constants (FileAdded, FileModified, etc.) replacing raw string literals - Pre-compute status styles (StatusAdded, StatusDeleted, StatusDefault) on styles struct instead of allocating per render - Remove dead indent parameter from renderFileEntry - Move status styling to styles.fileStatusStyle() method - Build []FileEntry directly in DirectoryReader without intermediate []string allocation - Remove WHAT comments that restated the code * refactor: use NUL-terminated git output and streamline file tree construction Switch ChangedFiles to git diff --name-status -z for robust parsing of filenames with special characters. Add newFileTreeFromEntries to eliminate the roundtrip of extracting paths then re-inserting statuses. Fix tree-pane mark-reviewed to use selected row instead of stale currFile.
Summary
Space— shown as✓in the file tree and✓ N/Mcounter in the status barA/M/D/R) displayed next to each filename, color-coded (green added, red deleted, muted modified/renamed)ChangedFiles()now uses--name-status -zfor NUL-terminated output, correctly handling special characters and renamesRationale
When reviewing large diffs with many files, it's easy to lose track of which files you've already looked at. The reviewed marks (✓) give you a lightweight way to track progress without leaving the TUI — just hit Space. The status bar counter (✓ 3/12) shows at a glance how far along you are.
The A/M/D indicators complement this by letting you prioritize your review — you might want to look at newly added files first, or focus on deletions that could break things. Having both together turns the file tree into a proper review dashboard.
Screenshot