From 2be1eeae5dde82915f171c8be17b2d01da0756d1 Mon Sep 17 00:00:00 2001 From: Edward Langley Date: Sat, 4 Apr 2026 10:42:25 -0700 Subject: [PATCH] refactor(app): remove legacy command execution code Remove unused imports for legacy code that is no longer needed. Delete execute_command function that handled :q, :w, :import commands via direct AppMode matching. Delete handle_wizard_key function and associated fallback logic for modes not yet migrated to keymaps. These are now handled by the new keymap-based approach. Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M) --- src/ui/app.rs | 357 +------------------------------------------------- 1 file changed, 3 insertions(+), 354 deletions(-) diff --git a/src/ui/app.rs b/src/ui/app.rs index 4fcaaeb..4e718fd 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -1,18 +1,16 @@ use anyhow::Result; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; use std::collections::HashMap; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::Arc; use std::time::{Duration, Instant}; use crate::command::cmd::CmdContext; use crate::command::keymap::{Keymap, KeymapSet}; -use crate::command::{self, Command}; -use crate::import::wizard::{ImportWizard, WizardStep}; -use crate::model::cell::{CellKey, CellValue}; +use crate::import::wizard::ImportWizard; +use crate::model::cell::CellValue; use crate::model::Model; use crate::persistence; -use crate::view::GridLayout; #[derive(Debug, Clone, PartialEq)] pub enum AppMode { @@ -159,355 +157,6 @@ impl App { }; if let Some(effects) = effects { self.apply_effects(effects); - return Ok(()); - } - - // Fallback: old-style handlers for modes not yet migrated to keymaps - match &self.mode.clone() { - AppMode::CommandMode { .. } => { - // Enter key (execute_command) is still handled here. - // Esc, Backspace, Char are handled by the keymap above. - if key.code == KeyCode::Enter { - let buf = if let AppMode::CommandMode { buffer } = &self.mode { - buffer.clone() - } else { - return Ok(()); - }; - // Also read from buffers map if the keymap was appending there - let cmd_buf = self.buffers.get("command").cloned().unwrap_or(buf); - self.execute_command(&cmd_buf)?; - } - } - AppMode::ImportWizard => self.handle_wizard_key(key)?, - _ => {} // All other modes handled by keymap - } - Ok(()) - } - - fn execute_command(&mut self, raw: &str) -> Result<()> { - let raw = raw.trim(); - let (cmd_name, rest) = raw - .split_once(char::is_whitespace) - .map(|(c, r)| (c, r.trim())) - .unwrap_or((raw, "")); - - // Default: return to Normal. Commands that open a new mode override this. - self.mode = AppMode::Normal; - - match cmd_name { - "q" | "quit" => { - if self.dirty { - self.status_msg = - "Unsaved changes. Use :q! to force quit or :wq to save+quit.".to_string(); - } else { - self.mode = AppMode::Quit; - } - } - "q!" => { - self.mode = AppMode::Quit; - } - "w" | "write" => { - if rest.is_empty() { - self.save()?; - } else { - let path = PathBuf::from(rest); - persistence::save(&self.model, &path)?; - self.file_path = Some(path.clone()); - self.dirty = false; - self.status_msg = format!("Saved to {}", path.display()); - } - } - "wq" | "x" => { - self.save()?; - self.mode = AppMode::Quit; - } - "import" => { - if rest.is_empty() { - self.status_msg = "Usage: :import ".to_string(); - } else { - match std::fs::read_to_string(rest) { - Ok(content) => match serde_json::from_str::(&content) { - Ok(json) => { - self.wizard = Some(ImportWizard::new(json)); - self.mode = AppMode::ImportWizard; - } - Err(e) => { - self.status_msg = format!("JSON parse error: {e}"); - } - }, - Err(e) => { - self.status_msg = format!("Cannot read file: {e}"); - } - } - } - } - "export" => { - let path = if rest.is_empty() { "export.csv" } else { rest }; - let view_name = self.model.active_view.clone(); - match persistence::export_csv(&self.model, &view_name, Path::new(path)) { - Ok(_) => { - self.status_msg = format!("Exported to {path}"); - } - Err(e) => { - self.status_msg = format!("Export error: {e}"); - } - } - } - "add-cat" | "add-category" | "cat" => { - if rest.is_empty() { - self.status_msg = "Usage: :add-cat ".to_string(); - } else { - let result = command::dispatch( - &mut self.model, - &Command::AddCategory { - name: rest.to_string(), - }, - ); - self.status_msg = result.message.unwrap_or_default(); - self.dirty = true; - } - } - "add-item" | "item" => { - // :add-item - let mut parts = rest.splitn(2, char::is_whitespace); - let cat = parts.next().unwrap_or("").trim(); - let item = parts.next().unwrap_or("").trim(); - if cat.is_empty() || item.is_empty() { - self.status_msg = "Usage: :add-item ".to_string(); - } else { - let result = command::dispatch( - &mut self.model, - &Command::AddItem { - category: cat.to_string(), - item: item.to_string(), - }, - ); - self.status_msg = result.message.unwrap_or_else(|| "Item added".to_string()); - self.dirty = true; - } - } - "add-items" | "items" => { - // :add-items item1 item2 item3 ... - let mut parts = rest.splitn(2, char::is_whitespace); - let cat = parts.next().unwrap_or("").trim().to_string(); - let items_str = parts.next().unwrap_or("").trim().to_string(); - if cat.is_empty() || items_str.is_empty() { - self.status_msg = "Usage: :add-items item1 item2 ...".to_string(); - } else { - let items: Vec<&str> = items_str.split_whitespace().collect(); - let count = items.len(); - for item in &items { - command::dispatch( - &mut self.model, - &Command::AddItem { - category: cat.clone(), - item: item.to_string(), - }, - ); - } - self.status_msg = format!("Added {count} items to \"{cat}\"."); - self.dirty = true; - } - } - "formula" | "add-formula" => { - if rest.is_empty() { - self.formula_panel_open = true; - self.mode = AppMode::FormulaPanel; - } else { - // :formula - let mut parts = rest.splitn(2, char::is_whitespace); - let cat = parts.next().unwrap_or("").trim(); - let formula = parts.next().unwrap_or("").trim(); - if cat.is_empty() || formula.is_empty() { - self.status_msg = "Usage: :formula ".to_string(); - } else { - let result = command::dispatch( - &mut self.model, - &Command::AddFormula { - raw: formula.to_string(), - target_category: cat.to_string(), - }, - ); - self.status_msg = result - .message - .unwrap_or_else(|| "Formula added".to_string()); - self.dirty = true; - } - } - } - "add-view" | "view" => { - let name = if rest.is_empty() { - format!("View {}", self.model.views.len() + 1) - } else { - rest.to_string() - }; - command::dispatch(&mut self.model, &Command::CreateView { name: name.clone() }); - let _ = command::dispatch(&mut self.model, &Command::SwitchView { name }); - self.dirty = true; - } - "set-format" | "fmt" => { - // :set-format e.g. ",.2" ",.0" ".2" - // "," = comma separators; ".N" = N decimal places - if rest.is_empty() { - self.status_msg = "Usage: :set-format e.g. ,.0 ,.2 .4".to_string(); - } else { - self.model.active_view_mut().number_format = rest.to_string(); - self.status_msg = format!("Number format set to '{rest}'"); - self.dirty = true; - } - } - "show-item" | "show" => { - // :show-item - let mut parts = rest.splitn(2, char::is_whitespace); - let cat = parts.next().unwrap_or("").trim(); - let item = parts.next().unwrap_or("").trim(); - if cat.is_empty() || item.is_empty() { - self.status_msg = "Usage: :show-item ".to_string(); - } else { - let result = command::dispatch( - &mut self.model, - &Command::ShowItem { - category: cat.to_string(), - item: item.to_string(), - }, - ); - self.status_msg = result - .message - .unwrap_or_else(|| format!("Showed \"{item}\" in \"{cat}\"")); - self.dirty = true; - } - } - "help" | "h" => { - self.mode = AppMode::Help; - } - "" => {} // just pressed Enter with empty buffer - other => { - self.status_msg = format!("Unknown command: :{other} (try :help)"); - } - } - Ok(()) - } - - fn handle_wizard_key(&mut self, key: KeyEvent) -> Result<()> { - if let Some(wizard) = &mut self.wizard { - match &wizard.step.clone() { - WizardStep::Preview => match key.code { - KeyCode::Enter | KeyCode::Char(' ') => wizard.advance(), - KeyCode::Esc => { - self.mode = AppMode::Normal; - self.wizard = None; - } - _ => {} - }, - WizardStep::SelectArrayPath => match key.code { - KeyCode::Up | KeyCode::Char('k') => wizard.move_cursor(-1), - KeyCode::Down | KeyCode::Char('j') => wizard.move_cursor(1), - KeyCode::Enter => wizard.confirm_path(), - KeyCode::Esc => { - self.mode = AppMode::Normal; - self.wizard = None; - } - _ => {} - }, - WizardStep::ReviewProposals => match key.code { - KeyCode::Up | KeyCode::Char('k') => wizard.move_cursor(-1), - KeyCode::Down | KeyCode::Char('j') => wizard.move_cursor(1), - KeyCode::Char(' ') => wizard.toggle_proposal(), - KeyCode::Char('c') => wizard.cycle_proposal_kind(), - KeyCode::Enter => wizard.advance(), - KeyCode::Esc => { - self.mode = AppMode::Normal; - self.wizard = None; - } - _ => {} - }, - WizardStep::ConfigureDates => match key.code { - KeyCode::Up | KeyCode::Char('k') => wizard.move_cursor(-1), - KeyCode::Down | KeyCode::Char('j') => wizard.move_cursor(1), - KeyCode::Char(' ') => wizard.toggle_date_component(), - KeyCode::Enter => wizard.advance(), - KeyCode::Esc => { - self.mode = AppMode::Normal; - self.wizard = None; - } - _ => {} - }, - WizardStep::DefineFormulas => { - if wizard.formula_editing { - match key.code { - KeyCode::Enter => wizard.confirm_formula(), - KeyCode::Esc => wizard.cancel_formula_edit(), - KeyCode::Backspace => wizard.pop_formula_char(), - KeyCode::Char(c) => wizard.push_formula_char(c), - _ => {} - } - } else { - match key.code { - KeyCode::Char('n') => wizard.start_formula_edit(), - KeyCode::Char('d') => wizard.delete_formula(), - KeyCode::Up | KeyCode::Char('k') => wizard.move_cursor(-1), - KeyCode::Down | KeyCode::Char('j') => wizard.move_cursor(1), - KeyCode::Enter => wizard.advance(), - KeyCode::Esc => { - self.mode = AppMode::Normal; - self.wizard = None; - } - _ => {} - } - } - } - WizardStep::NameModel => match key.code { - KeyCode::Char(c) => wizard.push_name_char(c), - KeyCode::Backspace => wizard.pop_name_char(), - KeyCode::Enter => match wizard.build_model() { - Ok(mut model) => { - model.normalize_view_state(); - self.model = model; - self.formula_cursor = 0; - self.dirty = true; - self.status_msg = - "Import successful! Press :w to save.".to_string(); - self.mode = AppMode::Normal; - self.wizard = None; - } - Err(e) => { - if let Some(w) = &mut self.wizard { - w.message = Some(format!("Error: {e}")); - } - } - }, - KeyCode::Esc => { - self.mode = AppMode::Normal; - self.wizard = None; - } - _ => {} - }, - WizardStep::Done => { - self.mode = AppMode::Normal; - self.wizard = None; - } - } - } - Ok(()) - } - - // ── Cell key resolution ────────────────────────────────────────────────── - - pub fn selected_cell_key(&self) -> Option { - let view = self.model.active_view(); - let (sel_row, sel_col) = view.selected; - GridLayout::new(&self.model, view).cell_key(sel_row, sel_col) - } - - // ── Persistence ────────────────────────────────────────────────────────── - - pub fn save(&mut self) -> Result<()> { - if let Some(path) = &self.file_path.clone() { - persistence::save(&self.model, path)?; - self.dirty = false; - self.status_msg = format!("Saved to {}", path.display()); - } else { - self.status_msg = "No file path — use :w to save.".to_string(); } Ok(()) }