From 702cf74647417535ac65d37f04b3776c00adaca1 Mon Sep 17 00:00:00 2001 From: electria Date: Wed, 14 Oct 2026 16:50:51 -0700 Subject: [PATCH 1/2] feat: generalize splitting for plus.minus --- src/formatting.rs | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/formatting.rs b/src/formatting.rs index 7c207f5..a278c4b 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -3,15 +3,7 @@ use rug::Float; use crate::nodes::{self, Error}; pub fn pretty_eval(input: &str, max_digits: usize) -> Result { - let (prefix, deliminator, input) = input - .rsplit_once('=') - .map(|(p, i)| (p, "= ", i)) - .unwrap_or_else(|| { - input - .rsplit_once('&') - .map(|(p, i)| (p, "& ", i)) - .unwrap_or(("", "", input)) - }); + let (prefix, deliminator, input) = input.rsplit_once_any(&["plus.minus ", "& ", "= "]); // no need to remove the character here, // as we ignore it in all other logic already @@ -39,6 +31,26 @@ pub fn pretty_eval(input: &str, max_digits: usize) -> Result { .replace('e', " * 10^")) } +trait StrExt { + fn rsplit_once_any<'a>( + &'a self, + delimiters: &[&'static str], + ) -> (&'a str, &'static str, &'a str); +} +impl StrExt for str { + fn rsplit_once_any<'a>( + &'a self, + delimiters: &[&'static str], + ) -> (&'a str, &'static str, &'a str) { + for delimiter in delimiters { + if let Some((prefix, suffix)) = self.rsplit_once(delimiter) { + return (prefix, delimiter, suffix); + } + } + return ("", "", self); + } +} + pub fn get_significant_digits(n: &Float) -> usize { let raw_string = n.to_string().replace('.', ""); @@ -98,6 +110,14 @@ mod tests { assert_eq!(pretty_eval("11.111111", 10).unwrap(), "11.111111"); } + #[test] + fn plus_minus() { + assert_eq!( + pretty_eval("y & = plus.minus sqrt(15.5) \\", 10).unwrap(), + "y & = plus.minus 3.937003937 \\" + ); + } + #[test] fn basic_get_significant_digits() { let many_zeros = eval("14.00643 + 1.00784 * 4 + 35.446 + 15.9994 * 4"); From 12455924e150823ea2e340ad59db08d9720edad0 Mon Sep 17 00:00:00 2001 From: electria Date: Wed, 14 Oct 2026 16:52:07 -0700 Subject: [PATCH 2/2] refactor: create constant for tests --- src/formatting.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/formatting.rs b/src/formatting.rs index a278c4b..bf321bc 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -87,33 +87,34 @@ pub fn get_significant_digits(n: &Float) -> usize { #[cfg(test)] mod tests { use super::*; + const MAX_DIGITS: usize = 10; fn eval(s: &str) -> Float { crate::nodes::eval(s).unwrap() } #[test] fn character_readdition() { - assert_eq!(pretty_eval(" = 11", 10).unwrap(), " = 11"); - assert_eq!(pretty_eval(" &= 11", 10).unwrap(), " &= 11"); - assert_eq!(pretty_eval(" & 11", 10).unwrap(), " & 11"); - assert_eq!(pretty_eval(" & 11 \\", 10).unwrap(), " & 11 \\"); + assert_eq!(pretty_eval(" = 11", MAX_DIGITS).unwrap(), " = 11"); + assert_eq!(pretty_eval(" &= 11", MAX_DIGITS).unwrap(), " &= 11"); + assert_eq!(pretty_eval(" & 11", MAX_DIGITS).unwrap(), " & 11"); + assert_eq!(pretty_eval(" & 11 \\", MAX_DIGITS).unwrap(), " & 11 \\"); } #[test] fn basic_output_up_to_999() { - assert_eq!(pretty_eval("1", 10).unwrap(), "1"); - assert_eq!(pretty_eval("10", 10).unwrap(), "10"); - assert_eq!(pretty_eval("100", 10).unwrap(), "100"); - assert_eq!(pretty_eval("999", 10).unwrap(), "999"); - assert_eq!(pretty_eval("1000", 10).unwrap(), "1 * 10^3"); + assert_eq!(pretty_eval("1", MAX_DIGITS).unwrap(), "1"); + assert_eq!(pretty_eval("10", MAX_DIGITS).unwrap(), "10"); + assert_eq!(pretty_eval("100", MAX_DIGITS).unwrap(), "100"); + assert_eq!(pretty_eval("999", MAX_DIGITS).unwrap(), "999"); + assert_eq!(pretty_eval("1000", MAX_DIGITS).unwrap(), "1 * 10^3"); - assert_eq!(pretty_eval("11.111111", 10).unwrap(), "11.111111"); + assert_eq!(pretty_eval("11.111111", MAX_DIGITS).unwrap(), "11.111111"); } #[test] fn plus_minus() { assert_eq!( - pretty_eval("y & = plus.minus sqrt(15.5) \\", 10).unwrap(), + pretty_eval("y & = plus.minus sqrt(15.5) \\", MAX_DIGITS).unwrap(), "y & = plus.minus 3.937003937 \\" ); }