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

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::view::Axis;
use serde::{Deserialize, Serialize};
/// All commands that can mutate a Model.
///
@ -15,7 +15,11 @@ pub enum Command {
AddItem { category: String, item: String },
/// Add an item inside a named group.
AddItemInGroup { category: String, item: String, group: String },
AddItemInGroup {
category: String,
item: String,
group: String,
},
/// Set a cell value. `coords` is a list of `[category, item]` pairs.
SetCell {
@ -30,10 +34,16 @@ pub enum Command {
/// Add or replace a formula.
/// `raw` is the full formula string, e.g. "Profit = Revenue - Cost".
/// `target_category` names the category that owns the formula target.
AddFormula { raw: String, target_category: String },
AddFormula {
raw: String,
target_category: String,
},
/// Remove a formula by its target name and category.
RemoveFormula { target: String, target_category: String },
RemoveFormula {
target: String,
target_category: String,
},
/// Create a new view.
CreateView { name: String },
@ -53,6 +63,12 @@ pub enum Command {
/// Toggle collapse of a group in the active view.
ToggleGroup { category: String, group: String },
/// Hide an item in the active view.
HideItem { category: String, item: String },
/// Show (un-hide) an item in the active view.
ShowItem { category: String, item: String },
/// Save the model to a file path.
Save { path: String },
@ -88,12 +104,21 @@ pub struct CommandResult {
impl CommandResult {
pub fn ok() -> Self {
Self { ok: true, message: None }
Self {
ok: true,
message: None,
}
}
pub fn ok_msg(msg: impl Into<String>) -> Self {
Self { ok: true, message: Some(msg.into()) }
Self {
ok: true,
message: Some(msg.into()),
}
}
pub fn err(msg: impl Into<String>) -> Self {
Self { ok: false, message: Some(msg.into()) }
Self {
ok: false,
message: Some(msg.into()),
}
}
}