From 0e69681ab82dfdaf7a0ec3b30249f588640ca617 Mon Sep 17 00:00:00 2001 From: Austen Adler Date: Thu, 29 Apr 2021 22:08:33 -0400 Subject: [PATCH] Use method 1 for macro undos --- src/calc.rs | 96 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 40 deletions(-) diff --git a/src/calc.rs b/src/calc.rs index 9a862d7..cf49dba 100644 --- a/src/calc.rs +++ b/src/calc.rs @@ -20,6 +20,7 @@ enum OpArgs { struct CalculatorStateChange { pop: OpArgs, push: OpArgs, + within_macro: bool, } pub struct Calculator<'a> { @@ -171,6 +172,12 @@ impl<'a> Calculator<'a> { // The macro needs to run in normal mode self.state = CalculatorState::Normal; + // Add a no-op undo event as a stopgap for undo/redo operations (fixes undo after multiple macros running) + // self.direct_state_change(CalculatorStateChange { + // pop: OpArgs::None, + // push: OpArgs::None, + // within_macro: self.within_macro(), + // })?; // Record that we are running macro c self.active_macros.insert(c); for c in value.chars() { @@ -271,36 +278,6 @@ impl<'a> Calculator<'a> { self.registers.iter() } - // pub fn push_constant(&mut self, key: char) -> CalculatorResult<()> { - // match self.constants.get(&key) { - // Some(CalculatorConstant { value, .. }) => { - // let value = *value; - // self.push(value) - // } - // None => Err(CalculatorError::NoSuchConstant(key)), - // } - // } - // pub fn push_register(&mut self, key: char) -> CalculatorResult<()> { - // match self.registers.get(&key) { - // Some(f) => { - // let f = *f; - // self.push(f) - // } - // None => Err(CalculatorError::NoSuchRegister), - // } - // } - // pub fn save_register(&mut self, key: char) -> CalculatorResult<()> { - // let f = self.pop()?; - // self.registers.insert(key, f); - // Ok(()) - // } - // pub fn get_macro(&mut self, key: char) -> Result<&CalculatorMacro<'a>, CalculatorError> { - // match self.macros.get(&key) { - // Some(m) => Ok(m), - // None => Err(CalculatorError::NoSuchMacro(key)), - // } - // } - pub fn flush_l(&mut self) -> CalculatorResult { if self.l.is_empty() { Ok(false) @@ -311,10 +288,14 @@ impl<'a> Calculator<'a> { Ok(true) } } + fn within_macro(&self) -> bool { + !self.active_macros.is_empty() + } fn push(&mut self, f: f64) -> CalculatorResult<()> { self.direct_state_change(CalculatorStateChange { pop: OpArgs::None, push: OpArgs::Unary(f), + within_macro: self.within_macro(), }) } fn pop(&mut self) -> CalculatorResult { @@ -322,6 +303,7 @@ impl<'a> Calculator<'a> { self.direct_state_change(CalculatorStateChange { pop: OpArgs::Unary(f), push: OpArgs::None, + within_macro: self.within_macro(), })?; Ok(f) } @@ -366,18 +348,50 @@ impl<'a> Calculator<'a> { CalculatorOperation::Pow => self.binary_op(|[a, b]| OpArgs::Unary(b.powf(a))), CalculatorOperation::E => self.binary_op(|[a, b]| OpArgs::Unary(b * 10.0f64.powf(a))), CalculatorOperation::Undo => { - let s = self - .undo_buf - .pop() - .ok_or_else(|| CalculatorError::EmptyHistory(String::from("undo")))?; - return self.apply_state_change(s, false); + let mut undone_already = false; + loop { + if undone_already { + let s = self + .undo_buf + .last() + .ok_or_else(|| CalculatorError::EmptyHistory(String::from("undo")))?; + if !s.within_macro { + return Ok(()); + } + } + + let s = self + .undo_buf + .pop() + .ok_or_else(|| CalculatorError::EmptyHistory(String::from("undo")))?; + let stop = !s.within_macro; + self.apply_state_change(s, false)?; + if stop { + return Ok(()); + } + undone_already = true; + } } CalculatorOperation::Redo => { - let s = self - .redo_buf - .pop() - .ok_or_else(|| CalculatorError::EmptyHistory(String::from("redo")))?; - return self.apply_state_change(s, true); + let mut redone_already = false; + loop { + let s = match self.redo_buf.pop() { + None => { + if redone_already { + return Ok(()); + } + return Err(CalculatorError::EmptyHistory(String::from("redo"))); + } + Some(s) => { + let stop = !s.within_macro; + self.apply_state_change(s, true)?; + if stop { + return Ok(()); + } + redone_already = true; + } + }; + } } // Macros are a no-op as an operator CalculatorOperation::Macro(_) => { @@ -399,6 +413,7 @@ impl<'a> Calculator<'a> { Ok(CalculatorStateChange { pop: OpArgs::Unary(*arg), push: op(*arg), + within_macro: self.within_macro(), }) } fn binary_op( @@ -418,6 +433,7 @@ impl<'a> Calculator<'a> { Ok(CalculatorStateChange { pop: OpArgs::Binary(args), push: op(args), + within_macro: self.within_macro(), }) }