Start work on formatting
This commit is contained in:
parent
06c4ab6b55
commit
3b81fc7d1b
99
src/calc.rs
99
src/calc.rs
@ -3,9 +3,9 @@ pub mod errors;
|
|||||||
pub mod operations;
|
pub mod operations;
|
||||||
|
|
||||||
use constants::{
|
use constants::{
|
||||||
CalculatorConstant, CalculatorConstants, CalculatorConstantsIter, CalculatorMacro,
|
CalculatorAngleMode, CalculatorConstant, CalculatorConstants, CalculatorConstantsIter,
|
||||||
CalculatorMacros, CalculatorMacrosIter, CalculatorRegisters, CalculatorRegistersIter,
|
CalculatorDisplayMode, CalculatorMacro, CalculatorMacros, CalculatorMacrosIter,
|
||||||
CalculatorState, RegisterState,
|
CalculatorRegisters, CalculatorRegistersIter, CalculatorState, RegisterState,
|
||||||
};
|
};
|
||||||
use errors::{CalculatorError, CalculatorResult};
|
use errors::{CalculatorError, CalculatorResult};
|
||||||
use operations::{CalculatorOperation, CalculatorStateChange, MacroState, OpArgs};
|
use operations::{CalculatorOperation, CalculatorStateChange, MacroState, OpArgs};
|
||||||
@ -33,13 +33,15 @@ pub struct Calculator<'a> {
|
|||||||
undo_buf: Vec<CalculatorStateChange>,
|
undo_buf: Vec<CalculatorStateChange>,
|
||||||
redo_buf: Vec<CalculatorStateChange>,
|
redo_buf: Vec<CalculatorStateChange>,
|
||||||
state: CalculatorState,
|
state: CalculatorState,
|
||||||
|
angle_mode: CalculatorAngleMode,
|
||||||
|
display_mode: CalculatorDisplayMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Default for Calculator<'a> {
|
impl<'a> Default for Calculator<'a> {
|
||||||
fn default() -> Calculator<'a> {
|
fn default() -> Calculator<'a> {
|
||||||
Calculator {
|
Calculator {
|
||||||
l: String::new(),
|
l: String::new(),
|
||||||
stack: vec![1.2, 1.3].into_iter().collect(),
|
stack: vec![1000.0, 1200.32].into_iter().collect(),
|
||||||
state: CalculatorState::Normal,
|
state: CalculatorState::Normal,
|
||||||
undo_buf: vec![],
|
undo_buf: vec![],
|
||||||
redo_buf: vec![],
|
redo_buf: vec![],
|
||||||
@ -125,6 +127,8 @@ impl<'a> Default for Calculator<'a> {
|
|||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
angle_mode: CalculatorAngleMode::Degrees,
|
||||||
|
display_mode: CalculatorDisplayMode::Default(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,6 +179,14 @@ impl<'a> Calculator<'a> {
|
|||||||
self.state = CalculatorState::WaitingForRegister(RegisterState::Save);
|
self.state = CalculatorState::WaitingForRegister(RegisterState::Save);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
'\t' => {
|
||||||
|
self.state = CalculatorState::WaitingForConstant;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
'@' => {
|
||||||
|
self.state = CalculatorState::WaitingForSetting;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
_ => Err(CalculatorError::NoSuchOperator(c)),
|
_ => Err(CalculatorError::NoSuchOperator(c)),
|
||||||
},
|
},
|
||||||
CalculatorState::WaitingForConstant => {
|
CalculatorState::WaitingForConstant => {
|
||||||
@ -184,7 +196,9 @@ impl<'a> Calculator<'a> {
|
|||||||
.ok_or(CalculatorError::NoSuchConstant(c))?
|
.ok_or(CalculatorError::NoSuchConstant(c))?
|
||||||
.value;
|
.value;
|
||||||
|
|
||||||
self.push(f)
|
self.push(f)?;
|
||||||
|
self.state = CalculatorState::Normal;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
CalculatorState::WaitingForMacro => {
|
CalculatorState::WaitingForMacro => {
|
||||||
let mac = *self.macros.get(&c).ok_or(CalculatorError::NoSuchMacro(c))?;
|
let mac = *self.macros.get(&c).ok_or(CalculatorError::NoSuchMacro(c))?;
|
||||||
@ -237,6 +251,25 @@ impl<'a> Calculator<'a> {
|
|||||||
self.state = CalculatorState::Normal;
|
self.state = CalculatorState::Normal;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
CalculatorState::WaitingForSetting => {
|
||||||
|
match c {
|
||||||
|
'd' => self.angle_mode = CalculatorAngleMode::Degrees,
|
||||||
|
'r' => self.angle_mode = CalculatorAngleMode::Radians,
|
||||||
|
'g' => self.angle_mode = CalculatorAngleMode::Grads,
|
||||||
|
'_' => self.display_mode = CalculatorDisplayMode::Default(None),
|
||||||
|
',' => self.display_mode = CalculatorDisplayMode::Default(Some(',')),
|
||||||
|
' ' => self.display_mode = CalculatorDisplayMode::Default(Some(' ')),
|
||||||
|
's' => self.display_mode = CalculatorDisplayMode::Scientific(3),
|
||||||
|
'S' => self.display_mode = CalculatorDisplayMode::Scientific(self.pop_usize()?),
|
||||||
|
'e' => self.display_mode = CalculatorDisplayMode::Engineering(3),
|
||||||
|
'E' => {
|
||||||
|
self.display_mode = CalculatorDisplayMode::Engineering(self.pop_usize()?)
|
||||||
|
}
|
||||||
|
_ => return Err(CalculatorError::NoSuchSetting(c)),
|
||||||
|
};
|
||||||
|
self.state = CalculatorState::Normal;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,6 +345,12 @@ impl<'a> Calculator<'a> {
|
|||||||
pub fn get_stack(&self) -> &VecDeque<f64> {
|
pub fn get_stack(&self) -> &VecDeque<f64> {
|
||||||
&self.stack
|
&self.stack
|
||||||
}
|
}
|
||||||
|
pub fn get_angle_mode(&self) -> &CalculatorAngleMode {
|
||||||
|
&self.angle_mode
|
||||||
|
}
|
||||||
|
pub fn get_display_mode(&self) -> &CalculatorDisplayMode {
|
||||||
|
&self.display_mode
|
||||||
|
}
|
||||||
|
|
||||||
pub fn flush_l(&mut self) -> CalculatorResult<bool> {
|
pub fn flush_l(&mut self) -> CalculatorResult<bool> {
|
||||||
if self.l.is_empty() {
|
if self.l.is_empty() {
|
||||||
@ -343,7 +382,7 @@ impl<'a> Calculator<'a> {
|
|||||||
}
|
}
|
||||||
pub fn pop_usize(&mut self) -> CalculatorResult<usize> {
|
pub fn pop_usize(&mut self) -> CalculatorResult<usize> {
|
||||||
let f = self.checked_get(0)?;
|
let f = self.checked_get(0)?;
|
||||||
let ret = usize::from(f as usize);
|
let ret = f as usize;
|
||||||
self.direct_state_change(CalculatorStateChange {
|
self.direct_state_change(CalculatorStateChange {
|
||||||
pop: OpArgs::Unary(f),
|
pop: OpArgs::Unary(f),
|
||||||
push: OpArgs::None,
|
push: OpArgs::None,
|
||||||
@ -373,12 +412,48 @@ impl<'a> Calculator<'a> {
|
|||||||
CalculatorOperation::Dup => self.unary_op(|a| OpArgs::Binary([a, a])),
|
CalculatorOperation::Dup => self.unary_op(|a| OpArgs::Binary([a, a])),
|
||||||
CalculatorOperation::Drop => self.unary_op(|_| OpArgs::None),
|
CalculatorOperation::Drop => self.unary_op(|_| OpArgs::None),
|
||||||
CalculatorOperation::Swap => self.binary_op(|[a, b]| OpArgs::Binary([b, a])),
|
CalculatorOperation::Swap => self.binary_op(|[a, b]| OpArgs::Binary([b, a])),
|
||||||
CalculatorOperation::Sin => self.unary_op(|a| OpArgs::Unary(a.sin())),
|
CalculatorOperation::Sin => self.unary_op(match self.angle_mode {
|
||||||
CalculatorOperation::Cos => self.unary_op(|a| OpArgs::Unary(a.cos())),
|
CalculatorAngleMode::Degrees => |a: f64| OpArgs::Unary(a.to_radians().sin()),
|
||||||
CalculatorOperation::Tan => self.unary_op(|a| OpArgs::Unary(a.tan())),
|
CalculatorAngleMode::Radians => |a: f64| OpArgs::Unary(a.sin()),
|
||||||
CalculatorOperation::ASin => self.unary_op(|a| OpArgs::Unary(a.asin())),
|
CalculatorAngleMode::Grads => {
|
||||||
CalculatorOperation::ACos => self.unary_op(|a| OpArgs::Unary(a.acos())),
|
|a: f64| OpArgs::Unary((a * std::f64::consts::PI / 200.0).sin())
|
||||||
CalculatorOperation::ATan => self.unary_op(|a| OpArgs::Unary(a.atan())),
|
}
|
||||||
|
}),
|
||||||
|
CalculatorOperation::Cos => self.unary_op(match self.angle_mode {
|
||||||
|
CalculatorAngleMode::Degrees => |a: f64| OpArgs::Unary(a.to_radians().cos()),
|
||||||
|
CalculatorAngleMode::Radians => |a: f64| OpArgs::Unary(a.cos()),
|
||||||
|
CalculatorAngleMode::Grads => {
|
||||||
|
|a: f64| OpArgs::Unary((a * std::f64::consts::PI / 200.0).cos())
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
CalculatorOperation::Tan => self.unary_op(match self.angle_mode {
|
||||||
|
CalculatorAngleMode::Degrees => |a: f64| OpArgs::Unary(a.to_radians().tan()),
|
||||||
|
CalculatorAngleMode::Radians => |a: f64| OpArgs::Unary(a.tan()),
|
||||||
|
CalculatorAngleMode::Grads => {
|
||||||
|
|a: f64| OpArgs::Unary((a * std::f64::consts::PI / 200.0).tan())
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
CalculatorOperation::ASin => self.unary_op(match self.angle_mode {
|
||||||
|
CalculatorAngleMode::Degrees => |a: f64| OpArgs::Unary(a.asin().to_degrees()),
|
||||||
|
CalculatorAngleMode::Radians => |a: f64| OpArgs::Unary(a.asin()),
|
||||||
|
CalculatorAngleMode::Grads => {
|
||||||
|
|a: f64| OpArgs::Unary(a.asin() * std::f64::consts::PI / 200.0)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
CalculatorOperation::ACos => self.unary_op(match self.angle_mode {
|
||||||
|
CalculatorAngleMode::Degrees => |a: f64| OpArgs::Unary(a.acos().to_degrees()),
|
||||||
|
CalculatorAngleMode::Radians => |a: f64| OpArgs::Unary(a.acos()),
|
||||||
|
CalculatorAngleMode::Grads => {
|
||||||
|
|a: f64| OpArgs::Unary(a.acos() * std::f64::consts::PI / 200.0)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
CalculatorOperation::ATan => self.unary_op(match self.angle_mode {
|
||||||
|
CalculatorAngleMode::Degrees => |a: f64| OpArgs::Unary(a.atan().to_degrees()),
|
||||||
|
CalculatorAngleMode::Radians => |a: f64| OpArgs::Unary(a.atan()),
|
||||||
|
CalculatorAngleMode::Grads => {
|
||||||
|
|a: f64| OpArgs::Unary(a.atan() * std::f64::consts::PI / 200.0)
|
||||||
|
}
|
||||||
|
}),
|
||||||
CalculatorOperation::Sqrt => self.unary_op(|a| OpArgs::Unary(a.sqrt())),
|
CalculatorOperation::Sqrt => self.unary_op(|a| OpArgs::Unary(a.sqrt())),
|
||||||
// CalculatorOperation::Factorial => self.unary_op(|a| OpArgs::Unary(a.())),
|
// CalculatorOperation::Factorial => self.unary_op(|a| OpArgs::Unary(a.())),
|
||||||
CalculatorOperation::Log => self.unary_op(|a| OpArgs::Unary(a.log10())),
|
CalculatorOperation::Log => self.unary_op(|a| OpArgs::Unary(a.log10())),
|
||||||
|
@ -11,6 +11,7 @@ pub enum CalculatorState {
|
|||||||
WaitingForConstant,
|
WaitingForConstant,
|
||||||
WaitingForMacro,
|
WaitingForMacro,
|
||||||
WaitingForRegister(RegisterState),
|
WaitingForRegister(RegisterState),
|
||||||
|
WaitingForSetting,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
@ -33,3 +34,15 @@ pub type CalculatorMacrosIter<'a> = Iter<'a, char, CalculatorMacro<'a>>;
|
|||||||
|
|
||||||
pub type CalculatorRegisters = HashMap<char, f64>;
|
pub type CalculatorRegisters = HashMap<char, f64>;
|
||||||
pub type CalculatorRegistersIter<'a> = Iter<'a, char, f64>;
|
pub type CalculatorRegistersIter<'a> = Iter<'a, char, f64>;
|
||||||
|
|
||||||
|
pub enum CalculatorAngleMode {
|
||||||
|
Degrees,
|
||||||
|
Radians,
|
||||||
|
Grads,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum CalculatorDisplayMode {
|
||||||
|
Default(Option<char>),
|
||||||
|
Scientific(usize),
|
||||||
|
Engineering(usize),
|
||||||
|
}
|
||||||
|
@ -11,6 +11,7 @@ pub enum CalculatorError {
|
|||||||
NoSuchRegister(char),
|
NoSuchRegister(char),
|
||||||
NoSuchMacro(char),
|
NoSuchMacro(char),
|
||||||
NoSuchOperator(char),
|
NoSuchOperator(char),
|
||||||
|
NoSuchSetting(char),
|
||||||
RecursiveMacro(char),
|
RecursiveMacro(char),
|
||||||
ParseError,
|
ParseError,
|
||||||
}
|
}
|
||||||
@ -28,6 +29,7 @@ impl fmt::Display for CalculatorError {
|
|||||||
CalculatorError::NoSuchConstant(c) => write!(f, "No such constant '{}'", c),
|
CalculatorError::NoSuchConstant(c) => write!(f, "No such constant '{}'", c),
|
||||||
CalculatorError::NoSuchRegister(c) => write!(f, "No such register '{}'", c),
|
CalculatorError::NoSuchRegister(c) => write!(f, "No such register '{}'", c),
|
||||||
CalculatorError::NoSuchMacro(c) => write!(f, "No such macro '{}'", c),
|
CalculatorError::NoSuchMacro(c) => write!(f, "No such macro '{}'", c),
|
||||||
|
CalculatorError::NoSuchSetting(c) => write!(f, "No such setting '{}'", c),
|
||||||
CalculatorError::RecursiveMacro(c) => write!(f, "Recursive macro '{}'", c),
|
CalculatorError::RecursiveMacro(c) => write!(f, "Recursive macro '{}'", c),
|
||||||
CalculatorError::ParseError => write!(f, "Parse error"),
|
CalculatorError::ParseError => write!(f, "Parse error"),
|
||||||
}
|
}
|
||||||
|
190
src/main.rs
190
src/main.rs
@ -4,7 +4,7 @@
|
|||||||
mod calc;
|
mod calc;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
use calc::constants::{CalculatorState, RegisterState};
|
use calc::constants::{CalculatorAngleMode, CalculatorDisplayMode, CalculatorState, RegisterState};
|
||||||
use calc::errors::CalculatorResult;
|
use calc::errors::CalculatorResult;
|
||||||
use calc::Calculator;
|
use calc::Calculator;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
@ -27,18 +27,7 @@ struct Dimensions {
|
|||||||
height: u16,
|
height: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DisplayMode {
|
|
||||||
Default(Option<char>),
|
|
||||||
Scientific(usize),
|
|
||||||
Engineering,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AppSettings {
|
|
||||||
display_mode: DisplayMode,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AppState {
|
enum AppState {
|
||||||
AppSettings,
|
|
||||||
Calculator,
|
Calculator,
|
||||||
Help,
|
Help,
|
||||||
}
|
}
|
||||||
@ -48,7 +37,6 @@ struct App<'a> {
|
|||||||
error_msg: Option<String>,
|
error_msg: Option<String>,
|
||||||
state: AppState,
|
state: AppState,
|
||||||
current_macro: Option<char>,
|
current_macro: Option<char>,
|
||||||
app_settings: AppSettings,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Default for App<'a> {
|
impl<'a> Default for App<'a> {
|
||||||
@ -58,9 +46,6 @@ impl<'a> Default for App<'a> {
|
|||||||
error_msg: None,
|
error_msg: None,
|
||||||
state: AppState::Calculator,
|
state: AppState::Calculator,
|
||||||
current_macro: None,
|
current_macro: None,
|
||||||
app_settings: AppSettings {
|
|
||||||
display_mode: DisplayMode::Default(None),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,11 +82,17 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
],
|
],
|
||||||
(None, AppState::Calculator) => {
|
(None, AppState::Calculator) => {
|
||||||
// TODO: There has to be a better way than making strings each time
|
// TODO: There has to be a better way than making strings each time
|
||||||
let display_mode_str = match &app.app_settings.display_mode {
|
let display_mode_str = match app.calculator.get_display_mode() {
|
||||||
DisplayMode::Default(None) => String::from("[d]"),
|
CalculatorDisplayMode::Default(None) => String::from("DEF"),
|
||||||
DisplayMode::Default(Some(c)) => format!("[d({})]", c),
|
CalculatorDisplayMode::Default(Some(c)) => format!("DEF({})", c),
|
||||||
DisplayMode::Scientific(p) => format!("[s({})]", p),
|
CalculatorDisplayMode::Scientific(p) => format!("SCI({})", p),
|
||||||
DisplayMode::Engineering => String::from("[e]"),
|
CalculatorDisplayMode::Engineering(p) => format!("ENG({})", p),
|
||||||
|
};
|
||||||
|
|
||||||
|
let angle_mode_str = match app.calculator.get_angle_mode() {
|
||||||
|
CalculatorAngleMode::Degrees => String::from("DEG"),
|
||||||
|
CalculatorAngleMode::Radians => String::from("RAD"),
|
||||||
|
CalculatorAngleMode::Grads => String::from("GRD"),
|
||||||
};
|
};
|
||||||
|
|
||||||
vec![
|
vec![
|
||||||
@ -109,8 +100,10 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
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(format!(
|
||||||
Span::raw(display_mode_str),
|
" for help - [{}] [{}]",
|
||||||
|
display_mode_str, angle_mode_str
|
||||||
|
)),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
(None, _) => vec![
|
(None, _) => vec![
|
||||||
@ -133,11 +126,13 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
.rev()
|
.rev()
|
||||||
.map(|(i, m)| {
|
.map(|(i, m)| {
|
||||||
let content = vec![Spans::from(Span::raw(
|
let content = vec![Spans::from(Span::raw(
|
||||||
match &app.app_settings.display_mode {
|
match app.calculator.get_display_mode() {
|
||||||
DisplayMode::Default(None) => format!("{:>2}: {}", i, *m),
|
CalculatorDisplayMode::Default(None) => format!("{:>2}: {}", i, *m),
|
||||||
DisplayMode::Default(Some(c)) => fmt_separated(i, *m, *c),
|
CalculatorDisplayMode::Default(Some(c)) => fmt_separated(i, *m, *c),
|
||||||
DisplayMode::Scientific(precision) => fmt_scientific(i, *m, *precision),
|
CalculatorDisplayMode::Scientific(precision) => {
|
||||||
DisplayMode::Engineering => {
|
fmt_scientific(i, *m, *precision)
|
||||||
|
}
|
||||||
|
CalculatorDisplayMode::Engineering(_precision) => {
|
||||||
format!("{:>2}: {}", i, m)
|
format!("{:>2}: {}", i, m)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -169,22 +164,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
match (&app.state, app.calculator.get_state()) {
|
match (&app.state, app.calculator.get_state()) {
|
||||||
(AppState::AppSettings, _) => {
|
|
||||||
draw_clippy_rect(
|
|
||||||
ClippyRectangle {
|
|
||||||
title: "App Settings",
|
|
||||||
msg: "\
|
|
||||||
d => Default\n\
|
|
||||||
, => Default (comma separated)\n\
|
|
||||||
s => Scientific\n\
|
|
||||||
S => Scientific (stack precision)\n\
|
|
||||||
e => Engineering\n\
|
|
||||||
E => Engineering (stack precision)\n\
|
|
||||||
",
|
|
||||||
},
|
|
||||||
f,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
(AppState::Help, _) => {
|
(AppState::Help, _) => {
|
||||||
draw_clippy_rect(
|
draw_clippy_rect(
|
||||||
ClippyRectangle {
|
ClippyRectangle {
|
||||||
@ -258,6 +237,24 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
f,
|
f,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
(AppState::Calculator, CalculatorState::WaitingForSetting) => {
|
||||||
|
draw_clippy_rect(
|
||||||
|
ClippyRectangle {
|
||||||
|
title: "Help",
|
||||||
|
msg: "\
|
||||||
|
d => Degrees\n\
|
||||||
|
r => Radians\n\
|
||||||
|
d => Default\n\
|
||||||
|
, => Default (comma separated)\n\
|
||||||
|
s => Scientific\n\
|
||||||
|
S => Scientific (stack precision)\n\
|
||||||
|
e => Engineering\n\
|
||||||
|
E => Engineering (stack precision)\
|
||||||
|
",
|
||||||
|
},
|
||||||
|
f,
|
||||||
|
);
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
@ -299,9 +296,6 @@ fn handle_key(app: &mut App, events: &Events, key: Key) -> CalculatorResult<bool
|
|||||||
Key::Char('h') => {
|
Key::Char('h') => {
|
||||||
app.state = AppState::Help;
|
app.state = AppState::Help;
|
||||||
}
|
}
|
||||||
Key::Ctrl('s') => {
|
|
||||||
app.state = AppState::AppSettings;
|
|
||||||
}
|
|
||||||
Key::Char('\n') | Key::Char(' ') => {
|
Key::Char('\n') | Key::Char(' ') => {
|
||||||
app.calculator.take_input(' ')?;
|
app.calculator.take_input(' ')?;
|
||||||
}
|
}
|
||||||
@ -319,20 +313,6 @@ fn handle_key(app: &mut App, events: &Events, key: Key) -> CalculatorResult<bool
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
(AppState::AppSettings, _) => match key {
|
|
||||||
Key::Esc | Key::Char('q') => {
|
|
||||||
app.state = AppState::Calculator;
|
|
||||||
app.calculator.cancel()?;
|
|
||||||
}
|
|
||||||
Key::Char('d') => app.app_settings.display_mode = DisplayMode::Default(None),
|
|
||||||
Key::Char(',') => app.app_settings.display_mode = DisplayMode::Default(Some(',')),
|
|
||||||
Key::Char('s') => app.app_settings.display_mode = DisplayMode::Scientific(3),
|
|
||||||
Key::Char('S') => {
|
|
||||||
app.app_settings.display_mode = DisplayMode::Scientific(app.calculator.pop_usize()?)
|
|
||||||
}
|
|
||||||
Key::Char('e') => app.app_settings.display_mode = DisplayMode::Engineering,
|
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
(AppState::Help, _) => match key {
|
(AppState::Help, _) => match key {
|
||||||
Key::Esc | Key::Char('q') => {
|
Key::Esc | Key::Char('q') => {
|
||||||
app.state = AppState::Calculator;
|
app.state = AppState::Calculator;
|
||||||
@ -341,6 +321,7 @@ fn handle_key(app: &mut App, events: &Events, key: Key) -> CalculatorResult<bool
|
|||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
(AppState::Calculator, CalculatorState::WaitingForConstant)
|
(AppState::Calculator, CalculatorState::WaitingForConstant)
|
||||||
|
| (AppState::Calculator, CalculatorState::WaitingForSetting)
|
||||||
| (AppState::Calculator, CalculatorState::WaitingForRegister(_))
|
| (AppState::Calculator, CalculatorState::WaitingForRegister(_))
|
||||||
| (AppState::Calculator, CalculatorState::WaitingForMacro) => match key {
|
| (AppState::Calculator, CalculatorState::WaitingForMacro) => match key {
|
||||||
Key::Esc => {
|
Key::Esc => {
|
||||||
@ -407,16 +388,16 @@ fn draw_clippy_rect<T: std::io::Write>(c: ClippyRectangle, f: &mut Frame<Termion
|
|||||||
|
|
||||||
// Based on https://stackoverflow.com/a/65266882
|
// Based on https://stackoverflow.com/a/65266882
|
||||||
fn fmt_scientific(i: usize, f: f64, precision: usize) -> String {
|
fn fmt_scientific(i: usize, f: f64, precision: usize) -> String {
|
||||||
let mut ret = format!("{:.precision$e}", f, precision = precision);
|
let mut ret = format!("{:.precision$E}", f, precision = precision);
|
||||||
let exp = ret.split_off(ret.find('e').unwrap_or(0));
|
let exp = ret.split_off(ret.find('E').unwrap_or(0));
|
||||||
let (pow_sign, exp) = if exp.starts_with("e-") {
|
let (pow_sign, exp) = if exp.starts_with("E-") {
|
||||||
('-', &exp[2..])
|
('-', &exp[2..])
|
||||||
} else {
|
} else {
|
||||||
('+', &exp[1..])
|
('+', &exp[1..])
|
||||||
};
|
};
|
||||||
let sign = if !ret.starts_with('-') { " " } else { "" };
|
let sign = if !ret.starts_with('-') { " " } else { "" };
|
||||||
format!(
|
format!(
|
||||||
"{:>2}: {}{}e{}{:0>pad$}",
|
"{:>2}: {}{}E{}{:0>pad$}",
|
||||||
i,
|
i,
|
||||||
sign,
|
sign,
|
||||||
ret,
|
ret,
|
||||||
@ -426,12 +407,87 @@ fn fmt_scientific(i: usize, f: f64, precision: usize) -> String {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // 100 E+3
|
||||||
|
// fn fmt_engineering(i: usize, f: f64, precision: usize) -> String {
|
||||||
|
// let mut ret = format!(" {:.precision$e}", f, precision = precision + 2);
|
||||||
|
// // The length of ret will always be at least 5 -- 2 leading spaces, integer portion, and precision + 2
|
||||||
|
// let exp = ret.split_off(ret.find('E').unwrap_or(0));
|
||||||
|
// let left = ret[()..()]
|
||||||
|
// let first_three = match exp {
|
||||||
|
// }
|
||||||
|
// let (pow_sign, exp) = if exp.starts_with("E-") {
|
||||||
|
// ('-', &exp[2..])
|
||||||
|
// } else {
|
||||||
|
// ('+', &exp[1..])
|
||||||
|
// };
|
||||||
|
// let sign = if !ret.starts_with('-') { " " } else { "" };
|
||||||
|
// format!(
|
||||||
|
// "{:>2}: {}{}e{}{:0>pad$}",
|
||||||
|
// i,
|
||||||
|
// sign,
|
||||||
|
// ret,
|
||||||
|
// pow_sign,
|
||||||
|
// exp,
|
||||||
|
// pad = 2
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
|
||||||
fn fmt_separated(i: usize, f: f64, sep: char) -> String {
|
fn fmt_separated(i: usize, f: f64, sep: char) -> String {
|
||||||
let mut ret = f.to_string();
|
let mut ret = f.to_string();
|
||||||
let start = if ret.starts_with('-') { 1 } else { 0 };
|
let start = if ret.starts_with('-') { 1 } else { 0 };
|
||||||
let end = ret.find('.').unwrap_or(ret.len());
|
let end = ret.find('.').unwrap_or(ret.len());
|
||||||
for i in 0..((end - start).div_euclid(3)) {
|
for i in 0..((end - start - 1).div_euclid(3)) {
|
||||||
ret.insert(end - start - (i + 1) * 3, sep);
|
ret.insert(end - (i + 1) * 3, sep);
|
||||||
}
|
}
|
||||||
format!("{:>2}: {}", i, ret)
|
format!("{:>2}: {}", i, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn test_fmt_scientific() {
|
||||||
|
for (i, f, p, s) in vec![
|
||||||
|
// Basic
|
||||||
|
(0, 1.0, 0, " 0: 1E+00"),
|
||||||
|
(0, -1.0, 0, " 0: -1E+00"),
|
||||||
|
(0, 100.0, 0, " 0: 1E+02"),
|
||||||
|
(0, 0.1, 0, " 0: 1E-01"),
|
||||||
|
(0, 0.01, 0, " 0: 1E-02"),
|
||||||
|
(0, -0.1, 0, " 0: -1E-01"),
|
||||||
|
// i
|
||||||
|
(22, 1.0, 0, "22: 1E+00"),
|
||||||
|
// Precision
|
||||||
|
(0, -0.123456789, 3, " 0: -1.235E-01"),
|
||||||
|
(0, -0.123456789, 2, " 0: -1.23E-01"),
|
||||||
|
(0, -0.123456789, 2, " 0: -1.23E-01"),
|
||||||
|
(0, -1e99, 2, " 0: -1.00E+99"),
|
||||||
|
(0, -1e100, 2, " 0: -1.00E+100"),
|
||||||
|
] {
|
||||||
|
assert_eq!(fmt_scientific(i, f, p), s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fmt_separated() {
|
||||||
|
for (i, f, c, s) in vec![
|
||||||
|
(10, 100.0, ',', "10: 100"),
|
||||||
|
(0, 100.0, ',', " 0: 100"),
|
||||||
|
(0, -100.0, ',', " 0: -100"),
|
||||||
|
(0, 1_000.0, ',', " 0: 1,000"),
|
||||||
|
(0, -1_000.0, ',', " 0: -1,000"),
|
||||||
|
(0, 10_000.0, ',', " 0: 10,000"),
|
||||||
|
(0, -10_000.0, ',', " 0: -10,000"),
|
||||||
|
(0, 100_000.0, ',', " 0: 100,000"),
|
||||||
|
(0, -100_000.0, ',', " 0: -100,000"),
|
||||||
|
(0, 1_000_000.0, ',', " 0: 1,000,000"),
|
||||||
|
(0, -1_000_000.0, ',', " 0: -1,000,000"),
|
||||||
|
(0, 1_000_000.123456789, ',', " 0: 1,000,000.123456789"),
|
||||||
|
(0, -1_000_000.123456789, ',', " 0: -1,000,000.123456789"),
|
||||||
|
(0, 1_000_000.123456789, ' ', " 0: 1 000 000.123456789"),
|
||||||
|
(0, 1_000_000.123456789, ' ', " 0: 1 000 000.123456789"),
|
||||||
|
] {
|
||||||
|
assert_eq!(fmt_separated(i, f, c), s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user