From b8fd938120a3536960ebfc322d1fbec9ea5da3c6 Mon Sep 17 00:00:00 2001 From: Rushmore75 Date: Fri, 14 Nov 2025 10:34:43 -0700 Subject: [PATCH] close #38 --- src/app/clipboard.rs | 54 +++++++++++++++++++++++++++++++++++++++++++ src/app/logic/calc.rs | 5 ++++ src/app/logic/cell.rs | 54 ++++++++++++++++++++++++++++++++++++++++--- src/app/logic/ctx.rs | 2 +- 4 files changed, 111 insertions(+), 4 deletions(-) diff --git a/src/app/clipboard.rs b/src/app/clipboard.rs index c32c37e..f74810a 100644 --- a/src/app/clipboard.rs +++ b/src/app/clipboard.rs @@ -296,3 +296,57 @@ fn copy_paste_vars_translate() { let a = app.grid.get_cell("A0").as_ref().expect("Should've been set by paste"); assert_eq!(a.to_string(), "=A1"); } + +#[test] +fn copy_paste_double_locked_var() { + let mut app = App::new(); + + app.grid.set_cell("A0", 0.); + app.grid.set_cell("A1", "=$A$0".to_string()); + + // Copy A0 + app.grid.mv_cursor_to(0, 1); + app.mode = super::mode::Mode::Chord(Chord::new('y')); + Mode::process_key(&mut app, 'y'); + + app.grid.mv_cursor_to(1, 0); + Mode::process_key(&mut app, 'p'); + let c = app.grid.get_cell("B0").as_ref().expect("Just set it"); + assert_eq!(c.to_string(), "=$A$0"); +} + +#[test] +fn copy_paste_x_locked_var() { + let mut app = App::new(); + + app.grid.set_cell("A0", 0.); + app.grid.set_cell("A1", "=$A0".to_string()); + + // Copy A0 + app.grid.mv_cursor_to(0, 1); + app.mode = super::mode::Mode::Chord(Chord::new('y')); + Mode::process_key(&mut app, 'y'); + + app.grid.mv_cursor_to(1, 2); + Mode::process_key(&mut app, 'p'); + let c = app.grid.get_cell("B2").as_ref().expect("Just set it"); + assert_eq!(c.to_string(), "=$A1"); +} + +#[test] +fn copy_paste_y_locked_var() { + let mut app = App::new(); + + app.grid.set_cell("A0", 0.); + app.grid.set_cell("A1", "=A$0".to_string()); + + // Copy A0 + app.grid.mv_cursor_to(0, 1); + app.mode = super::mode::Mode::Chord(Chord::new('y')); + Mode::process_key(&mut app, 'y'); + + app.grid.mv_cursor_to(1, 2); + Mode::process_key(&mut app, 'p'); + let c = app.grid.get_cell("B2").as_ref().expect("Just set it"); + assert_eq!(c.to_string(), "=B$0"); +} \ No newline at end of file diff --git a/src/app/logic/calc.rs b/src/app/logic/calc.rs index 0e59e14..b422ef5 100644 --- a/src/app/logic/calc.rs +++ b/src/app/logic/calc.rs @@ -379,6 +379,8 @@ impl Grid { /// Parse values in the format of A0, C10 ZZ99, etc, and /// turn them into an X,Y index. pub fn parse_to_idx(i: &str) -> Option<(usize, usize)> { + let i = i.replace('$', ""); + let chars = i.chars().take_while(|c| c.is_alphabetic()).collect::>(); let nums = i.chars().skip(chars.len()).take_while(|c| c.is_numeric()).collect::(); @@ -474,6 +476,9 @@ fn cell_strings() { #[test] fn alphanumeric_indexing() { assert_eq!(Grid::parse_to_idx("A0"), Some((0, 0))); + assert_eq!(Grid::parse_to_idx("$A0"), Some((0, 0))); + assert_eq!(Grid::parse_to_idx("A$0"), Some((0, 0))); + assert_eq!(Grid::parse_to_idx("$A$0"), Some((0, 0))); assert_eq!(Grid::parse_to_idx("AA0"), Some((26, 0))); assert_eq!(Grid::parse_to_idx("A1"), Some((0, 1))); assert_eq!(Grid::parse_to_idx("A10"), Some((0, 10))); diff --git a/src/app/logic/cell.rs b/src/app/logic/cell.rs index aab317c..8543085 100644 --- a/src/app/logic/cell.rs +++ b/src/app/logic/cell.rs @@ -66,6 +66,37 @@ impl CellType { let mut rolling = eq.clone(); // translate standard vars A0 -> A1 for old_var in ctx.dump_vars() { + let mut lock_x = false; + let mut lock_y = false; + + if old_var.contains('$') { + let locations = old_var.char_indices().filter(|(_, c)| *c == '$').map(|(i, _)| i).collect::>(); + match locations.len() { + 1 => { + if locations[0] == 0 { + // locking the X axis (A,B,C...) + lock_x = true; + } else if locations[0] < old_var.len() { + // inside the string somewhere, gonna assume this means to lock Y (1,2,3...) + lock_y = true; + + } else { + // where tf is this dollar sign? + // (It's somewhere malformed, like A0$ or something) + } + } + 2 => { + // YOLO, lock both X & Y + continue; // just pretend you never even saw this var + } + _ => { + // Could probably optimize the code or something so you only go over the string + // once, instead of contains() then getting the indexes of where it is. + // You could then put your no-$ code here. + } + } + } + if let Some((src_x, src_y)) = Grid::parse_to_idx(&old_var) { let (x1, y1) = from; let x1 = x1 as i32; @@ -74,12 +105,29 @@ impl CellType { let x2 = x2 as i32; let y2 = y2 as i32; - let dest_x = (src_x as i32 + (x2 - x1)) as usize; - let dest_y = (src_y as i32 + (y2 - y1)) as usize; + let dest_x = if lock_x { + src_x as usize + } else { + (src_x as i32 + (x2 - x1)) as usize + }; + + let dest_y = if lock_y { + src_y as usize + } else { + (src_y as i32 + (y2 - y1)) as usize + }; let alpha = Grid::num_to_char(dest_x); let alpha = alpha.trim(); - let new_var = format!("{alpha}{dest_y}"); + + let new_var = if lock_x { + format!("${alpha}{dest_y}") + } else if lock_y { + format!("{alpha}${dest_y}") + } else { + format!("{alpha}{dest_y}") + }; + // swap out vars rolling = replace_fn(&rolling, &old_var, &new_var); diff --git a/src/app/logic/ctx.rs b/src/app/logic/ctx.rs index 0171ec0..ad64d3f 100644 --- a/src/app/logic/ctx.rs +++ b/src/app/logic/ctx.rs @@ -295,7 +295,7 @@ impl Context for ExtractionContext { registry.push(identifier.to_owned()) } else { panic!("The RwLock should always be write-able") } // Ok(Value::Int(1)) - todo!(); + unimplemented!("Extracting function identifier not implemented yet") } fn are_builtin_functions_disabled(&self) -> bool {