Add quick-add mode for categories
N (from anywhere) or n (in Category panel) opens an inline prompt to add categories one after another without typing :add-cat each time. - Yellow border + prompt distinguishes it from item-add (green) - Enter / Tab adds the category and clears the buffer, staying open - Esc returns to the category list - Cursor automatically moves to the newly added category Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@ -18,6 +18,8 @@ pub enum AppMode {
|
||||
FormulaEdit { buffer: String },
|
||||
FormulaPanel,
|
||||
CategoryPanel,
|
||||
/// Quick-add a new category: Enter adds and stays open, Esc closes.
|
||||
CategoryAdd { buffer: String },
|
||||
/// Quick-add items to `category`: Enter adds and stays open, Esc closes.
|
||||
ItemAdd { category: String, buffer: String },
|
||||
ViewPanel,
|
||||
@ -89,6 +91,7 @@ impl App {
|
||||
AppMode::FormulaEdit { .. } => { self.handle_formula_edit_key(key)?; }
|
||||
AppMode::FormulaPanel => { self.handle_formula_panel_key(key)?; }
|
||||
AppMode::CategoryPanel => { self.handle_category_panel_key(key)?; }
|
||||
AppMode::CategoryAdd { .. } => { self.handle_category_add_key(key)?; }
|
||||
AppMode::ItemAdd { .. } => { self.handle_item_add_key(key)?; }
|
||||
AppMode::ViewPanel => { self.handle_view_panel_key(key)?; }
|
||||
AppMode::TileSelect { .. } => { self.handle_tile_select_key(key)?; }
|
||||
@ -266,6 +269,12 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
// N = quick-add a new category (opens Category panel in add mode)
|
||||
(KeyCode::Char('N'), _) => {
|
||||
self.category_panel_open = true;
|
||||
self.mode = AppMode::CategoryAdd { buffer: String::new() };
|
||||
}
|
||||
|
||||
// ── Tile movement ──────────────────────────────────────────────
|
||||
// T = enter tile select mode (single key, no Ctrl needed)
|
||||
(KeyCode::Char('T'), _) => {
|
||||
@ -617,7 +626,11 @@ impl App {
|
||||
}
|
||||
}
|
||||
}
|
||||
// a / o — open quick-add mode for the selected category
|
||||
// n — add a new category
|
||||
KeyCode::Char('n') => {
|
||||
self.mode = AppMode::CategoryAdd { buffer: String::new() };
|
||||
}
|
||||
// a / o — open quick-add items mode for the selected category
|
||||
KeyCode::Char('a') | KeyCode::Char('o') => {
|
||||
if let Some(cat_name) = cat_names.get(self.cat_panel_cursor) {
|
||||
self.mode = AppMode::ItemAdd {
|
||||
@ -625,7 +638,7 @@ impl App {
|
||||
buffer: String::new(),
|
||||
};
|
||||
} else {
|
||||
self.status_msg = "No category selected. Add a category first with :add-cat <name>.".to_string();
|
||||
self.status_msg = "No category selected. Press n to add a category first.".to_string();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@ -633,6 +646,45 @@ impl App {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_category_add_key(&mut self, key: KeyEvent) -> Result<()> {
|
||||
match key.code {
|
||||
KeyCode::Esc => {
|
||||
self.mode = AppMode::CategoryPanel;
|
||||
self.status_msg = String::new();
|
||||
}
|
||||
KeyCode::Enter | KeyCode::Tab => {
|
||||
let buf = if let AppMode::CategoryAdd { buffer } = &self.mode {
|
||||
buffer.trim().to_string()
|
||||
} else { return Ok(()); };
|
||||
|
||||
if !buf.is_empty() {
|
||||
let result = command::dispatch(&mut self.model, &Command::AddCategory { name: buf.clone() });
|
||||
if result.ok {
|
||||
// Move cursor to the new category
|
||||
self.cat_panel_cursor = self.model.categories.len().saturating_sub(1);
|
||||
let count = self.model.categories.len();
|
||||
self.status_msg = format!("Added category \"{buf}\" ({count} total). Enter to add more, Esc to finish.");
|
||||
self.dirty = true;
|
||||
} else {
|
||||
self.status_msg = result.message.unwrap_or_default();
|
||||
}
|
||||
}
|
||||
// Stay in CategoryAdd for the next entry
|
||||
if let AppMode::CategoryAdd { ref mut buffer } = self.mode {
|
||||
buffer.clear();
|
||||
}
|
||||
}
|
||||
KeyCode::Char(c) => {
|
||||
if let AppMode::CategoryAdd { ref mut buffer } = self.mode { buffer.push(c); }
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
if let AppMode::CategoryAdd { ref mut buffer } = self.mode { buffer.pop(); }
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_item_add_key(&mut self, key: KeyEvent) -> Result<()> {
|
||||
match key.code {
|
||||
KeyCode::Esc => {
|
||||
@ -1013,8 +1065,9 @@ impl App {
|
||||
AppMode::Editing { .. } => "Enter:commit Esc:cancel",
|
||||
AppMode::FormulaPanel => "n:new d:delete jk:nav Esc:back",
|
||||
AppMode::FormulaEdit { .. } => "Enter:save Esc:cancel — type: Name = expression",
|
||||
AppMode::CategoryPanel => "jk:nav Space:cycle-axis a:add-items Esc:back",
|
||||
AppMode::ItemAdd { category, .. } => "Enter:add & continue Tab:same Esc:done",
|
||||
AppMode::CategoryPanel => "jk:nav Space:cycle-axis n:new-cat a:add-items Esc:back",
|
||||
AppMode::CategoryAdd { .. } => "Enter:add & continue Tab:same Esc:done — type a category name",
|
||||
AppMode::ItemAdd { .. } => "Enter:add & continue Tab:same Esc:done — type an item name",
|
||||
AppMode::ViewPanel => "jk:nav Enter:switch n:new d:delete Esc:back",
|
||||
AppMode::TileSelect { .. } => "hl:select Enter:cycle r/c/p:set-axis Esc:back",
|
||||
AppMode::CommandMode { .. } => ":q quit :w save :import :add-cat :formula :help",
|
||||
|
||||
Reference in New Issue
Block a user