Skip to content

feat: add calculate_cumulative_size command#628

Open
BoogerMan2103 wants to merge 2 commits into
kamiyaa:mainfrom
BoogerMan2103:feat-cumulative-size
Open

feat: add calculate_cumulative_size command#628
BoogerMan2103 wants to merge 2 commits into
kamiyaa:mainfrom
BoogerMan2103:feat-cumulative-size

Conversation

@BoogerMan2103
Copy link
Copy Markdown

Summary

asciicast

Adds a calculate_cumulative_size command that mimics ranger's dc
("get cumulative size"). It recursively walks the visual / permanent
selection (falling back to the entry under the cursor when nothing is
selected), sums every regular file's bytes, stores the result on each
measured entry, and posts the total to the status line.

Bound to d c by default — matches the ranger muscle memory.

Closes the recurring ask for a du -hs-style readout (see #229 and the
discussion under #334, where partial / lazy directory sizing was
rejected for breaking user expectations).

What's in the PR

New command

  • src/commands/cumulative_size.rs — recursive walker (du-style:
    does not follow symlinks, counts the symlink's own size; tolerates
    per-entry I/O errors) and the command entry point. Iterates
    selected_or_current(), sums, stores per-entry, and emits a status
    message — Size of foo: 1.2 G for one entry, Cumulative size of N items: … for many.

Metadata

  • src/fs/metadata.rs — new cumulative_size: Option<u64> field,
    distinct from the existing directory_size: Option<usize> (which is
    an item count). Accessor + setter, no other call-sites touched.

Command plumbing

The usual fan-out so the command is reachable from the keymap, the
command line, and the help page:

  • src/constants/command_name.rsCMD_CALCULATE_CUMULATIVE_SIZE.
  • src/types/command/mod.rsCommand::CalculateCumulativeSize.
  • src/types/command/impl_appcommand.rs,
    impl_appexecute.rs, impl_from_str.rs, impl_comment.rs — name,
    dispatch, parsing, help text.

Display

  • src/ui/widgets/tui_dirlist_detailed.rs — when an entry carries a
    cumulative_size, the detailed dirlist renders it through
    file_size_to_string (so a measured directory shows e.g. 1.2 G
    instead of the item count). Entries that have never been measured
    fall back to existing behavior (count for dirs, raw len for files),
    so nothing changes until the user runs the command.

Sort integration (bug fix in the same PR)

Two follow-ups discovered while testing:

  1. Reload preserved selection state but not the measured size.
    sort triggers a soft reload, which rebuilt entries from disk and
    wiped cumulative_size. src/history.rs now carries the value
    across reload next to the existing selection-state preservation
    loop, so measurements survive any reload or re-sort.
  2. size_sort only compared metadata.len() — directories all
    tied at 0 and the sort order was meaningless for them.
    src/types/option/sort/sort_option.rs now falls back to
    cumulative_size when present, so directories with measured sizes
    sort correctly against each other and against files.

Default keybind

  • config/keymap.toml{ keys = ["d", "c"], commands = ["calculate_cumulative_size"] }. The d, _ chord is already used
    for cut_files (d d) and delete_files (d D), so this slots in
    naturally and matches ranger.

Behavior

Input Result
d c on a single directory Walks the tree, replaces the count in the size column with 1.2 G-style.
d c with N entries selected Measures each; status line shows Cumulative size of N items: ….
d c on a file Just reports the file's size in the status line.
s s after d c Sort by size now respects the measured value (previously dirs all tied).
Navigate away and back / re-sort Measurements are preserved (carried across reload via the parent dir list).

Tradeoffs / known limitations

  • Synchronous. The walker blocks the UI while running. Acceptable
    for the small/medium trees this is usually pointed at; for huge
    trees the natural follow-up is to push the walk onto the existing
    worker thread infrastructure (see src/types/io/) and update the
    entry asynchronously. Kept synchronous in v1 to keep the diff
    reviewable; happy to do the async pass in a follow-up PR if
    preferred.
  • No cache. Re-running d c on the same directory re-walks it.
    A path-keyed cache + invalidation on mtime change would be a
    natural next step.
  • No cancellation. No way to abort an in-progress measurement on
    a huge tree. Falls out of the async refactor above.

BoogerMan2103 and others added 2 commits May 22, 2026 15:57
Mirrors ranger's `dc` — recursively measures the size of selected
entries (or the entry under the cursor) and displays the totals both
inline on each directory and as a status-line message. Bound to `dc`
by default.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
After `calculate_cumulative_size` measured a directory, sorting (which
soft-reloads from disk) wiped the value and the UI fell back to the
item count. Carry the field across reload alongside selection state,
and let `size_sort` fall back to `cumulative_size` so directories with
measured sizes sort against each other and against files.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.

1 participant