Use method 1 for macro undos
This commit is contained in:
parent
e9ef4db202
commit
0e69681ab8
88
src/calc.rs
88
src/calc.rs
@ -20,6 +20,7 @@ enum OpArgs {
|
|||||||
struct CalculatorStateChange {
|
struct CalculatorStateChange {
|
||||||
pop: OpArgs,
|
pop: OpArgs,
|
||||||
push: OpArgs,
|
push: OpArgs,
|
||||||
|
within_macro: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Calculator<'a> {
|
pub struct Calculator<'a> {
|
||||||
@ -171,6 +172,12 @@ impl<'a> Calculator<'a> {
|
|||||||
// The macro needs to run in normal mode
|
// The macro needs to run in normal mode
|
||||||
self.state = CalculatorState::Normal;
|
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
|
// Record that we are running macro c
|
||||||
self.active_macros.insert(c);
|
self.active_macros.insert(c);
|
||||||
for c in value.chars() {
|
for c in value.chars() {
|
||||||
@ -271,36 +278,6 @@ impl<'a> Calculator<'a> {
|
|||||||
self.registers.iter()
|
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<bool> {
|
pub fn flush_l(&mut self) -> CalculatorResult<bool> {
|
||||||
if self.l.is_empty() {
|
if self.l.is_empty() {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
@ -311,10 +288,14 @@ impl<'a> Calculator<'a> {
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn within_macro(&self) -> bool {
|
||||||
|
!self.active_macros.is_empty()
|
||||||
|
}
|
||||||
fn push(&mut self, f: f64) -> CalculatorResult<()> {
|
fn push(&mut self, f: f64) -> CalculatorResult<()> {
|
||||||
self.direct_state_change(CalculatorStateChange {
|
self.direct_state_change(CalculatorStateChange {
|
||||||
pop: OpArgs::None,
|
pop: OpArgs::None,
|
||||||
push: OpArgs::Unary(f),
|
push: OpArgs::Unary(f),
|
||||||
|
within_macro: self.within_macro(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn pop(&mut self) -> CalculatorResult<f64> {
|
fn pop(&mut self) -> CalculatorResult<f64> {
|
||||||
@ -322,6 +303,7 @@ impl<'a> Calculator<'a> {
|
|||||||
self.direct_state_change(CalculatorStateChange {
|
self.direct_state_change(CalculatorStateChange {
|
||||||
pop: OpArgs::Unary(f),
|
pop: OpArgs::Unary(f),
|
||||||
push: OpArgs::None,
|
push: OpArgs::None,
|
||||||
|
within_macro: self.within_macro(),
|
||||||
})?;
|
})?;
|
||||||
Ok(f)
|
Ok(f)
|
||||||
}
|
}
|
||||||
@ -366,18 +348,50 @@ impl<'a> Calculator<'a> {
|
|||||||
CalculatorOperation::Pow => self.binary_op(|[a, b]| OpArgs::Unary(b.powf(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::E => self.binary_op(|[a, b]| OpArgs::Unary(b * 10.0f64.powf(a))),
|
||||||
CalculatorOperation::Undo => {
|
CalculatorOperation::Undo => {
|
||||||
|
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
|
let s = self
|
||||||
.undo_buf
|
.undo_buf
|
||||||
.pop()
|
.pop()
|
||||||
.ok_or_else(|| CalculatorError::EmptyHistory(String::from("undo")))?;
|
.ok_or_else(|| CalculatorError::EmptyHistory(String::from("undo")))?;
|
||||||
return self.apply_state_change(s, false);
|
let stop = !s.within_macro;
|
||||||
|
self.apply_state_change(s, false)?;
|
||||||
|
if stop {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
undone_already = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CalculatorOperation::Redo => {
|
CalculatorOperation::Redo => {
|
||||||
let s = self
|
let mut redone_already = false;
|
||||||
.redo_buf
|
loop {
|
||||||
.pop()
|
let s = match self.redo_buf.pop() {
|
||||||
.ok_or_else(|| CalculatorError::EmptyHistory(String::from("redo")))?;
|
None => {
|
||||||
return self.apply_state_change(s, true);
|
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
|
// Macros are a no-op as an operator
|
||||||
CalculatorOperation::Macro(_) => {
|
CalculatorOperation::Macro(_) => {
|
||||||
@ -399,6 +413,7 @@ impl<'a> Calculator<'a> {
|
|||||||
Ok(CalculatorStateChange {
|
Ok(CalculatorStateChange {
|
||||||
pop: OpArgs::Unary(*arg),
|
pop: OpArgs::Unary(*arg),
|
||||||
push: op(*arg),
|
push: op(*arg),
|
||||||
|
within_macro: self.within_macro(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn binary_op(
|
fn binary_op(
|
||||||
@ -418,6 +433,7 @@ impl<'a> Calculator<'a> {
|
|||||||
Ok(CalculatorStateChange {
|
Ok(CalculatorStateChange {
|
||||||
pop: OpArgs::Binary(args),
|
pop: OpArgs::Binary(args),
|
||||||
push: op(args),
|
push: op(args),
|
||||||
|
within_macro: self.within_macro(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user