Properly implement interface
This commit is contained in:
parent
4600f5d31e
commit
fbedb044c5
22
src/calc.rs
22
src/calc.rs
@ -143,7 +143,7 @@ impl<'a> Calculator<'a> {
|
||||
Ok(())
|
||||
}
|
||||
'R' => {
|
||||
self.state = CalculatorState::WaitingForRegister(RegisterState::Load);
|
||||
self.state = CalculatorState::WaitingForRegister(RegisterState::Save);
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
@ -215,7 +215,24 @@ impl<'a> Calculator<'a> {
|
||||
self.state = CalculatorState::Normal;
|
||||
self.active_macros.clear();
|
||||
}
|
||||
pub fn backspace(&mut self) -> CalculatorResult<()> {
|
||||
self.l.pop();
|
||||
Ok(())
|
||||
}
|
||||
pub fn edit(&mut self) -> CalculatorResult<()> {
|
||||
if self.l.len() > 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.l = self
|
||||
.pop()
|
||||
.or(Err(CalculatorError::NotEnoughStackEntries))?
|
||||
.to_string();
|
||||
Ok(())
|
||||
}
|
||||
pub fn get_l(&mut self) -> &str {
|
||||
self.l.as_ref()
|
||||
}
|
||||
fn entry(&mut self, c: char) -> CalculatorResult<()> {
|
||||
match c {
|
||||
'0'..='9' => {
|
||||
@ -245,6 +262,9 @@ impl<'a> Calculator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_state(&self) -> &CalculatorState {
|
||||
&self.state
|
||||
}
|
||||
pub fn get_constants_iter(&'a self) -> CalculatorConstantsIter<'a> {
|
||||
self.constants.iter()
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ pub enum RegisterState {
|
||||
|
||||
pub enum CalculatorState {
|
||||
Normal,
|
||||
//Macro,
|
||||
WaitingForConstant,
|
||||
WaitingForMacro,
|
||||
WaitingForRegister(RegisterState),
|
||||
|
177
src/main.rs
177
src/main.rs
@ -4,12 +4,11 @@
|
||||
mod calc;
|
||||
mod util;
|
||||
|
||||
use calc::errors::{CalculatorError, CalculatorResult};
|
||||
use calc::constants::{CalculatorState, RegisterState};
|
||||
use calc::errors::CalculatorResult;
|
||||
use calc::Calculator;
|
||||
use std::cmp;
|
||||
use std::convert::TryFrom;
|
||||
use util::event::{Event, Events};
|
||||
//use util::event::T;
|
||||
use std::{error::Error, io};
|
||||
use termion::{event::Key, raw::IntoRawMode, screen::AlternateScreen};
|
||||
use tui::{
|
||||
@ -21,27 +20,19 @@ use tui::{
|
||||
widgets::{Block, Borders, Clear, List, ListItem, Paragraph},
|
||||
Terminal,
|
||||
};
|
||||
use util::event::{Event, Events};
|
||||
|
||||
struct Dimensions {
|
||||
width: u16,
|
||||
height: u16,
|
||||
}
|
||||
|
||||
enum RegisterState {
|
||||
Save,
|
||||
Load,
|
||||
}
|
||||
|
||||
enum AppState {
|
||||
Calculator,
|
||||
Help,
|
||||
Constants,
|
||||
Macros,
|
||||
Registers(RegisterState),
|
||||
}
|
||||
|
||||
struct App<'a> {
|
||||
input: String,
|
||||
calculator: Calculator<'a>,
|
||||
error_msg: Option<String>,
|
||||
state: AppState,
|
||||
@ -51,7 +42,6 @@ struct App<'a> {
|
||||
impl<'a> Default for App<'a> {
|
||||
fn default() -> App<'a> {
|
||||
App {
|
||||
input: String::new(),
|
||||
calculator: Calculator::default(),
|
||||
error_msg: None,
|
||||
state: AppState::Calculator,
|
||||
@ -121,11 +111,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
})
|
||||
.collect();
|
||||
|
||||
// stack.insert(
|
||||
// 0,
|
||||
// ListItem::new(Span::raw(format!("dbg: {}", chunks[2].height))),
|
||||
// );
|
||||
|
||||
for _ in 0..(chunks[1]
|
||||
.height
|
||||
.saturating_sub(stack.len() as u16)
|
||||
@ -138,15 +123,18 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
List::new(stack).block(Block::default().borders(Borders::ALL).title("Stack"));
|
||||
f.render_widget(stack, chunks[1]);
|
||||
|
||||
let input = Paragraph::new(app.input.as_ref())
|
||||
let input = Paragraph::new(app.calculator.get_l().as_ref())
|
||||
.style(Style::default())
|
||||
.block(Block::default().borders(Borders::ALL).title("Input"));
|
||||
f.render_widget(input, chunks[2]);
|
||||
|
||||
f.set_cursor(chunks[2].x + app.input.len() as u16 + 1, chunks[2].y + 1);
|
||||
f.set_cursor(
|
||||
chunks[2].x + app.calculator.get_l().len() as u16 + 1,
|
||||
chunks[2].y + 1,
|
||||
);
|
||||
|
||||
match &app.state {
|
||||
AppState::Help => {
|
||||
match (&app.state, app.calculator.get_state()) {
|
||||
(AppState::Help, _) => {
|
||||
draw_clippy_rect(
|
||||
ClippyRectangle {
|
||||
title: "Help",
|
||||
@ -171,7 +159,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
f,
|
||||
);
|
||||
}
|
||||
AppState::Constants => {
|
||||
(AppState::Calculator, CalculatorState::WaitingForConstant) => {
|
||||
draw_clippy_rect(
|
||||
ClippyRectangle {
|
||||
title: "Constants",
|
||||
@ -187,8 +175,8 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
f,
|
||||
);
|
||||
}
|
||||
AppState::Registers(state) => {
|
||||
let title = match state {
|
||||
(AppState::Calculator, CalculatorState::WaitingForRegister(register_state)) => {
|
||||
let title = match register_state {
|
||||
RegisterState::Save => "Registers (press char to save)",
|
||||
RegisterState::Load => "Registers",
|
||||
};
|
||||
@ -205,7 +193,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
f,
|
||||
);
|
||||
}
|
||||
AppState::Macros => {
|
||||
(AppState::Calculator, CalculatorState::WaitingForMacro) => {
|
||||
draw_clippy_rect(
|
||||
ClippyRectangle {
|
||||
title: "Macros",
|
||||
@ -252,167 +240,54 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
|
||||
fn handle_key(app: &mut App, events: &Events, key: Key) -> CalculatorResult<bool> {
|
||||
match &app.state {
|
||||
AppState::Calculator => match key {
|
||||
match (&app.state, app.calculator.get_state()) {
|
||||
(AppState::Calculator, CalculatorState::Normal) => 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('e') => {
|
||||
if app.input.is_empty() {
|
||||
let f = app
|
||||
.calculator
|
||||
.pop()
|
||||
.or(Err(CalculatorError::NotEnoughStackEntries))?;
|
||||
app.input = f.to_string();
|
||||
}
|
||||
|
||||
if !app.input.contains('e') {
|
||||
app.input.push('e');
|
||||
}
|
||||
}
|
||||
Key::Char('.') => {
|
||||
if !app.input.contains('.') {
|
||||
app.input.push('.');
|
||||
}
|
||||
}
|
||||
Key::Char('\n') | Key::Char(' ') => {
|
||||
if app.input.is_empty() {
|
||||
calc_operation(app, ' ')?;
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
app.calculator.take_input(' ')?;
|
||||
}
|
||||
Key::Right => {
|
||||
calc_operation(app, '>')?;
|
||||
app.calculator.take_input('>')?;
|
||||
}
|
||||
Key::Down => {
|
||||
// TODO: Internal calculator function
|
||||
if let Ok(x) = app.calculator.pop() {
|
||||
app.input = x.to_string();
|
||||
}
|
||||
app.calculator.edit()?;
|
||||
}
|
||||
Key::Backspace => {
|
||||
app.input.pop();
|
||||
}
|
||||
Key::Delete => {
|
||||
app.input.clear();
|
||||
app.calculator.backspace()?;
|
||||
}
|
||||
Key::Char(c) => {
|
||||
calc_operation(app, c)?;
|
||||
app.calculator.take_input(c)?;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
AppState::Help => match key {
|
||||
(AppState::Help, _) => match key {
|
||||
Key::Esc | Key::Char('q') => {
|
||||
app.state = AppState::Calculator;
|
||||
app.calculator.cancel();
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
AppState::Constants => match key {
|
||||
(AppState::Calculator, CalculatorState::WaitingForConstant)
|
||||
| (AppState::Calculator, CalculatorState::WaitingForRegister(_))
|
||||
| (AppState::Calculator, CalculatorState::WaitingForMacro) => match key {
|
||||
Key::Esc => {
|
||||
app.state = AppState::Calculator;
|
||||
app.calculator.cancel();
|
||||
}
|
||||
Key::Char(c) => {
|
||||
app.calculator.push_constant(c)?;
|
||||
app.input.clear();
|
||||
app.state = AppState::Calculator;
|
||||
app.calculator.cancel();
|
||||
app.calculator.take_input(c)?;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
AppState::Registers(task) => match key {
|
||||
Key::Esc => {
|
||||
app.state = AppState::Calculator;
|
||||
app.calculator.cancel();
|
||||
}
|
||||
// Key::Char(c) => {
|
||||
// match task {
|
||||
// RegisterState::Save => {
|
||||
// app.calculator.save_register(c)?;
|
||||
// }
|
||||
// RegisterState::Load => {
|
||||
// app.calculator.push_register(c)?;
|
||||
// }
|
||||
// }
|
||||
// app.input.clear();
|
||||
// app.state = AppState::Calculator;
|
||||
// }
|
||||
_ => {}
|
||||
},
|
||||
AppState::Macros => match key {
|
||||
Key::Esc => {
|
||||
app.state = AppState::Calculator;
|
||||
app.calculator.cancel();
|
||||
}
|
||||
// Key::Char(c) => {
|
||||
// if !app.input.is_empty() {
|
||||
// //TODO: A better way to do this
|
||||
// //Can use calc_operation in the future. Already performs this check
|
||||
// let f = app
|
||||
// .input
|
||||
// .parse::<f64>()
|
||||
// .or(Err(CalculatorError::ParseError))?;
|
||||
// app.calculator.push(f).and_then(|()| {
|
||||
// app.input.clear();
|
||||
// Ok(())
|
||||
// })?;
|
||||
// }
|
||||
|
||||
// // TODO: Handle macros internally to the calculator
|
||||
// let mac = app.calculator.get_macro(c)?;
|
||||
// events.fill_event_buf(mac.value);
|
||||
// app.state = AppState::Calculator;
|
||||
// }
|
||||
_ => {}
|
||||
},
|
||||
}
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
fn calc_operation(app: &mut App, c: char) -> CalculatorResult<()> {
|
||||
if !app.input.is_empty() {
|
||||
let f = app
|
||||
.input
|
||||
.parse::<f64>()
|
||||
.or(Err(CalculatorError::ParseError))?;
|
||||
app.calculator.push(f)?;
|
||||
app.input.clear();
|
||||
}
|
||||
|
||||
//let op = CalculatorOperation::from_char(c)?;
|
||||
app.calculator.take_input(c)
|
||||
//app.calculator.op(op)
|
||||
}
|
||||
|
||||
struct ClippyRectangle<'a> {
|
||||
title: &'a str,
|
||||
msg: &'a str,
|
||||
|
Loading…
Reference in New Issue
Block a user