aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/input.rs45
-rw-r--r--src/lib.rs40
-rw-r--r--src/main.rs112
-rw-r--r--src/ui.rs30
4 files changed, 117 insertions, 110 deletions
diff --git a/src/input.rs b/src/input.rs
new file mode 100644
index 0000000..5ffaec8
--- /dev/null
+++ b/src/input.rs
@@ -0,0 +1,45 @@
+use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
+
+use crate::{Calculator, Operator, Signal};
+
+impl Calculator {
+ pub fn handle_input(&mut self, key: KeyEvent) -> Signal {
+ match key.modifiers {
+ KeyModifiers::CONTROL => match key.code {
+ KeyCode::Char('c') => {
+ return Signal::Exit;
+ }
+ _ => {}
+ },
+ KeyModifiers::NONE => match key.code {
+ KeyCode::Char('q') => {
+ return Signal::Exit;
+ }
+ KeyCode::Char(c) => {
+ if c.is_ascii_digit() {
+ self.input_buffer.push(c);
+ } else if c == '.' && !self.input_buffer.contains('.') {
+ if self.input_buffer.len() == 0 {
+ self.input_buffer.push('0');
+ }
+ self.input_buffer.push(c);
+ } else if let Ok(op) = Operator::parse(c) {
+ if self.input_buffer.len() > 0 {
+ self.push_buffer_to_stack();
+ }
+ self.perform_operation(op);
+ }
+ }
+ KeyCode::Enter if self.input_buffer.len() > 0 => {
+ self.push_buffer_to_stack();
+ }
+ KeyCode::Backspace => {
+ self.input_buffer.pop();
+ }
+ _ => {}
+ },
+ _ => {}
+ }
+ return Signal::None;
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index e08796d..79210fc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,40 @@
+mod input;
pub mod ui;
+#[derive(Default)]
+pub struct Calculator {
+ stack: Vec<f64>,
+ input_buffer: String,
+}
+
+impl Calculator {
+ fn push_buffer_to_stack(&mut self) {
+ self.stack.push(self.input_buffer.parse::<f64>().unwrap());
+ self.input_buffer = String::new();
+ }
+
+ fn perform_operation(&mut self, op: Operator) {
+ let rhs = match self.stack.pop() {
+ Some(f) => f,
+ None => {
+ return;
+ }
+ };
+ let lhs = match self.stack.pop() {
+ Some(f) => f,
+ None => {
+ return;
+ }
+ };
+ match op {
+ Operator::Add => self.stack.push(lhs + rhs),
+ Operator::Sub => self.stack.push(lhs - rhs),
+ Operator::Mul => self.stack.push(lhs * rhs),
+ Operator::Div => self.stack.push(lhs / rhs),
+ }
+ }
+}
+
pub enum Operator {
Add,
Sub,
@@ -20,3 +55,8 @@ impl Operator {
}
pub struct ParseOperatorError(char);
+
+pub enum Signal {
+ None,
+ Exit,
+}
diff --git a/src/main.rs b/src/main.rs
index 89c47aa..be9f440 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,114 +1,8 @@
-use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyModifiers};
+use crossterm::event::{self, Event};
use std::io;
-use tui::{
- backend::Backend,
- layout::{Constraint, Direction, Layout},
- widgets::{List, ListItem, Paragraph},
- Frame, Terminal,
-};
+use tui::{backend::Backend, Terminal};
-use pfc::{ui, Operator};
-
-enum Signal {
- None,
- Exit,
-}
-
-#[derive(Default)]
-struct Calculator {
- stack: Vec<f64>,
- input_buffer: String,
-}
-
-impl Calculator {
- fn handle_input(&mut self, key: KeyEvent) -> Signal {
- match key.modifiers {
- KeyModifiers::CONTROL => match key.code {
- KeyCode::Char('c') => {
- return Signal::Exit;
- }
- _ => {}
- },
- KeyModifiers::NONE => match key.code {
- KeyCode::Char('q') => {
- return Signal::Exit;
- }
- KeyCode::Char(c) => {
- if c.is_ascii_digit() {
- self.input_buffer.push(c);
- } else if c == '.' && !self.input_buffer.contains('.') {
- if self.input_buffer.len() == 0 {
- self.input_buffer.push('0');
- }
- self.input_buffer.push(c);
- } else if let Ok(op) = Operator::parse(c) {
- if self.input_buffer.len() > 0 {
- self.push_buffer_to_stack();
- }
- self.perform_operation(op);
- }
- }
- KeyCode::Enter if self.input_buffer.len() > 0 => {
- self.push_buffer_to_stack();
- }
- KeyCode::Backspace => {
- self.input_buffer.pop();
- }
- _ => {}
- },
- _ => {}
- }
- return Signal::None;
- }
-
- fn draw<B: Backend>(&self, f: &mut Frame<B>) {
- let chunks = Layout::default()
- .direction(Direction::Vertical)
- .constraints(
- [
- Constraint::Max(u16::MAX),
- Constraint::Length(self.stack.len() as u16),
- Constraint::Length(1),
- ]
- .as_ref(),
- )
- .split(f.size());
-
- let items: Vec<ListItem> = (self.stack)
- .iter()
- .map(|f| ListItem::new(format!("{}", f)))
- .collect();
- f.render_widget(List::new(items), chunks[1]);
-
- f.render_widget(Paragraph::new(self.input_buffer.as_str()), chunks[2]);
- }
-
- fn perform_operation(&mut self, op: Operator) {
- let rhs = match self.stack.pop() {
- Some(f) => f,
- None => {
- return;
- }
- };
- let lhs = match self.stack.pop() {
- Some(f) => f,
- None => {
- return;
- }
- };
- match op {
- Operator::Add => self.stack.push(lhs + rhs),
- Operator::Sub => self.stack.push(lhs - rhs),
- Operator::Mul => self.stack.push(lhs * rhs),
- Operator::Div => self.stack.push(lhs / rhs),
- }
- }
-
- fn push_buffer_to_stack(&mut self) {
- self.stack.push(self.input_buffer.parse::<f64>().unwrap());
- self.input_buffer = String::new();
- }
-}
+use pfc::{ui, Calculator, Signal};
fn main() -> io::Result<()> {
let calculator = Calculator::default();
diff --git a/src/ui.rs b/src/ui.rs
index 9133f1c..bb5057d 100644
--- a/src/ui.rs
+++ b/src/ui.rs
@@ -6,9 +6,37 @@ use crossterm::{
use std::io;
use tui::{
backend::{Backend, CrosstermBackend},
- Terminal,
+ layout::{Constraint, Direction, Layout},
+ widgets::{List, ListItem, Paragraph},
+ Frame, Terminal,
};
+use crate::Calculator;
+
+impl Calculator {
+ pub fn draw<B: Backend>(&self, f: &mut Frame<B>) {
+ let chunks = Layout::default()
+ .direction(Direction::Vertical)
+ .constraints(
+ [
+ Constraint::Max(u16::MAX),
+ Constraint::Length(self.stack.len() as u16),
+ Constraint::Length(1),
+ ]
+ .as_ref(),
+ )
+ .split(f.size());
+
+ let items: Vec<ListItem> = (self.stack)
+ .iter()
+ .map(|f| ListItem::new(format!("{}", f)))
+ .collect();
+ f.render_widget(List::new(items), chunks[1]);
+
+ f.render_widget(Paragraph::new(self.input_buffer.as_str()), chunks[2]);
+ }
+}
+
pub fn init_terminal() -> Result<Terminal<CrosstermBackend<io::Stdout>>, io::Error> {
enable_raw_mode()?;
let mut stdout = io::stdout();