diff --git a/src/app/logic/calc.rs b/src/app/logic/calc.rs index c5c88a5..058c9f9 100644 --- a/src/app/logic/calc.rs +++ b/src/app/logic/calc.rs @@ -7,10 +7,13 @@ use std::{ use evalexpr::*; -use crate::app::{logic::{ - cell::{CSV_DELIMITER, CellType}, - ctx, -}, mode::Mode}; +use crate::app::{ + logic::{ + cell::{CSV_DELIMITER, CellType}, + ctx, + }, + mode::Mode, +}; #[cfg(test)] use crate::app::app::App; @@ -234,8 +237,28 @@ impl Grid { self.mv_cursor_to(x, y); } - pub fn insert_row_above(&mut self, (x, y): (usize, usize)) {todo!()} - pub fn insert_row_below(&mut self, (x, y): (usize, usize)) {todo!()} + pub fn insert_row_above(&mut self, (_x, insertion_y): (usize, usize)) { + for x in 0..LEN { + self.cells[x].insert(insertion_y, None); + self.cells[x].pop(); + for y in 0..LEN { + if let Some(cell) = self.get_cell_raw(x, y).as_ref().map(|f| { + f.custom_translate_cell((0, 0), (0, 1), |rolling, old, new| { + if let Some((_, arg_y)) = Grid::parse_to_idx(old) { + if arg_y < insertion_y { rolling.to_owned() } else { rolling.replace(old, new) } + } else { + unimplemented!("Invalid variable wanted to be translated") + } + } + )}) { + self.set_cell_raw((x,y), Some(cell)); + } + } + } + } + pub fn insert_row_below(&mut self, (x, y): (usize, usize)) { + self.insert_row_above((x,y+1)); + } pub fn insert_column_before(&mut self, (insertion_x, _y): (usize, usize)) { let mut v = Vec::with_capacity(LEN); for _ in 0..LEN { @@ -244,31 +267,25 @@ impl Grid { self.cells.insert(insertion_x, v); // keep the grid LEN self.cells.pop(); - for x in 0..LEN { + for x in 0..LEN { for y in 0..LEN { - if let Some(cell) = self - .get_cell_raw(x, y) - .as_ref() - .map(|f| f - .custom_translate_cell((0,0), (1,0), |rolling, old, new| { - if let Some((arg_x, _)) = Grid::parse_to_idx(old) { - // add 1 because of the insertion - if arg_x < insertion_x { - rolling.to_owned() - } else { - rolling.replace(old, new) - } - } else { - unimplemented!("Invalid variable wanted to be translated") - } - })) { - self.set_cell_raw((x,y), Some(cell)); + if let Some(cell) = self.get_cell_raw(x, y).as_ref().map(|f| { + f.custom_translate_cell((0, 0), (1, 0), |rolling, old, new| { + if let Some((arg_x, _)) = Grid::parse_to_idx(old) { + // add 1 because of the insertion + if arg_x < insertion_x { rolling.to_owned() } else { rolling.replace(old, new) } + } else { + unimplemented!("Invalid variable wanted to be translated") + } + }) + }) { + self.set_cell_raw((x, y), Some(cell)); } } } } pub fn insert_column_after(&mut self, (x, y): (usize, usize)) { - self.insert_column_before((x+1,y)); + self.insert_column_before((x + 1, y)); } /// Iterate over the entire grid and see where /// the farthest modified cell is. @@ -851,3 +868,66 @@ fn insert_col_before_3() { let cell = grid.get_cell("C0").as_ref().expect("Just set it"); assert_eq!(cell.to_string(), "=B0*B1"); } + +#[test] +fn insert_row_above_1() { + let mut grid = Grid::new(); + + grid.set_cell("A1", 2.); + grid.set_cell("A0", "=A1*2".to_string()); + grid.set_cell("B0", "=A0".to_string()); + + // shift half down + grid.mv_cursor_to(0, 1); + grid.insert_row_above(grid.cursor()); + + // cell didn't get translated + let cell = grid.get_cell("A0").as_ref().expect("Just set it"); + assert_eq!(cell.to_string(), "=A2*2"); + + // cell referencing another cell on the same side of the insertion + let cell = grid.get_cell("B0").as_ref().expect("Just set it"); + assert_eq!(cell.to_string(), "=A0"); +} + +#[test] +fn insert_row_above_2() { + let mut grid = Grid::new(); + + grid.set_cell("A1", 2.); + grid.set_cell("A0", "=A1*2".to_string()); + grid.set_cell("B0", "=A0".to_string()); + + // shift nothing down + grid.mv_cursor_to(0, 2); + grid.insert_row_above(grid.cursor()); + + // cell didn't get translated + let cell = grid.get_cell("A0").as_ref().expect("Just set it"); + assert_eq!(cell.to_string(), "=A1*2"); + + // cell referencing another cell on the same side of the insertion + let cell = grid.get_cell("B0").as_ref().expect("Just set it"); + assert_eq!(cell.to_string(), "=A0"); +} + +#[test] +fn insert_row_above_3() { + let mut grid = Grid::new(); + + grid.set_cell("A1", 2.); + grid.set_cell("A0", "=A1*2".to_string()); + grid.set_cell("B0", "=A0".to_string()); + + // shift everything down + grid.mv_cursor_to(0, 0); + grid.insert_row_above(grid.cursor()); + + // cell didn't get translated + let cell = grid.get_cell("A1").as_ref().expect("Just set it"); + assert_eq!(cell.to_string(), "=A2*2"); + + // cell referencing another cell on the same side of the insertion + let cell = grid.get_cell("B1").as_ref().expect("Just set it"); + assert_eq!(cell.to_string(), "=A1"); +} diff --git a/src/app/mode.rs b/src/app/mode.rs index c79f30a..b8f63fe 100644 --- a/src/app/mode.rs +++ b/src/app/mode.rs @@ -168,8 +168,14 @@ impl Mode { 'A' => { app.grid.insert_column_after(app.grid.cursor()); } - 'o' => { /* insert row below */ } - 'O' => { /* insert row above */ } + // insert row below + 'o' => { + app.grid.insert_row_below(app.grid.cursor()); + } + // insert row above + 'O' => { + app.grid.insert_row_above(app.grid.cursor()); + } 'v' => app.mode = Mode::Visual(app.grid.cursor()), ':' => app.mode = Mode::Command(Chord::new(':')), 'p' => {