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