working on #26, got column insertion working

This commit is contained in:
2025-11-13 17:24:13 -07:00
parent 755dbc70f1
commit 7c383028a3
6 changed files with 122 additions and 17 deletions

View File

@@ -1,6 +1,4 @@
use evalexpr::eval_with_context;
use crate::app::logic::{calc::Grid, cell::CellType, ctx::ExtractionContext};
use crate::app::logic::{calc::Grid, cell::CellType};
#[cfg(test)]
use crate::app::{

View File

@@ -1,6 +1,5 @@
use std::{
cmp::{max, min},
fmt::Display,
fs,
io::{Read, Write},
path::PathBuf,
@@ -8,10 +7,10 @@ use std::{
use evalexpr::*;
use crate::app::logic::{
use crate::app::{logic::{
cell::{CSV_DELIMITER, CellType},
ctx,
};
}, mode::Mode};
#[cfg(test)]
use crate::app::app::App;
@@ -114,7 +113,7 @@ impl Grid {
{
val.to_string()
} else {
cell.to_string_csv_escaped()
cell.escaped_csv_string()
}
} else {
CSV_DELIMITER.to_string()
@@ -235,6 +234,42 @@ 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_column_before(&mut self, (insertion_x, _y): (usize, usize)) {
let mut v = Vec::with_capacity(LEN);
for _ in 0..LEN {
v.push(None);
}
self.cells.insert(insertion_x, v);
// keep the grid LEN
self.cells.pop();
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));
}
}
}
}
pub fn insert_column_after(&mut self, (x, y): (usize, usize)) {
self.insert_column_before((x+1,y));
}
/// Iterate over the entire grid and see where
/// the farthest modified cell is.
#[must_use]
@@ -759,3 +794,60 @@ fn cursor_fns() {
app.grid.mv_cursor_to(1, 0);
assert_eq!(app.grid.cursor(), (1, 0));
}
#[test]
fn insert_col_before_1() {
let mut grid = Grid::new();
grid.set_cell("A0", 2.);
grid.set_cell("B0", "=A0*2".to_string());
grid.set_cell("B1", "=B0".to_string());
grid.mv_cursor_to(1, 0);
grid.insert_column_before(grid.cursor());
// cell didn't get translated
let cell = grid.get_cell("A0").as_ref().expect("Just set it");
assert_eq!(cell.to_string(), "2");
// cell referencing another cell on the same side of the insertion
let cell = grid.get_cell("C1").as_ref().expect("Just set it");
assert_eq!(cell.to_string(), "=C0");
}
#[test]
fn insert_col_before_2() {
let mut grid = Grid::new();
grid.set_cell("A0", 2.);
grid.set_cell("B0", "=A0*2".to_string());
grid.set_cell("B1", "=B0".to_string());
grid.mv_cursor_to(0, 0);
grid.insert_column_before(grid.cursor());
let cell = grid.get_cell("B0").as_ref().expect("Just set it");
assert_eq!(cell.to_string(), "2");
// cell referencing another cell on the same side of the insertion
let cell = grid.get_cell("C1").as_ref().expect("Just set it");
assert_eq!(cell.to_string(), "=C0");
}
#[test]
fn insert_col_before_3() {
let mut grid = Grid::new();
grid.set_cell("A0", 2.);
grid.set_cell("A1", 2.);
grid.set_cell("B0", "=A0*A1".to_string());
grid.mv_cursor_to(0, 0);
grid.insert_column_before(grid.cursor());
let cell = grid.get_cell("C0").as_ref().expect("Just set it");
assert_eq!(cell.to_string(), "=B0*B1");
}

View File

@@ -27,7 +27,7 @@ pub const CSV_DELIMITER: char = ',';
const CSV_ESCAPE: char = '"';
impl CellType {
pub fn to_string_csv_escaped(&self) -> String {
pub fn escaped_csv_string(&self) -> String {
let mut display = self.to_string();
// escape quotes " -> ""
@@ -53,7 +53,8 @@ impl CellType {
if value.starts_with('=') { Self::Equation(value) } else { Self::String(value) }
}
}
pub fn translate_cell(&self, from: (usize, usize), to: (usize, usize)) -> CellType {
pub fn custom_translate_cell(&self, from: (usize, usize), to: (usize, usize), replace_fn: impl Fn(&str, &str, &str) -> String) -> CellType {
match self {
// don't translate non-equations
CellType::Number(_) | CellType::String(_) => return self.clone(),
@@ -81,7 +82,8 @@ impl CellType {
let new_var = format!("{alpha}{dest_y}");
// swap out vars
rolling = rolling.replace(&old_var, &new_var);
rolling = replace_fn(&rolling, &old_var, &new_var);
// rolling = rolling.replace(&old_var, &new_var);
} else {
// why you coping invalid stuff, nerd?
}
@@ -90,6 +92,10 @@ impl CellType {
}
}
}
pub fn translate_cell(&self, from: (usize, usize), to: (usize, usize)) -> CellType {
self.custom_translate_cell(from, to, |a,b,c| a.replace(b, c))
}
}
impl Display for CellType {

View File

@@ -280,8 +280,9 @@ impl Context for ExtractionContext {
fn get_value(&self, identifier: &str) -> Option<Value<Self::NumericTypes>> {
if let Ok(mut registry) = self.var_registry.write() {
registry.push(identifier.to_owned());
}
None
} else { panic!("The RwLock should always be write-able") }
Some(Value::Int(1))
}
fn call_function(
@@ -292,8 +293,9 @@ impl Context for ExtractionContext {
let _ = argument;
if let Ok(mut registry) = self.fn_registry.write() {
registry.push(identifier.to_owned())
}
Ok(Value::Empty)
} else { panic!("The RwLock should always be write-able") }
// Ok(Value::Int(1))
todo!();
}
fn are_builtin_functions_disabled(&self) -> bool {

View File

@@ -160,8 +160,14 @@ impl Mode {
'r' => {
app.mode = Mode::Insert(Chord::from(String::new()));
}
'I' => { /* insert col before */ }
'A' => { /* insert col after */ }
// insert column before
'I' => {
app.grid.insert_column_before(app.grid.cursor());
}
// insert column after
'A' => {
app.grid.insert_column_after(app.grid.cursor());
}
'o' => { /* insert row below */ }
'O' => { /* insert row above */ }
'v' => app.mode = Mode::Visual(app.grid.cursor()),