fix #18
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -134,6 +134,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "evalexpr"
|
name = "evalexpr"
|
||||||
version = "13.0.0"
|
version = "13.0.0"
|
||||||
|
source = "git+https://github.com/Rushmore75/evalexpr.git#f7b8fa3436bfc3e114da3f84d1d62603307fed70"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# evalexpr = "13.0.0"
|
# evalexpr = "13.0.0"
|
||||||
evalexpr ={ path = "../evalexpr"}
|
# evalexpr ={ path = "../evalexpr"}
|
||||||
# evalexpr = { git="https://github.com/Rushmore75/evalexpr.git" }
|
evalexpr = { git="https://github.com/Rushmore75/evalexpr.git" }
|
||||||
ratatui = "0.29.0"
|
ratatui = "0.29.0"
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ impl std::fmt::Debug for Grid {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CSV_DELIMITER: char = ',';
|
||||||
|
const CSV_ESCAPE: char = '"';
|
||||||
|
|
||||||
impl Grid {
|
impl Grid {
|
||||||
pub fn needs_to_be_saved(&self) -> bool {
|
pub fn needs_to_be_saved(&self) -> bool {
|
||||||
self.dirty
|
self.dirty
|
||||||
@@ -51,8 +54,20 @@ impl Grid {
|
|||||||
for y in 0..=my {
|
for y in 0..=my {
|
||||||
for x in 0..=mx {
|
for x in 0..=mx {
|
||||||
let cell = &self.cells[x][y];
|
let cell = &self.cells[x][y];
|
||||||
let display = cell.as_ref().map(|f| f.to_string()).unwrap_or(String::new());
|
let mut display = cell.as_ref().map(|f| f.to_string()).unwrap_or(String::new());
|
||||||
write!(f, "{display},")?;
|
|
||||||
|
// escape quotes " -> ""
|
||||||
|
let needs_escaping = display.char_indices().filter(|f| f.1==CSV_ESCAPE).map(|f| f.0).collect::<Vec<usize>>();
|
||||||
|
for idx in needs_escaping.iter().rev() {
|
||||||
|
display.insert(*idx, CSV_ESCAPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// escape string of it has a comma
|
||||||
|
if display.contains(CSV_DELIMITER) {
|
||||||
|
write!(f, "\"{display}\"{CSV_DELIMITER}")?;
|
||||||
|
} else {
|
||||||
|
write!(f, "{display}{CSV_DELIMITER}")?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
write!(f, "\n")?;
|
write!(f, "\n")?;
|
||||||
}
|
}
|
||||||
@@ -92,9 +107,55 @@ impl Grid {
|
|||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
file.read_to_string(&mut buf)?;
|
file.read_to_string(&mut buf)?;
|
||||||
for (yi, line) in buf.lines().enumerate() {
|
for (yi, line) in buf.lines().enumerate() {
|
||||||
for (xi, cell) in line.split(',').enumerate() {
|
|
||||||
|
// 1, 2, "=avg(A0,B0)", she said: """wow""",
|
||||||
|
|
||||||
|
let mut cells = Vec::new();
|
||||||
|
|
||||||
|
let mut inside_quotes = false;
|
||||||
|
let mut token = Vec::new();
|
||||||
|
|
||||||
|
let mut iter = line.as_bytes().iter().map(|f| *f as char).peekable();
|
||||||
|
while let Some(c) = iter.next() {
|
||||||
|
// we just finished
|
||||||
|
if c == CSV_DELIMITER && !inside_quotes {
|
||||||
|
if !token.is_empty() {
|
||||||
|
cells.push(Some(token.iter().collect::<String>()));
|
||||||
|
} else {
|
||||||
|
cells.push(None);
|
||||||
|
}
|
||||||
|
token.clear();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// start reading an escaped cell
|
||||||
|
if c == '"' {
|
||||||
|
if inside_quotes {
|
||||||
|
// we might be escaping a quote
|
||||||
|
if let Some(next) = iter.peek() {
|
||||||
|
// check if the next cell is a quote, if it is, that's because it's being escaped by the current quote
|
||||||
|
if *next == '"' {
|
||||||
|
// don't save the escape char
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// escaped cell over
|
||||||
|
inside_quotes = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we are at the end of the row, so idk if it matters anymore, as there won't be a next()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
inside_quotes = true;
|
||||||
|
// don't save the scape char
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
token.push(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (xi, cell) in cells.into_iter().enumerate() {
|
||||||
// This gets automatically duck-typed
|
// This gets automatically duck-typed
|
||||||
grid.set_cell_raw((xi, yi), Some(cell.to_string()));
|
grid.set_cell_raw((xi, yi), cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user