working on #26, got column insertion working
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
/target
|
/target
|
||||||
/.vscode
|
/.vscode
|
||||||
/*.csv
|
/*.csv
|
||||||
|
/*.nscim
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
use evalexpr::eval_with_context;
|
use crate::app::logic::{calc::Grid, cell::CellType};
|
||||||
|
|
||||||
use crate::app::logic::{calc::Grid, cell::CellType, ctx::ExtractionContext};
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use crate::app::{
|
use crate::app::{
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
cmp::{max, min},
|
cmp::{max, min},
|
||||||
fmt::Display,
|
|
||||||
fs,
|
fs,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
@@ -8,10 +7,10 @@ use std::{
|
|||||||
|
|
||||||
use evalexpr::*;
|
use evalexpr::*;
|
||||||
|
|
||||||
use crate::app::logic::{
|
use crate::app::{logic::{
|
||||||
cell::{CSV_DELIMITER, CellType},
|
cell::{CSV_DELIMITER, CellType},
|
||||||
ctx,
|
ctx,
|
||||||
};
|
}, mode::Mode};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use crate::app::app::App;
|
use crate::app::app::App;
|
||||||
@@ -114,7 +113,7 @@ impl Grid {
|
|||||||
{
|
{
|
||||||
val.to_string()
|
val.to_string()
|
||||||
} else {
|
} else {
|
||||||
cell.to_string_csv_escaped()
|
cell.escaped_csv_string()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CSV_DELIMITER.to_string()
|
CSV_DELIMITER.to_string()
|
||||||
@@ -235,6 +234,42 @@ impl Grid {
|
|||||||
self.mv_cursor_to(x, y);
|
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
|
/// Iterate over the entire grid and see where
|
||||||
/// the farthest modified cell is.
|
/// the farthest modified cell is.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@@ -759,3 +794,60 @@ fn cursor_fns() {
|
|||||||
app.grid.mv_cursor_to(1, 0);
|
app.grid.mv_cursor_to(1, 0);
|
||||||
assert_eq!(app.grid.cursor(), (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 = '"';
|
const CSV_ESCAPE: char = '"';
|
||||||
|
|
||||||
impl CellType {
|
impl CellType {
|
||||||
pub fn to_string_csv_escaped(&self) -> String {
|
pub fn escaped_csv_string(&self) -> String {
|
||||||
let mut display = self.to_string();
|
let mut display = self.to_string();
|
||||||
|
|
||||||
// escape quotes " -> ""
|
// escape quotes " -> ""
|
||||||
@@ -53,7 +53,8 @@ impl CellType {
|
|||||||
if value.starts_with('=') { Self::Equation(value) } else { Self::String(value) }
|
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 {
|
match self {
|
||||||
// don't translate non-equations
|
// don't translate non-equations
|
||||||
CellType::Number(_) | CellType::String(_) => return self.clone(),
|
CellType::Number(_) | CellType::String(_) => return self.clone(),
|
||||||
@@ -81,7 +82,8 @@ impl CellType {
|
|||||||
let new_var = format!("{alpha}{dest_y}");
|
let new_var = format!("{alpha}{dest_y}");
|
||||||
|
|
||||||
// swap out vars
|
// 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 {
|
} else {
|
||||||
// why you coping invalid stuff, nerd?
|
// 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 {
|
impl Display for CellType {
|
||||||
|
|||||||
@@ -280,8 +280,9 @@ impl Context for ExtractionContext {
|
|||||||
fn get_value(&self, identifier: &str) -> Option<Value<Self::NumericTypes>> {
|
fn get_value(&self, identifier: &str) -> Option<Value<Self::NumericTypes>> {
|
||||||
if let Ok(mut registry) = self.var_registry.write() {
|
if let Ok(mut registry) = self.var_registry.write() {
|
||||||
registry.push(identifier.to_owned());
|
registry.push(identifier.to_owned());
|
||||||
}
|
} else { panic!("The RwLock should always be write-able") }
|
||||||
None
|
|
||||||
|
Some(Value::Int(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_function(
|
fn call_function(
|
||||||
@@ -292,8 +293,9 @@ impl Context for ExtractionContext {
|
|||||||
let _ = argument;
|
let _ = argument;
|
||||||
if let Ok(mut registry) = self.fn_registry.write() {
|
if let Ok(mut registry) = self.fn_registry.write() {
|
||||||
registry.push(identifier.to_owned())
|
registry.push(identifier.to_owned())
|
||||||
}
|
} else { panic!("The RwLock should always be write-able") }
|
||||||
Ok(Value::Empty)
|
// Ok(Value::Int(1))
|
||||||
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn are_builtin_functions_disabled(&self) -> bool {
|
fn are_builtin_functions_disabled(&self) -> bool {
|
||||||
|
|||||||
@@ -160,8 +160,14 @@ impl Mode {
|
|||||||
'r' => {
|
'r' => {
|
||||||
app.mode = Mode::Insert(Chord::from(String::new()));
|
app.mode = Mode::Insert(Chord::from(String::new()));
|
||||||
}
|
}
|
||||||
'I' => { /* insert col before */ }
|
// insert column before
|
||||||
'A' => { /* insert col after */ }
|
'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 below */ }
|
||||||
'O' => { /* insert row above */ }
|
'O' => { /* insert row above */ }
|
||||||
'v' => app.mode = Mode::Visual(app.grid.cursor()),
|
'v' => app.mode = Mode::Visual(app.grid.cursor()),
|
||||||
|
|||||||
Reference in New Issue
Block a user