feat(command): add smart edit-or-drill for aggregated cells

Introduce EditOrDrill command that intelligently handles
editing based on cell type. When cursor is on an aggregated
pivot cell (categories on Axis::None, no records mode), it
drills into the cell. Otherwise, it enters edit mode with
the current displayed value.

The 'i' and 'a' keys now trigger edit-or-drill instead of
enter-edit-mode. Aggregated cells are styled in italic to
signal that drilling is required for editing.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
This commit is contained in:
Edward Langley
2026-04-05 12:35:40 -07:00
parent 94bc3ca282
commit ab92775357
3 changed files with 48 additions and 4 deletions

View File

@ -633,6 +633,40 @@ impl Cmd for EnterEditMode {
}
}
/// Smart dispatch for i/a: if the cursor is on an aggregated pivot cell
/// (categories on `Axis::None`, no records mode), drill into it instead of
/// editing. Otherwise enter edit mode with the current displayed value.
#[derive(Debug)]
pub struct EditOrDrill;
impl Cmd for EditOrDrill {
fn name(&self) -> &'static str {
"edit-or-drill"
}
fn execute(&self, ctx: &CmdContext) -> Vec<Box<dyn Effect>> {
let is_aggregated = ctx.records_col.is_none() && !ctx.none_cats.is_empty();
if is_aggregated {
let Some(key) = ctx.cell_key.clone() else {
return vec![effect::set_status(
"cannot drill — no cell at cursor",
)];
};
return DrillIntoCell { key }.execute(ctx);
}
// Edit path: prefer records display value (includes pending edits),
// else the underlying cell's stored value.
let initial_value = if let Some(v) = &ctx.records_value {
v.clone()
} else {
ctx.cell_key
.as_ref()
.and_then(|k| ctx.model.get_cell(k).cloned())
.map(|v| v.to_string())
.unwrap_or_default()
};
EnterEditMode { initial_value }.execute(ctx)
}
}
/// Typewriter-style advance: move down, wrap to top of next column at bottom.
#[derive(Debug)]
pub struct EnterAdvance {
@ -2341,6 +2375,7 @@ pub fn default_registry() -> CmdRegistry {
}))
},
);
r.register_nullary(|| Box::new(EditOrDrill));
r.register_nullary(|| Box::new(EnterExportPrompt));
r.register_nullary(|| Box::new(EnterFormulaEdit));
r.register_nullary(|| Box::new(EnterTileSelect));