From a45390b7a90631985ccbbe7b5ca714852f4d8220 Mon Sep 17 00:00:00 2001 From: Edward Langley Date: Sat, 4 Apr 2026 10:57:37 -0700 Subject: [PATCH] refactor(command): rename commands and extract panel/axis parsers Rename several commands for consistency: - save -> save-as (SaveAsCmd) - save-cmd -> save (SaveCmd) - enter-search -> search (EnterSearchMode) - enter-edit -> enter-edit-mode (EnterEditMode) - exit-search -> exit-search-mode (ExitSearchMode) Add new commands: - search-or-category-add - search-append-char - search-pop-char - toggle-panel-and-focus - toggle-panel-visibility - command-mode-backspace Extract parse_panel() and parse_axis() helper functions to replace repeated match statements. Update documentation comments to reflect quasi-lisp syntax instead of Forth-style. Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M) --- src/command/cmd.rs | 95 +++++++++++++++++++++++++------------------- src/command/mod.rs | 2 +- src/command/parse.rs | 2 +- 3 files changed, 56 insertions(+), 43 deletions(-) diff --git a/src/command/cmd.rs b/src/command/cmd.rs index f59eb68..be1de89 100644 --- a/src/command/cmd.rs +++ b/src/command/cmd.rs @@ -1786,8 +1786,8 @@ effect_cmd!( effect_cmd!( SaveAsCmd, - "save", - |args: &[String]| require_args("save", args, 1), + "save-as", + |args: &[String]| require_args("save-as", args, 1), |args: &Vec, _ctx: &CmdContext| -> Vec> { vec![Box::new(effect::SaveAs(std::path::PathBuf::from( &args[0], @@ -1836,11 +1836,12 @@ effect_cmd!( } ); -/// Build the default command registry with all parseable commands. +/// Build the default command registry with all commands. +/// Registry names MUST match the `Cmd::name()` return value. pub fn default_registry() -> CmdRegistry { let mut r = CmdRegistry::new(); - // Model mutations (effect_cmd! wrappers) + // ── Model mutations (effect_cmd! wrappers) ─────────────────────────── r.register("add-category", AddCategoryCmd::parse); r.register("add-item", AddItemCmd::parse); r.register("add-item-in-group", AddItemInGroupCmd::parse); @@ -1856,12 +1857,12 @@ pub fn default_registry() -> CmdRegistry { r.register("toggle-group", ToggleGroupCmd::parse); r.register("hide-item", HideItemCmd::parse); r.register("show-item", ShowItemCmd::parse); - r.register("save", SaveAsCmd::parse); + r.register("save-as", SaveAsCmd::parse); r.register("load", LoadModelCmd::parse); r.register("export-csv", ExportCsvCmd::parse); r.register("import-json", ImportJsonCmd::parse); - // Navigation (zero-arg or simple-arg commands that already exist as Cmd structs) + // ── Navigation ─────────────────────────────────────────────────────── r.register("move-selection", |args| { require_args("move-selection", args, 2)?; let dr = args[0].parse::().map_err(|e| e.to_string())?; @@ -1879,22 +1880,22 @@ pub fn default_registry() -> CmdRegistry { }); r.register("enter-advance", |_| Ok(Box::new(EnterAdvance))); - // Cell operations + // ── Cell operations ────────────────────────────────────────────────── r.register("yank", |_| Ok(Box::new(YankCell))); r.register("paste", |_| Ok(Box::new(PasteCell))); r.register("clear-selected-cell", |_| Ok(Box::new(ClearSelectedCell))); - // View operations + // ── View / page ────────────────────────────────────────────────────── r.register("transpose", |_| Ok(Box::new(TransposeAxes))); r.register("page-next", |_| Ok(Box::new(PageNext))); r.register("page-prev", |_| Ok(Box::new(PagePrev))); - // Mode changes + // ── Mode changes ───────────────────────────────────────────────────── r.register("force-quit", |_| Ok(Box::new(ForceQuit))); r.register("save-and-quit", |_| Ok(Box::new(SaveAndQuit))); - r.register("save-cmd", |_| Ok(Box::new(SaveCmd))); - r.register("enter-search", |_| Ok(Box::new(EnterSearchMode))); - r.register("enter-edit", |_| Ok(Box::new(EnterEditMode))); + r.register("save", |_| Ok(Box::new(SaveCmd))); + r.register("search", |_| Ok(Box::new(EnterSearchMode))); + r.register("enter-edit-mode", |_| Ok(Box::new(EnterEditMode))); r.register("enter-export-prompt", |_| Ok(Box::new(EnterExportPrompt))); r.register("enter-formula-edit", |_| Ok(Box::new(EnterFormulaEdit))); r.register("enter-tile-select", |_| Ok(Box::new(EnterTileSelect))); @@ -1913,33 +1914,31 @@ pub fn default_registry() -> CmdRegistry { Ok(Box::new(EnterMode(mode))) }); - // Search + // ── Search ─────────────────────────────────────────────────────────── r.register("search-navigate", |args| { let forward = args.first().map(|s| s != "backward").unwrap_or(true); Ok(Box::new(SearchNavigate(forward))) }); - r.register("exit-search", |_| Ok(Box::new(ExitSearchMode))); + r.register("search-or-category-add", |_| Ok(Box::new(SearchOrCategoryAdd))); + r.register("exit-search-mode", |_| Ok(Box::new(ExitSearchMode))); + r.register("search-append-char", |_| Ok(Box::new(SearchAppendChar))); + r.register("search-pop-char", |_| Ok(Box::new(SearchPopChar))); - // Panel operations - r.register("toggle-panel", |args| { - require_args("toggle-panel", args, 1)?; - let panel = match args[0].as_str() { - "formula" => effect::Panel::Formula, - "category" => effect::Panel::Category, - "view" => effect::Panel::View, - other => return Err(format!("Unknown panel: {other}")), - }; + // ── Panel operations ───────────────────────────────────────────────── + r.register("toggle-panel-and-focus", |args| { + require_args("toggle-panel-and-focus", args, 1)?; + let panel = parse_panel(&args[0])?; Ok(Box::new(TogglePanelAndFocus(panel))) }); + r.register("toggle-panel-visibility", |args| { + require_args("toggle-panel-visibility", args, 1)?; + let panel = parse_panel(&args[0])?; + Ok(Box::new(TogglePanelVisibility(panel))) + }); r.register("cycle-panel-focus", |_| Ok(Box::new(CyclePanelFocus))); r.register("move-panel-cursor", |args| { require_args("move-panel-cursor", args, 2)?; - let panel = match args[0].as_str() { - "formula" => effect::Panel::Formula, - "category" => effect::Panel::Category, - "view" => effect::Panel::View, - other => return Err(format!("Unknown panel: {other}")), - }; + let panel = parse_panel(&args[0])?; let delta = args[1].parse::().map_err(|e| e.to_string())?; Ok(Box::new(MovePanelCursor { panel, delta })) }); @@ -1950,7 +1949,7 @@ pub fn default_registry() -> CmdRegistry { r.register("create-and-switch-view", |_| Ok(Box::new(CreateAndSwitchView))); r.register("delete-view-at-cursor", |_| Ok(Box::new(DeleteViewAtCursor))); - // Tile select + // ── Tile select ────────────────────────────────────────────────────── r.register("move-tile-cursor", |args| { require_args("move-tile-cursor", args, 1)?; let delta = args[0].parse::().map_err(|e| e.to_string())?; @@ -1959,22 +1958,16 @@ pub fn default_registry() -> CmdRegistry { r.register("cycle-axis-for-tile", |_| Ok(Box::new(CycleAxisForTile))); r.register("set-axis-for-tile", |args| { require_args("set-axis-for-tile", args, 1)?; - let axis = match args[0].to_lowercase().as_str() { - "row" => Axis::Row, - "column" | "col" => Axis::Column, - "page" => Axis::Page, - "none" => Axis::None, - other => return Err(format!("Unknown axis: {other}")), - }; + let axis = parse_axis(&args[0])?; Ok(Box::new(SetAxisForTile(axis))) }); - // Grid operations + // ── Grid operations ────────────────────────────────────────────────── r.register("toggle-group-under-cursor", |_| Ok(Box::new(ToggleGroupUnderCursor))); r.register("toggle-col-group-under-cursor", |_| Ok(Box::new(ToggleColGroupUnderCursor))); r.register("hide-selected-row-item", |_| Ok(Box::new(HideSelectedRowItem))); - // Text buffer + // ── Text buffer ────────────────────────────────────────────────────── r.register("append-char", |args| { require_args("append-char", args, 1)?; Ok(Box::new(AppendChar { buffer: args[0].clone() })) @@ -1983,8 +1976,9 @@ pub fn default_registry() -> CmdRegistry { require_args("pop-char", args, 1)?; Ok(Box::new(PopChar { buffer: args[0].clone() })) }); + r.register("command-mode-backspace", |_| Ok(Box::new(CommandModeBackspace))); - // Commit commands + // ── Commit ─────────────────────────────────────────────────────────── r.register("commit-cell-edit", |_| Ok(Box::new(CommitCellEdit))); r.register("commit-formula", |_| Ok(Box::new(CommitFormula))); r.register("commit-category-add", |_| Ok(Box::new(CommitCategoryAdd))); @@ -1992,12 +1986,31 @@ pub fn default_registry() -> CmdRegistry { r.register("commit-export", |_| Ok(Box::new(CommitExport))); r.register("execute-command", |_| Ok(Box::new(ExecuteCommand))); - // Wizard + // ── Wizard ─────────────────────────────────────────────────────────── r.register("handle-wizard-key", |_| Ok(Box::new(HandleWizardKey))); r } +fn parse_panel(s: &str) -> Result { + match s { + "formula" => Ok(Panel::Formula), + "category" => Ok(Panel::Category), + "view" => Ok(Panel::View), + other => Err(format!("Unknown panel: {other}")), + } +} + +fn parse_axis(s: &str) -> Result { + match s.to_lowercase().as_str() { + "row" => Ok(Axis::Row), + "column" | "col" => Ok(Axis::Column), + "page" => Ok(Axis::Page), + "none" => Ok(Axis::None), + other => Err(format!("Unknown axis: {other}")), + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/command/mod.rs b/src/command/mod.rs index bf8d288..73d2c54 100644 --- a/src/command/mod.rs +++ b/src/command/mod.rs @@ -2,7 +2,7 @@ //! replayed, scripted, and tested without the TUI. //! //! Commands are trait objects (`dyn Cmd`) that produce effects (`dyn Effect`). -//! The headless CLI (--cmd / --script) parses Forth-style text into effects +//! The headless CLI (--cmd / --script) parses quasi-lisp text into effects //! and applies them directly. pub mod cmd; diff --git a/src/command/parse.rs b/src/command/parse.rs index 8d633a0..0973ccb 100644 --- a/src/command/parse.rs +++ b/src/command/parse.rs @@ -1,4 +1,4 @@ -//! Forth-style prefix command parser. +//! Quasi-lisp prefix command parser. //! //! Syntax: `word arg1 arg2 ...` //! Multiple commands on one line separated by `.`