From 4e17a27eb8d36868bcf7e1edf32affd84412a1f4 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Sat, 22 Jul 2023 21:30:53 -0230 Subject: init go module --- src/function.rs | 61 ---------------------------- src/input.rs | 94 ------------------------------------------- src/lib.rs | 122 -------------------------------------------------------- src/main.rs | 24 ----------- src/ui.rs | 106 ------------------------------------------------ 5 files changed, 407 deletions(-) delete mode 100644 src/function.rs delete mode 100644 src/input.rs delete mode 100644 src/lib.rs delete mode 100644 src/main.rs delete mode 100644 src/ui.rs (limited to 'src') diff --git a/src/function.rs b/src/function.rs deleted file mode 100644 index bb6462d..0000000 --- a/src/function.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::AngleMode; - -pub enum Function { - Sin, // Sine - Cos, // Cosine - Tan, // Tangent - Asin, // Inverse sine - Acos, // Inverse cosine - Atan, // Inverse tangent - Deg, // Convert from radians to degrees - Rad, // Convert from degrees to radians -} - -impl Function { - pub fn parse(s: &str) -> Result { - match s { - "sin" => Ok(Self::Sin), - "cos" => Ok(Self::Cos), - "tan" => Ok(Self::Tan), - "asin" => Ok(Self::Asin), - "acos" => Ok(Self::Acos), - "atan" => Ok(Self::Atan), - "deg" => Ok(Self::Deg), - "rad" => Ok(Self::Rad), - _ => Err(ParseFunctionError(s.to_string())), - } - } - - pub fn call(&self, val: f64, angle_mode: AngleMode) -> f64 { - match self { - Self::Sin => match angle_mode { - AngleMode::Degrees => val.to_radians().sin(), - AngleMode::Radians => val.sin(), - }, - Self::Cos => match angle_mode { - AngleMode::Degrees => val.to_radians().cos(), - AngleMode::Radians => val.cos(), - }, - Self::Tan => match angle_mode { - AngleMode::Degrees => val.to_radians().tan(), - AngleMode::Radians => val.tan(), - }, - Self::Asin => match angle_mode { - AngleMode::Degrees => val.asin().to_degrees(), - AngleMode::Radians => val.asin(), - }, - Self::Acos => match angle_mode { - AngleMode::Degrees => val.acos().to_degrees(), - AngleMode::Radians => val.acos(), - }, - Self::Atan => match angle_mode { - AngleMode::Degrees => val.atan().to_degrees(), - AngleMode::Radians => val.atan(), - }, - Self::Deg => val.to_degrees(), - Self::Rad => val.to_radians(), - } - } -} - -pub struct ParseFunctionError(String); diff --git a/src/input.rs b/src/input.rs deleted file mode 100644 index 2d982e5..0000000 --- a/src/input.rs +++ /dev/null @@ -1,94 +0,0 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; - -use crate::{Calculator, Constant, Function, 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::SHIFT => match key.code { - KeyCode::Char('Q') => { - return Signal::Exit; - } - KeyCode::Char('J' | 'K') => self.swap(), - KeyCode::Char('D') => { - self.input_buffer = String::new(); - } - KeyCode::Char('C') => self.clear(), - KeyCode::Char('A') => { - self.angle_mode = self.angle_mode.toggle(); - } - KeyCode::Char('N') => { - if self.input_buffer.len() > 0 { - if let Ok(f) = self.input_buffer.parse::() { - self.input_buffer = format!("{}", -f); - } - } else if let Some(v) = self.stack.pop() { - self.stack.push(-v); - } - } - _ => {} - }, - KeyModifiers::NONE => match key.code { - KeyCode::Char(c) => self.push_to_buffer(c), - KeyCode::Backspace => { - self.input_buffer.pop(); - } - KeyCode::Enter => { - if let Ok(func) = Function::parse(&self.input_buffer) { - if let Some(val) = self.stack.pop() { - self.stack.push(func.call(val, self.angle_mode)); - } - } else if let Ok(c) = Constant::parse(&self.input_buffer) { - self.stack.push(c.value()); - } else if let Ok(bu) = self.input_buffer.parse::() { - self.stack.push(bu); - } - self.input_buffer = String::new(); - } - _ => {} - }, - _ => {} - } - return Signal::None; - } - - fn push_to_buffer(&mut self, c: char) { - 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 let Ok(c) = Constant::parse(&self.input_buffer) { - self.stack.push(c.value()); - } else if let Ok(f) = self.input_buffer.parse::() { - self.stack.push(f); - } - self.input_buffer = String::new(); - self.perform_operation(op); - } else { - self.input_buffer.push(c); - } - } - - fn swap(&mut self) { - if let Some(st) = self.stack.pop() { - if let Ok(bu) = self.input_buffer.parse::() { - self.stack.push(bu); - } - self.input_buffer = format!("{}", st); - } - } - - // Clear stack and input buffer. - fn clear(&mut self) { - self.input_buffer = String::new(); - self.stack = Vec::new(); - } -} diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index db316f0..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,122 +0,0 @@ -use std::{ - f64::consts::{E, PI}, - fmt::{self, Display, Formatter}, -}; - -mod function; -mod input; -pub mod ui; - -pub use function::Function; - -#[derive(Default)] -pub struct Calculator { - stack: Vec, - input_buffer: String, - angle_mode: AngleMode, -} - -impl Calculator { - 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; - } - }; - self.stack.push(match op { - Operator::Add => lhs + rhs, - Operator::Sub => lhs - rhs, - Operator::Mul => lhs * rhs, - Operator::Div => lhs / rhs, - Operator::Exp => lhs.powf(rhs), - }); - } -} - -#[derive(Default, Copy, Clone, PartialEq)] -pub enum AngleMode { - #[default] - Degrees, - Radians, -} - -impl AngleMode { - fn toggle(&self) -> Self { - match self { - Self::Degrees => Self::Radians, - Self::Radians => Self::Degrees, - } - } -} - -impl Display for AngleMode { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!( - f, - "{}", - match self { - Self::Degrees => "deg", - Self::Radians => "rad", - } - ) - } -} - -enum Operator { - Add, - Sub, - Mul, - Div, - Exp, -} - -impl Operator { - fn parse(c: char) -> Result { - match c { - '+' => Ok(Self::Add), - '-' => Ok(Self::Sub), - '*' => Ok(Self::Mul), - '/' => Ok(Self::Div), - '^' => Ok(Self::Exp), - _ => Err(ParseOperatorError(c)), - } - } -} - -struct ParseOperatorError(char); - -enum Constant { - Pi, // Archimedes’ constant (π) - E, // Euler's number (e) -} - -impl Constant { - fn parse(s: &str) -> Result { - match s { - "pi" => Ok(Self::Pi), - "e" => Ok(Self::E), - _ => Err(ParseConstantError(s.to_string())), - } - } - - fn value(&self) -> f64 { - match self { - Self::Pi => PI, - Self::E => E, - } - } -} - -struct ParseConstantError(String); - -pub enum Signal { - None, - Exit, -} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 85e3888..0000000 --- a/src/main.rs +++ /dev/null @@ -1,24 +0,0 @@ -use crossterm::event::{self, Event}; -use std::io; - -use pfc::{ui, Calculator, Signal}; - -fn main() -> io::Result<()> { - let mut terminal = ui::init_terminal()?; - let mut calculator = Calculator::default(); - - let result = || -> io::Result<()> { - loop { - terminal.draw(|f| calculator.draw(f))?; - - if let Event::Key(key) = event::read()? { - if let Signal::Exit = calculator.handle_input(key) { - return Ok(()); - } - } - } - }(); - - ui::cleanup_terminal(terminal)?; - result -} diff --git a/src/ui.rs b/src/ui.rs deleted file mode 100644 index 76ecaf5..0000000 --- a/src/ui.rs +++ /dev/null @@ -1,106 +0,0 @@ -use crossterm::{ - execute, - terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, -}; -use std::io; -use tui::{ - backend::{Backend, CrosstermBackend}, - layout::{Alignment, Constraint, Direction, Layout, Rect}, - style::{Modifier, Style}, - text::{Span, Spans}, - widgets::{Block, Borders, List, ListItem, Paragraph, Widget}, - Frame, Terminal, -}; - -use crate::{AngleMode, Calculator, Constant, Function}; - -const WIDTH: u16 = 32; - -impl Calculator { - pub fn draw(&self, f: &mut Frame) { - let chunks = layout(self.stack.len(), f.size()); - f.render_widget(version_number_widget(), chunks[0]); - f.render_widget(angle_mode_widget(self.angle_mode), chunks[2]); - f.render_widget(stack_widget(&self.stack), chunks[3]); - f.render_widget(input_buffer_widget(&self.input_buffer), chunks[4]); - } -} - -pub fn init_terminal() -> Result>, io::Error> { - enable_raw_mode()?; - let mut stdout = io::stdout(); - execute!(stdout, EnterAlternateScreen)?; - let backend = CrosstermBackend::new(stdout); - Terminal::new(backend) -} - -pub fn cleanup_terminal(mut terminal: Terminal) -> Result<(), io::Error> -where - B: Backend + io::Write, -{ - disable_raw_mode()?; - execute!(terminal.backend_mut(), LeaveAlternateScreen,)?; - terminal.show_cursor()?; - Ok(()) -} - -fn layout(stack_size: usize, frame_size: Rect) -> Vec { - let columns = Layout::default() - .direction(Direction::Horizontal) - .constraints([Constraint::Length(WIDTH), Constraint::Max(u16::MAX)].as_ref()) - .split(frame_size); - - Layout::default() - .direction(Direction::Vertical) - .constraints( - [ - Constraint::Length(1), // Version number - Constraint::Max(u16::MAX), // Fill - Constraint::Length(1), // Angle mode - Constraint::Length(stack_size as u16 + 2), // Stack - Constraint::Length(3), // Input buffer - ] - .as_ref(), - ) - .split(columns[0]) -} - -fn angle_mode_widget(angle_mode: AngleMode) -> impl Widget { - Paragraph::new(format!("{}", angle_mode)).alignment(Alignment::Right) -} - -fn stack_widget(stack: &Vec) -> impl Widget { - List::new( - stack - .iter() - .map(|f| ListItem::new(format!(" {}", f))) - .collect::>(), - ) - .block(Block::default().borders(Borders::ALL)) -} - -fn input_buffer_widget(input_buffer: &str) -> impl Widget { - Paragraph::new(Spans::from(vec![ - Span::raw(">"), - Span::styled( - format!(" {}", input_buffer), - input_buffer_style(input_buffer), - ), - ])) - .block(Block::default().borders(Borders::ALL)) -} - -fn version_number_widget() -> impl Widget { - Paragraph::new(format!("pfc-{}", option_env!("CARGO_PKG_VERSION").unwrap())) - .alignment(Alignment::Center) -} - -fn input_buffer_style(input_buffer: &str) -> Style { - if let Ok(_) = Function::parse(&input_buffer) { - Style::default().add_modifier(Modifier::BOLD) - } else if let Ok(_) = Constant::parse(&input_buffer) { - Style::default().add_modifier(Modifier::BOLD) - } else { - Style::default() - } -} -- cgit v1.2.3