feat: group-aware grid rendering and hide/show item

Builds out two half-finished view features:

Group collapse:
- AxisEntry enum distinguishes GroupHeader from DataItem on grid axes
- expand_category() emits group headers and filters collapsed items
- Grid renders inline group header rows with ▼/▶ indicator
- `z` keybinding toggles collapse of nearest group above cursor

Hide/show item:
- Restore show_item() (was commented out alongside hide_item)
- Add HideItem / ShowItem commands and dispatch
- `H` keybinding hides the current row item
- `:show-item <cat> <item>` command to restore hidden items
- Restore silenced test assertions for hide/show round-trip

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Edward Langley
2026-03-31 00:07:11 -07:00
parent 3cf64b40a3
commit 37584670eb
8 changed files with 1735 additions and 555 deletions

View File

@ -23,9 +23,11 @@ impl Widget for HelpWidget {
let inner = block.inner(popup_area);
block.render(popup_area, buf);
let head = Style::default().fg(Color::Blue).add_modifier(Modifier::BOLD);
let key = Style::default().fg(Color::Cyan);
let dim = Style::default().fg(Color::DarkGray);
let head = Style::default()
.fg(Color::Blue)
.add_modifier(Modifier::BOLD);
let key = Style::default().fg(Color::Cyan);
let dim = Style::default().fg(Color::DarkGray);
let norm = Style::default();
// (key_col, desc_col, style)
@ -51,25 +53,51 @@ impl Widget for HelpWidget {
("", "", norm),
("Panels", "", head),
(" F", "Toggle Formula panel (n:new d:del)", key),
(" C", "Toggle Category panel (n:new-cat a:add-items)", key),
(
" C",
"Toggle Category panel (n:new-cat a:add-items)",
key,
),
(" N", "New category quick-add (from anywhere)", key),
(" V", "Toggle View panel (n:new d:del Enter:switch)", key),
(
" V",
"Toggle View panel (n:new d:del Enter:switch)",
key,
),
(" Tab", "Focus next open panel", key),
("", "", norm),
("Pivot / Tiles", "", head),
("Pivot / Tiles / Groups", "", head),
(" z", "Toggle collapse nearest group above cursor", key),
(
" H",
"Hide current row item (:show-item cat item to restore)",
key,
),
(" T", "Tile-select mode", key),
(" ← h / → l", "Select previous/next tile", dim),
(" Space / Enter", "Cycle axis (Row→Col→Page)", dim),
(" r / c / p", "Set axis to Row / Col / Page", dim),
("", "", norm),
("Command line ( : )", "", head),
(" :q :q! :wq ZZ", "Quit / force-quit / save+quit", key),
(
" :q :q! :wq ZZ",
"Quit / force-quit / save+quit",
key,
),
(" :w [path]", "Save (path optional)", key),
(" :import <path.json>", "Open JSON import wizard", key),
(" :export [path.csv]", "Export active view to CSV", key),
(" :add-cat <name>", "Add a category", key),
(" :add-item <cat> <item>", "Add one item to a category", key),
(" :add-items <cat> a b c…", "Add multiple items at once", key),
(
" :add-item <cat> <item>",
"Add one item to a category",
key,
),
(
" :add-items <cat> a b c…",
"Add multiple items at once",
key,
),
(" :formula <cat> <Name=expr>", "Add a formula", key),
(" :add-view [name]", "Create a new view", key),
("", "", norm),
@ -79,7 +107,9 @@ impl Widget for HelpWidget {
let key_col_w = 32usize;
for (i, (k, d, style)) in rows.iter().enumerate() {
if i >= inner.height as usize { break; }
if i >= inner.height as usize {
break;
}
let y = inner.y + i as u16;
if d.is_empty() {
buf.set_string(inner.x, y, k, *style);