diff --git a/src/command/cmd.rs b/src/command/cmd.rs index b7750ac..084b019 100644 --- a/src/command/cmd.rs +++ b/src/command/cmd.rs @@ -1318,9 +1318,8 @@ impl Cmd for CycleAxisAtCursor { "cycle-axis-at-cursor" } fn execute(&self, ctx: &CmdContext) -> Vec> { - let cat_names = ctx.model.category_names(); - if let Some(cat_name) = cat_names.get(ctx.cat_panel_cursor) { - vec![Box::new(effect::CycleAxis(cat_name.to_string()))] + if let Some(cat_name) = ctx.cat_at_cursor() { + vec![Box::new(effect::CycleAxis(cat_name))] } else { vec![] } @@ -1335,10 +1334,9 @@ impl Cmd for OpenItemAddAtCursor { "open-item-add-at-cursor" } fn execute(&self, ctx: &CmdContext) -> Vec> { - let cat_names = ctx.model.category_names(); - if let Some(cat_name) = cat_names.get(ctx.cat_panel_cursor) { + if let Some(cat_name) = ctx.cat_at_cursor() { vec![effect::change_mode(AppMode::ItemAdd { - category: cat_name.to_string(), + category: cat_name, buffer: String::new(), })] } else { @@ -1962,12 +1960,13 @@ impl Cmd for CommitCellEdit { ))); effects.push(effect::mark_dirty()); } - effects.push(effect::change_mode(AppMode::Normal)); - // Advance cursor down (typewriter-style) + // Advance cursor down (typewriter-style) and re-enter edit mode + // at the new cell so the user can continue data entry. let adv = EnterAdvance { cursor: CursorState::from_ctx(ctx), }; effects.extend(adv.execute(ctx)); + effects.push(Box::new(effect::EnterEditAtCursor)); effects } } @@ -2013,18 +2012,19 @@ impl Cmd for CommitCategoryAdd { fn execute(&self, ctx: &CmdContext) -> Vec> { let buf = ctx.buffers.get("category").cloned().unwrap_or_default(); let trimmed = buf.trim().to_string(); - let mut effects: Vec> = Vec::new(); - if !trimmed.is_empty() { - effects.push(Box::new(effect::AddCategory(trimmed.clone()))); - effects.push(effect::mark_dirty()); - effects.push(effect::set_status(format!("Added category \"{trimmed}\""))); + if trimmed.is_empty() { + // Empty → exit category-add mode + return vec![effect::change_mode(AppMode::CategoryPanel)]; } - // Clear buffer for next entry - effects.push(Box::new(effect::SetBuffer { - name: "category".to_string(), - value: String::new(), - })); - effects + vec![ + Box::new(effect::AddCategory(trimmed.clone())), + effect::mark_dirty(), + effect::set_status(format!("Added category \"{trimmed}\"")), + Box::new(effect::SetBuffer { + name: "category".to_string(), + value: String::new(), + }), + ] } } @@ -2038,27 +2038,27 @@ impl Cmd for CommitItemAdd { fn execute(&self, ctx: &CmdContext) -> Vec> { let buf = ctx.buffers.get("item").cloned().unwrap_or_default(); let trimmed = buf.trim().to_string(); - // Get the category from the mode + if trimmed.is_empty() { + // Empty → exit item-add mode + return vec![effect::change_mode(AppMode::CategoryPanel)]; + } let category = if let AppMode::ItemAdd { category, .. } = ctx.mode { category.clone() } else { return vec![]; }; - let mut effects: Vec> = Vec::new(); - if !trimmed.is_empty() { - effects.push(Box::new(effect::AddItem { + vec![ + Box::new(effect::AddItem { category, item: trimmed.clone(), - })); - effects.push(effect::mark_dirty()); - effects.push(effect::set_status(format!("Added \"{trimmed}\""))); - } - // Clear buffer for next entry - effects.push(Box::new(effect::SetBuffer { - name: "item".to_string(), - value: String::new(), - })); - effects + }), + effect::mark_dirty(), + effect::set_status(format!("Added \"{trimmed}\"")), + Box::new(effect::SetBuffer { + name: "item".to_string(), + value: String::new(), + }), + ] } }