refactor(command): pre-resolve cell key and grid dimensions in CmdContext
Refactor command system to pre-resolve cell key and grid dimensions in CmdContext, eliminating repeated GridLayout construction. Key changes: - Add cell_key, row_count, col_count to CmdContext - Replace generic CmdRegistry::register with register/register_pure/register_nullary - Cell commands (clear-cell, yank, paste) now take explicit CellKey - Update keymap dispatch to use new interactive() method - Special-case "search" buffer in SetBuffer effect - Update tests to populate new context fields This reduces code duplication and makes command execution more efficient by computing layout once at context creation time. Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -165,7 +165,7 @@ impl Keymap {
|
||||
let binding = self.lookup(key, mods)?;
|
||||
match binding {
|
||||
Binding::Cmd { name, args } => {
|
||||
let cmd = registry.parse(name, args).ok()?;
|
||||
let cmd = registry.interactive(name, args, ctx).ok()?;
|
||||
Some(cmd.execute(ctx))
|
||||
}
|
||||
Binding::Prefix(sub) => Some(vec![Box::new(SetTransientKeymap(sub.clone()))]),
|
||||
@ -267,7 +267,7 @@ impl KeymapSet {
|
||||
normal.bind_args(KeyCode::Char('u'), ctrl, "scroll-rows", vec!["-5".into()]);
|
||||
|
||||
// Cell operations
|
||||
normal.bind(KeyCode::Char('x'), none, "clear-selected-cell");
|
||||
normal.bind(KeyCode::Char('x'), none, "clear-cell");
|
||||
normal.bind(KeyCode::Char('p'), none, "paste");
|
||||
|
||||
// View
|
||||
|
||||
@ -11,6 +11,7 @@ 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 {
|
||||
@ -101,6 +102,8 @@ impl App {
|
||||
|
||||
pub fn cmd_context(&self, key: KeyCode, mods: KeyModifiers) -> CmdContext<'_> {
|
||||
let view = self.model.active_view();
|
||||
let layout = GridLayout::new(&self.model, view);
|
||||
let (sel_row, sel_col) = view.selected;
|
||||
CmdContext {
|
||||
model: &self.model,
|
||||
mode: &self.mode,
|
||||
@ -120,6 +123,9 @@ impl App {
|
||||
cat_panel_cursor: self.cat_panel_cursor,
|
||||
view_panel_cursor: self.view_panel_cursor,
|
||||
tile_cat_idx: self.tile_cat_idx,
|
||||
cell_key: layout.cell_key(sel_row, sel_col),
|
||||
row_count: layout.row_count(),
|
||||
col_count: layout.col_count(),
|
||||
key_code: key,
|
||||
key_modifiers: mods,
|
||||
}
|
||||
@ -220,11 +226,26 @@ mod tests {
|
||||
app.apply_effects(effects);
|
||||
}
|
||||
|
||||
fn enter_advance_cmd(app: &App) -> crate::command::cmd::EnterAdvance {
|
||||
use crate::command::cmd::CursorState;
|
||||
let view = app.model.active_view();
|
||||
let cursor = CursorState {
|
||||
row: view.selected.0,
|
||||
col: view.selected.1,
|
||||
row_count: 3,
|
||||
col_count: 2,
|
||||
row_offset: 0,
|
||||
col_offset: 0,
|
||||
};
|
||||
crate::command::cmd::EnterAdvance { cursor }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enter_advance_moves_down_within_column() {
|
||||
let mut app = two_col_model();
|
||||
app.model.active_view_mut().selected = (0, 0);
|
||||
run_cmd(&mut app, &crate::command::cmd::EnterAdvance);
|
||||
let cmd = enter_advance_cmd(&app);
|
||||
run_cmd(&mut app, &cmd);
|
||||
assert_eq!(app.model.active_view().selected, (1, 0));
|
||||
}
|
||||
|
||||
@ -233,7 +254,8 @@ mod tests {
|
||||
let mut app = two_col_model();
|
||||
// row_max = 2 (A,B,C), col 0 → should wrap to (0, 1)
|
||||
app.model.active_view_mut().selected = (2, 0);
|
||||
run_cmd(&mut app, &crate::command::cmd::EnterAdvance);
|
||||
let cmd = enter_advance_cmd(&app);
|
||||
run_cmd(&mut app, &cmd);
|
||||
assert_eq!(app.model.active_view().selected, (0, 1));
|
||||
}
|
||||
|
||||
@ -241,7 +263,8 @@ mod tests {
|
||||
fn enter_advance_stays_at_bottom_right() {
|
||||
let mut app = two_col_model();
|
||||
app.model.active_view_mut().selected = (2, 1);
|
||||
run_cmd(&mut app, &crate::command::cmd::EnterAdvance);
|
||||
let cmd = enter_advance_cmd(&app);
|
||||
run_cmd(&mut app, &cmd);
|
||||
assert_eq!(app.model.active_view().selected, (2, 1));
|
||||
}
|
||||
|
||||
|
||||
@ -289,7 +289,12 @@ pub struct SetBuffer {
|
||||
}
|
||||
impl Effect for SetBuffer {
|
||||
fn apply(&self, app: &mut App) {
|
||||
app.buffers.insert(self.name.clone(), self.value.clone());
|
||||
// "search" is special — it writes to search_query for backward compat
|
||||
if self.name == "search" {
|
||||
app.search_query = self.value.clone();
|
||||
} else {
|
||||
app.buffers.insert(self.name.clone(), self.value.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user