Properly bubble errors
This commit is contained in:
parent
5762fd868a
commit
21492876c5
@ -6,6 +6,7 @@ pub enum CalculatorError {
|
||||
NoSuchConstant,
|
||||
NoSuchRegister,
|
||||
NoSuchMacro,
|
||||
ParseError,
|
||||
}
|
||||
|
||||
impl CalculatorError {
|
||||
@ -21,6 +22,7 @@ impl CalculatorError {
|
||||
CalculatorError::NoSuchConstant => String::from("No such constant"),
|
||||
CalculatorError::NoSuchRegister => String::from("No such register"),
|
||||
CalculatorError::NoSuchMacro => String::from("No such macro"),
|
||||
CalculatorError::ParseError => String::from("Parse error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
245
src/main.rs
245
src/main.rs
@ -4,7 +4,7 @@
|
||||
mod calc;
|
||||
mod util;
|
||||
|
||||
use calc::constants::CalculatorMacro;
|
||||
use calc::errors::CalculatorError;
|
||||
use calc::operations::CalculatorOperation;
|
||||
use calc::Calculator;
|
||||
use std::cmp;
|
||||
@ -86,18 +86,23 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
)
|
||||
.split(f.size());
|
||||
|
||||
let msg = match &app.error_msg {
|
||||
Some(e) => vec![
|
||||
let msg = match (&app.error_msg, &app.state) {
|
||||
(Some(e), _) => vec![
|
||||
Span::raw("Error: "),
|
||||
Span::styled(e, Style::default().add_modifier(Modifier::RAPID_BLINK)),
|
||||
],
|
||||
None => vec![
|
||||
(None, AppState::Calculator) => vec![
|
||||
Span::raw("Press "),
|
||||
Span::styled("q", Style::default().add_modifier(Modifier::BOLD)),
|
||||
Span::raw(" to exit, "),
|
||||
Span::styled("h", Style::default().add_modifier(Modifier::BOLD)),
|
||||
Span::raw(" for help"),
|
||||
],
|
||||
(None, _) => vec![
|
||||
Span::raw("Press "),
|
||||
Span::styled("<esc>", Style::default().add_modifier(Modifier::BOLD)),
|
||||
Span::raw(" to exit"),
|
||||
],
|
||||
};
|
||||
|
||||
let text = Text::from(Spans::from(msg));
|
||||
@ -159,7 +164,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
<ret> => Dup l => Log\n\
|
||||
> => Swap L => Ln\n\
|
||||
e => E ^c => Constants\n\
|
||||
^m => Macros rR => Registers",
|
||||
m => Macros rR => Registers",
|
||||
},
|
||||
f,
|
||||
);
|
||||
@ -217,18 +222,23 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
})?;
|
||||
|
||||
if let Event::Input(key) = events.next()? {
|
||||
if handle_key(&mut app, &events, key) {
|
||||
break 'outer;
|
||||
app.error_msg = match handle_key(&mut app, &events, key) {
|
||||
// Exit the program
|
||||
Ok(true) => break 'outer Ok(()),
|
||||
Ok(false) => None,
|
||||
Err(e) => Some(e.message()),
|
||||
};
|
||||
}
|
||||
|
||||
for e in events.try_iter() {
|
||||
match e {
|
||||
Event::Input(key) => {
|
||||
if handle_key(&mut app, &events, key) {
|
||||
//return Ok(());
|
||||
break 'outer;
|
||||
}
|
||||
app.error_msg = match handle_key(&mut app, &events, key) {
|
||||
// Exit the program
|
||||
Ok(true) => break 'outer Ok(()),
|
||||
Ok(false) => None,
|
||||
Err(e) => Some(e.message()),
|
||||
};
|
||||
}
|
||||
Event::MacroEnd => app.current_macro = None,
|
||||
_ => continue,
|
||||
@ -237,170 +247,141 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
app.current_macro = None;
|
||||
}
|
||||
// TODO: Bubble up return Ok so we can handle saving
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_key(app: &mut App, events: &Events, key: Key) -> bool {
|
||||
fn handle_key(app: &mut App, events: &Events, key: Key) -> Result<bool, CalculatorError> {
|
||||
match &app.state {
|
||||
AppState::Calculator => {
|
||||
app.error_msg = None;
|
||||
match key {
|
||||
Key::Char('q') => {
|
||||
//process::exit(0);
|
||||
print!("XX");
|
||||
return true;
|
||||
AppState::Calculator => match key {
|
||||
Key::Char('q') => {
|
||||
return Ok(true);
|
||||
}
|
||||
Key::Ctrl('c') => {
|
||||
app.state = AppState::Constants;
|
||||
}
|
||||
Key::Char('r') => {
|
||||
app.state = AppState::Registers(RegisterState::Load);
|
||||
}
|
||||
Key::Char('R') => {
|
||||
app.state = AppState::Registers(RegisterState::Save);
|
||||
}
|
||||
Key::Char('m') => {
|
||||
app.state = AppState::Macros;
|
||||
}
|
||||
Key::Char('h') => {
|
||||
app.state = AppState::Help;
|
||||
}
|
||||
Key::Char(c @ '0'..='9') => {
|
||||
app.input.push(c);
|
||||
}
|
||||
Key::Char(c @ 'e') | Key::Char(c @ '.') => {
|
||||
if app.input.is_empty() {
|
||||
if let Ok(f) = app.calculator.pop() {
|
||||
app.input = f.to_string();
|
||||
} else {
|
||||
return Err(CalculatorError::NotEnoughStackEntries);
|
||||
}
|
||||
}
|
||||
Key::Ctrl('c') => {
|
||||
app.state = AppState::Constants;
|
||||
}
|
||||
Key::Char('r') => {
|
||||
app.state = AppState::Registers(RegisterState::Load);
|
||||
}
|
||||
Key::Char('R') => {
|
||||
app.state = AppState::Registers(RegisterState::Save);
|
||||
}
|
||||
Key::Char('m') => {
|
||||
app.state = AppState::Macros;
|
||||
}
|
||||
Key::Char('h') => {
|
||||
app.state = AppState::Help;
|
||||
}
|
||||
Key::Char(c @ '0'..='9') => {
|
||||
|
||||
if !app.input.contains(c) {
|
||||
app.input.push(c);
|
||||
}
|
||||
Key::Char(c @ 'e') | Key::Char(c @ '.') => {
|
||||
if app.input.is_empty() {
|
||||
if let Ok(x) = app.calculator.pop() {
|
||||
app.input = x.to_string();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if !app.input.contains(c) {
|
||||
app.input.push(c);
|
||||
}
|
||||
}
|
||||
Key::Char('\n') | Key::Char(' ') => {
|
||||
if app.input.is_empty() {
|
||||
calc_operation(app, '\n');
|
||||
} else {
|
||||
let mut tmp_input = app.input.clone();
|
||||
if tmp_input.ends_with('e') {
|
||||
let tmp_input = tmp_input.push('0');
|
||||
}
|
||||
|
||||
if let Ok(f) = tmp_input.parse::<f64>() {
|
||||
if app.calculator.push(f).is_ok() {
|
||||
app.input.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Key::Right => {
|
||||
calc_operation(app, '>');
|
||||
}
|
||||
Key::Down => {
|
||||
if let Ok(x) = app.calculator.pop() {
|
||||
app.input = x.to_string();
|
||||
}
|
||||
}
|
||||
Key::Backspace => {
|
||||
app.input.pop();
|
||||
}
|
||||
Key::Delete => {
|
||||
app.input.clear();
|
||||
}
|
||||
Key::Char(c) => {
|
||||
calc_operation(app, c);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Key::Char('\n') | Key::Char(' ') => {
|
||||
if app.input.is_empty() {
|
||||
calc_operation(app, '\n');
|
||||
} else {
|
||||
let mut tmp_input = app.input.clone();
|
||||
if tmp_input.ends_with('e') {
|
||||
let tmp_input = tmp_input.push('0');
|
||||
}
|
||||
|
||||
if let Ok(f) = tmp_input.parse::<f64>() {
|
||||
if app.calculator.push(f).is_ok() {
|
||||
app.input.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Key::Right => {
|
||||
calc_operation(app, '>');
|
||||
}
|
||||
Key::Down => {
|
||||
if let Ok(x) = app.calculator.pop() {
|
||||
app.input = x.to_string();
|
||||
}
|
||||
}
|
||||
Key::Backspace => {
|
||||
app.input.pop();
|
||||
}
|
||||
Key::Delete => {
|
||||
app.input.clear();
|
||||
}
|
||||
Key::Char(c) => {
|
||||
calc_operation(app, c);
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
AppState::Help => match key {
|
||||
Key::Esc | Key::Char('q') => {
|
||||
Key::Esc => {
|
||||
app.state = AppState::Calculator;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
AppState::Constants => match key {
|
||||
Key::Esc | Key::Char('q') => {
|
||||
Key::Esc => {
|
||||
app.state = AppState::Calculator;
|
||||
}
|
||||
Key::Char(c) => {
|
||||
app.error_msg = match app.calculator.push_constant(c) {
|
||||
Err(e) => Some(e.message()),
|
||||
Ok(()) => {
|
||||
app.input.clear();
|
||||
app.state = AppState::Calculator;
|
||||
None
|
||||
}
|
||||
}
|
||||
app.calculator.push_constant(c)?;
|
||||
app.input.clear();
|
||||
app.state = AppState::Calculator;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
AppState::Registers(task) => match key {
|
||||
Key::Esc | Key::Char('q') => {
|
||||
Key::Esc => {
|
||||
app.state = AppState::Calculator;
|
||||
}
|
||||
Key::Char(c) => match task {
|
||||
RegisterState::Save => {
|
||||
app.error_msg = match app.calculator.save_register(c) {
|
||||
Err(e) => Some(e.message()),
|
||||
Ok(()) => {
|
||||
app.input.clear();
|
||||
app.state = AppState::Calculator;
|
||||
None
|
||||
}
|
||||
Key::Char(c) => {
|
||||
match task {
|
||||
RegisterState::Save => {
|
||||
app.calculator.save_register(c)?;
|
||||
}
|
||||
RegisterState::Load => {
|
||||
app.calculator.push_register(c)?;
|
||||
}
|
||||
}
|
||||
RegisterState::Load => {
|
||||
app.error_msg = match app.calculator.push_register(c) {
|
||||
Err(e) => Some(e.message()),
|
||||
Ok(()) => {
|
||||
app.input.clear();
|
||||
app.state = AppState::Calculator;
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
app.input.clear();
|
||||
app.state = AppState::Calculator;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
AppState::Macros => match key {
|
||||
Key::Esc | Key::Char('q') => {
|
||||
Key::Esc => {
|
||||
app.state = AppState::Calculator;
|
||||
}
|
||||
Key::Char(c) => {
|
||||
if !app.input.is_empty() {
|
||||
//TODO: A better way to do this
|
||||
if let Ok(f) = app.input.parse::<f64>() {
|
||||
if app.calculator.push(f).is_ok() {
|
||||
app.input.clear();
|
||||
} else {
|
||||
return false;
|
||||
match app.calculator.push(f) {
|
||||
Ok(()) => app.input.clear(),
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
return Err(CalculatorError::ParseError);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Handle macros internally to the calculator
|
||||
app.error_msg = match app.calculator.get_macro(c) {
|
||||
Ok(CalculatorMacro { value, .. }) => {
|
||||
// let value = *value;
|
||||
events.fill_event_buf(value);
|
||||
app.state = AppState::Calculator;
|
||||
None
|
||||
}
|
||||
Err(e) => Some(e.message()),
|
||||
}
|
||||
let mac = app.calculator.get_macro(c)?;
|
||||
events.fill_event_buf(mac.value);
|
||||
app.state = AppState::Calculator;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
}
|
||||
return false;
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
fn calc_operation(app: &mut App, c: char) {
|
||||
|
Loading…
Reference in New Issue
Block a user