diff --git a/src/app/logic/calc.rs b/src/app/logic/calc.rs index bad40e1..c04d894 100644 --- a/src/app/logic/calc.rs +++ b/src/app/logic/calc.rs @@ -241,8 +241,6 @@ impl Grid { /// Only evaluates equations, such as `=10` or `=A1/C2`, not /// strings or numbers. pub fn evaluate(&self, mut eq: &str) -> Result { - let original_equation = eq; - if eq.starts_with('=') { eq = &eq[1..]; } else { @@ -271,49 +269,6 @@ impl Grid { } Err(e) => match e { EvalexprError::VariableIdentifierNotFound(var_not_found) => { - // the identifier might be a range: A:A - let v = var_not_found.split(':').collect::>(); - if v.len() == 2 { - let start_col = v[0]; - let end_col = v[1]; - - let as_index = |s: &str| { - s.char_indices().map(|(a, b)| Grid::char_to_idx((a, &b))).fold(0, |a, b| a + b) - }; - - let start_idx = as_index(start_col); - let end_idx = as_index(end_col); - - let mut buf = Vec::new(); - - for x in start_idx..=end_idx { - for y in 0..=self.max_y_at_x(x) { - if let Some(s) = self.get_cell_raw(x, y) { - match s { - super::calc::CellType::Number(n) => buf.push(n.to_string()), - super::calc::CellType::String(_) => (), - super::calc::CellType::Equation(e) => buf.push(e.to_string()), - }; - } - } - } - let start = original_equation.find(&var_not_found).expect("It should be here"); - let end = start + var_not_found.len(); - - let res = buf.iter().enumerate().map(|(i,b )| { - if i == buf.len()-1 { - // last cell - b.to_owned() - } else { - format!("{b},") - } - }).collect::(); - - let new_eq = format!("{}{}{}", &original_equation[..start], res, &original_equation[end..]); - - // FIXME this might be a dangerous recursion, as I don't think its bounded right now - return self.evaluate(&new_eq) - } return Err(format!("\"{var_not_found}\" is not a variable")); } EvalexprError::TypeError { diff --git a/src/app/logic/ctx.rs b/src/app/logic/ctx.rs index edf48ad..f061fbb 100644 --- a/src/app/logic/ctx.rs +++ b/src/app/logic/ctx.rs @@ -14,6 +14,35 @@ pub struct CallbackContext<'a> { } impl<'a> CallbackContext<'a> { + fn expand_range(&self, range: &str) -> Option> { + let v = range.split(':').collect::>(); + if v.len() == 2 { + let start_col = v[0]; + let end_col = v[1]; + + let as_index = |s: &str| s.char_indices().map(|(a, b)| Grid::char_to_idx((a, &b))).fold(0, |a, b| a + b); + + let start_idx = as_index(start_col); + let end_idx = as_index(end_col); + + let mut buf = Vec::new(); + + for x in start_idx..=end_idx { + for y in 0..=self.variables.max_y_at_x(x) { + if let Some(s) = self.variables.get_cell_raw(x, y) { + match s { + super::calc::CellType::Number(n) => buf.push(n.to_string()), + super::calc::CellType::String(_) => (), + super::calc::CellType::Equation(e) => buf.push(e.to_string()), + }; + } + } + } + return Some(buf); + } + None + } + fn get_functions() -> HashMap> { let mut functions = HashMap::new(); @@ -75,21 +104,6 @@ impl<'a> CallbackContext<'a> { } } - #[allow(dead_code)] - pub fn clear_variables(&mut self) { - () - } - - #[allow(dead_code)] - pub fn clear_functions(&mut self) { - () - } - - #[allow(dead_code)] - pub fn clear(&mut self) { - self.clear_variables(); - self.clear_functions(); - } } impl<'a> Context for CallbackContext<'a> { @@ -113,6 +127,8 @@ impl<'a> Context for CallbackContext<'a> { // deep we've gone. return None; } + // remove the equals sign from the beginning, as that + // tries to set variables with our evaluation lib match eval_with_context(&eq[1..], self) { Ok(e) => return Some(e), Err(e) => { @@ -130,6 +146,18 @@ impl<'a> Context for CallbackContext<'a> { } } } + } else { + // identifier not found in cells, might be range + if let Some(v) = self.expand_range(identifier) { + dbg!(&v); + let mut vals = Vec::new(); + for v in v { + if let Some(value) = self.get_value(&v) { + vals.push(value); + } + } + return Some(Value::Tuple(vals)); + } } return None; }