Skip to content

feat: reviewed file marks and A/M/D status indicators in file tree - #54

Merged
umputun merged 3 commits into
umputun:masterfrom
melonamin:feat/reviewed-files-and-status-indicators
Apr 7, 2026
Merged

umputun merged 3 commits into
umputun:masterfrom
melonamin:feat/reviewed-files-and-status-indicators

Conversation

@melonamin

@melonamin melonamin commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Per-file reviewed state toggled with Space — shown as in the file tree and ✓ N/M counter in the status bar
  • Git file change status (A/M/D/R) displayed next to each filename, color-coded (green added, red deleted, muted modified/renamed)
  • ChangedFiles() now uses --name-status -z for NUL-terminated output, correctly handling special characters and renames

Rationale

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

screenshot-2026-04-07_09-07-11

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 umputun left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@umputun
umputun merged commit e9744e0 into umputun:master Apr 7, 2026
5 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/M progress indicator in the status bar.
  • Display Git file status letters (A/M/D/R) next to filenames with color styling, backed by a new diff.FileEntry return 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.

Comment thread app/diff/diff.go
Comment on lines +104 to 114
// 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]
}

Copilot AI Apr 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copilot uses AI. Check for mistakes.
Comment thread app/keymap/keymap.go
{ActionToggleLineNums, "toggle line numbers", "View"},
{ActionToggleBlame, "toggle blame gutter", "View"},
{ActionToggleHunk, "toggle hunk in collapsed", "View"},
{ActionMarkReviewed, "mark file as reviewed", "View"},

Copilot AI Apr 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
{ActionMarkReviewed, "mark file as reviewed", "View"},
{ActionMarkReviewed, "toggle reviewed mark", "View"},

Copilot uses AI. Check for mistakes.
sanchesfree pushed a commit to sanchesfree/revdiff that referenced this pull request Apr 8, 2026
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants