Commit 32daffe
feat(tui): show the volume's free disk space in each pane frame (#171)
* feat(tui): show the volume's free disk space in each pane frame
Add a per-pane free-disk-space indicator in the frame's bottom-left (e.g.
`137.0 GiB free`), refreshed on every navigate. Shows the space available to the
current user (respects root-reserved blocks / quotas). Yields to the filter label
when a filter is active; degrades gracefully (truncates) on a very narrow pane.
- cairn-types: `SpaceInfo { total, available }` and a `Caps::SPACE` flag.
- cairn-vfs: `Vfs::space(path) -> Result<Option<SpaceInfo>>`, default `Ok(None)`.
Path-scoped (a backend can straddle mounts).
- cairn-backend-local: implement via the cross-platform `fs4` crate (statvfs on
Unix, GetDiskFreeSpaceEx on Windows) in spawn_blocking — no unsafe/ADR needed.
Advertises `Caps::SPACE`.
- Other backends inherit the `None` default (object stores/containers have no
meaningful free space). SSH/SFTP via `statvfs@openssh.com` is a tracked
follow-up (#170) — russh-sftp only exposes it on the raw session.
- cairn-core: `PaneState.space`, cleared on navigate; `AppEvent::SpaceFetched`
applied with the same conn/dir staleness guard as `Listed`.
- cairn: the runtime fetches space as a non-blocking sibling of each `List` and
emits `SpaceFetched` — so the reducer still emits a single effect (no test churn).
- cairn-plugin: `SPACE` is host-only (no WIT counterpart yet), like `LOCAL_PATH`.
Tests: local `space()` (plausible totals, advertises the cap); reducer
(stores on match, ignores stale, cleared on navigate); a pane-free-space scenario
+ snapshots. README + CHANGELOG.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(tui): hide the free-space label when it would clip; gate the fetch on Caps::SPACE
Review fixes:
- Narrow-pane clipping (bug-bot): on a half-width pane the free-space label was
clipped mid-word to a misleading unitless number (e.g. "137.0"). Only show it
when it fits alongside the sort label (measured against the pane width);
otherwise omit it entirely. Wide panes render the full "137.0 GiB free".
- Gate the runtime's space-fetch on `Caps::SPACE` (code-review): skip the task,
the space() call, and the no-op SpaceFetched event for backends that can't
report space (object stores, containers) — no pointless work.
- Log a debug line on a space() error instead of silently swallowing it.
Tests: free-space label shows on a wide pane and is omitted (not clipped) on a
narrow one. Snapshots regenerated (40x12 now omits the label).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent 6abbf7f commit 32daffe
18 files changed
Lines changed: 331 additions & 12 deletions
File tree
- crates
- cairn-backend-local
- src
- cairn-core/src
- cairn-plugin/src
- cairn-tui/src
- snapshots
- cairn-types/src
- cairn-vfs/src
- cairn/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
12 | 19 | | |
13 | 20 | | |
14 | 21 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
89 | 89 | | |
90 | 90 | | |
91 | 91 | | |
92 | | - | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
93 | 95 | | |
94 | 96 | | |
95 | 97 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
20 | 23 | | |
21 | | - | |
| 24 | + | |
22 | 25 | | |
23 | 26 | | |
24 | 27 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
| 10 | + | |
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
| 30 | + | |
| 31 | + | |
31 | 32 | | |
32 | 33 | | |
33 | 34 | | |
| |||
251 | 252 | | |
252 | 253 | | |
253 | 254 | | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
254 | 275 | | |
255 | 276 | | |
256 | 277 | | |
| |||
431 | 452 | | |
432 | 453 | | |
433 | 454 | | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
434 | 478 | | |
435 | 479 | | |
436 | 480 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
198 | 198 | | |
199 | 199 | | |
200 | 200 | | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
201 | 214 | | |
202 | 215 | | |
203 | 216 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
257 | 257 | | |
258 | 258 | | |
259 | 259 | | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
260 | 264 | | |
261 | 265 | | |
262 | 266 | | |
| |||
290 | 294 | | |
291 | 295 | | |
292 | 296 | | |
| 297 | + | |
293 | 298 | | |
294 | 299 | | |
295 | 300 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3740 | 3740 | | |
3741 | 3741 | | |
3742 | 3742 | | |
| 3743 | + | |
| 3744 | + | |
| 3745 | + | |
3743 | 3746 | | |
3744 | 3747 | | |
3745 | 3748 | | |
| |||
3753 | 3756 | | |
3754 | 3757 | | |
3755 | 3758 | | |
| 3759 | + | |
3756 | 3760 | | |
3757 | 3761 | | |
3758 | 3762 | | |
| |||
3816 | 3820 | | |
3817 | 3821 | | |
3818 | 3822 | | |
| 3823 | + | |
| 3824 | + | |
| 3825 | + | |
| 3826 | + | |
| 3827 | + | |
| 3828 | + | |
| 3829 | + | |
| 3830 | + | |
| 3831 | + | |
| 3832 | + | |
| 3833 | + | |
| 3834 | + | |
| 3835 | + | |
| 3836 | + | |
3819 | 3837 | | |
3820 | 3838 | | |
3821 | 3839 | | |
| |||
7115 | 7133 | | |
7116 | 7134 | | |
7117 | 7135 | | |
| 7136 | + | |
| 7137 | + | |
| 7138 | + | |
| 7139 | + | |
| 7140 | + | |
| 7141 | + | |
| 7142 | + | |
| 7143 | + | |
| 7144 | + | |
| 7145 | + | |
| 7146 | + | |
| 7147 | + | |
| 7148 | + | |
| 7149 | + | |
| 7150 | + | |
| 7151 | + | |
| 7152 | + | |
| 7153 | + | |
| 7154 | + | |
| 7155 | + | |
| 7156 | + | |
| 7157 | + | |
| 7158 | + | |
| 7159 | + | |
| 7160 | + | |
| 7161 | + | |
| 7162 | + | |
| 7163 | + | |
| 7164 | + | |
| 7165 | + | |
| 7166 | + | |
| 7167 | + | |
| 7168 | + | |
| 7169 | + | |
| 7170 | + | |
| 7171 | + | |
| 7172 | + | |
| 7173 | + | |
| 7174 | + | |
| 7175 | + | |
| 7176 | + | |
| 7177 | + | |
| 7178 | + | |
| 7179 | + | |
| 7180 | + | |
| 7181 | + | |
| 7182 | + | |
| 7183 | + | |
| 7184 | + | |
| 7185 | + | |
| 7186 | + | |
| 7187 | + | |
| 7188 | + | |
| 7189 | + | |
| 7190 | + | |
7118 | 7191 | | |
7119 | 7192 | | |
7120 | 7193 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
749 | 749 | | |
750 | 750 | | |
751 | 751 | | |
752 | | - | |
753 | | - | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
754 | 755 | | |
755 | | - | |
| 756 | + | |
756 | 757 | | |
757 | 758 | | |
758 | 759 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1605 | 1605 | | |
1606 | 1606 | | |
1607 | 1607 | | |
1608 | | - | |
1609 | | - | |
| 1608 | + | |
| 1609 | + | |
| 1610 | + | |
1610 | 1611 | | |
1611 | 1612 | | |
1612 | 1613 | | |
1613 | 1614 | | |
1614 | | - | |
| 1615 | + | |
| 1616 | + | |
| 1617 | + | |
1615 | 1618 | | |
1616 | 1619 | | |
1617 | 1620 | | |
| 1621 | + | |
| 1622 | + | |
| 1623 | + | |
| 1624 | + | |
| 1625 | + | |
| 1626 | + | |
| 1627 | + | |
| 1628 | + | |
| 1629 | + | |
| 1630 | + | |
| 1631 | + | |
| 1632 | + | |
| 1633 | + | |
| 1634 | + | |
1618 | 1635 | | |
1619 | 1636 | | |
1620 | 1637 | | |
| |||
0 commit comments