working on #26, got column insertion working
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
/target
|
||||
/.vscode
|
||||
/*.csv
|
||||
/*.csv
|
||||
/*.nscim
|
||||
@@ -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::{
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()),
|
||||
|
||||
Reference in New Issue
Block a user