Enforce cargo clippy strict mode
This commit is contained in:
parent
9f0ca9d276
commit
17e74b0f52
62
src/calc.rs
62
src/calc.rs
@ -1,19 +1,19 @@
|
||||
pub mod constants;
|
||||
pub mod errors;
|
||||
pub mod operations;
|
||||
pub mod types;
|
||||
|
||||
use confy::{load, store};
|
||||
use constants::{
|
||||
CalculatorAlignment, CalculatorAngleMode, CalculatorConstant, CalculatorConstants,
|
||||
CalculatorDisplayMode, CalculatorMacro, CalculatorMacros, CalculatorRegisters, CalculatorState,
|
||||
RegisterState,
|
||||
};
|
||||
use errors::{CalculatorError, CalculatorResult};
|
||||
use operations::{CalculatorOperation, CalculatorStateChange, MacroState, OpArgs};
|
||||
use serde::ser::Serializer;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::{HashSet, VecDeque};
|
||||
use types::{
|
||||
CalculatorAlignment, CalculatorAngleMode, CalculatorConstant, CalculatorConstants,
|
||||
CalculatorDisplayMode, CalculatorMacro, CalculatorMacros, CalculatorRegisters, CalculatorState,
|
||||
RegisterState,
|
||||
};
|
||||
|
||||
const MAX_PRECISION: usize = 20;
|
||||
const APP_NAME: &str = "rpn_rs";
|
||||
@ -66,7 +66,7 @@ where
|
||||
|
||||
impl Default for Calculator {
|
||||
fn default() -> Self {
|
||||
Calculator {
|
||||
Self {
|
||||
l: String::new(),
|
||||
redo_buf: vec![],
|
||||
undo_buf: vec![],
|
||||
@ -136,13 +136,15 @@ impl Calculator {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_config() -> CalculatorResult<Calculator> {
|
||||
pub fn load_config() -> CalculatorResult<Self> {
|
||||
load(APP_NAME).map_err(|e| CalculatorError::LoadError(Some(e)))
|
||||
}
|
||||
pub fn save_config(&self) -> CalculatorResult<()> {
|
||||
store(APP_NAME, self).map_err(|e| CalculatorError::SaveError(Some(e)))
|
||||
}
|
||||
|
||||
// This maps chars to operations. Not sure I can make this shorter
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub fn take_input(&mut self, c: char) -> CalculatorResult<()> {
|
||||
match &self.state {
|
||||
CalculatorState::Normal => match c {
|
||||
@ -274,12 +276,8 @@ impl Calculator {
|
||||
}
|
||||
}
|
||||
'S' => {
|
||||
let precision = self.checked_get(0)? as usize;
|
||||
if precision > MAX_PRECISION {
|
||||
return Err(CalculatorError::PrecisionTooHigh);
|
||||
}
|
||||
self.display_mode = CalculatorDisplayMode::Scientific {
|
||||
precision: self.pop_usize()?,
|
||||
precision: self.pop_precision()?,
|
||||
}
|
||||
}
|
||||
'e' => {
|
||||
@ -288,12 +286,8 @@ impl Calculator {
|
||||
}
|
||||
}
|
||||
'E' => {
|
||||
let precision = self.checked_get(0)? as usize;
|
||||
if precision > MAX_PRECISION {
|
||||
return Err(CalculatorError::PrecisionTooHigh);
|
||||
}
|
||||
self.display_mode = CalculatorDisplayMode::Engineering {
|
||||
precision: self.pop_usize()?,
|
||||
precision: self.pop_precision()?,
|
||||
}
|
||||
}
|
||||
'f' => {
|
||||
@ -303,7 +297,7 @@ impl Calculator {
|
||||
}
|
||||
'F' => {
|
||||
self.display_mode = CalculatorDisplayMode::Fixed {
|
||||
precision: self.pop_usize()?,
|
||||
precision: self.pop_precision()?,
|
||||
}
|
||||
}
|
||||
'w' => self.save_on_close = false,
|
||||
@ -405,24 +399,36 @@ impl Calculator {
|
||||
push: OpArgs::Unary(f),
|
||||
})
|
||||
}
|
||||
pub fn pop(&mut self) -> CalculatorResult<f64> {
|
||||
pub fn peek(&mut self) -> CalculatorResult<f64> {
|
||||
self.flush_l()?;
|
||||
let f = self.checked_get(0)?;
|
||||
self.checked_get(0)
|
||||
}
|
||||
pub fn pop(&mut self) -> CalculatorResult<f64> {
|
||||
let f = self.peek()?;
|
||||
self.direct_state_change(CalculatorStateChange {
|
||||
pop: OpArgs::Unary(f),
|
||||
push: OpArgs::None,
|
||||
})?;
|
||||
Ok(f)
|
||||
}
|
||||
pub fn pop_usize(&mut self) -> CalculatorResult<usize> {
|
||||
self.flush_l()?;
|
||||
let f = self.checked_get(0)?;
|
||||
let ret = f as usize;
|
||||
pub fn pop_precision(&mut self) -> CalculatorResult<usize> {
|
||||
let f = self.peek()?;
|
||||
// Ensure this can be cast to a usize
|
||||
if !f.is_finite() || f.is_sign_negative() {
|
||||
return Err(CalculatorError::ArithmeticError);
|
||||
}
|
||||
#[allow(clippy::cast_sign_loss)]
|
||||
let u = f as usize;
|
||||
|
||||
if u > MAX_PRECISION {
|
||||
return Err(CalculatorError::PrecisionTooHigh);
|
||||
}
|
||||
|
||||
self.direct_state_change(CalculatorStateChange {
|
||||
pop: OpArgs::Unary(f),
|
||||
push: OpArgs::None,
|
||||
})?;
|
||||
Ok(ret)
|
||||
Ok(u)
|
||||
}
|
||||
pub fn op(&mut self, op: CalculatorOperation) -> CalculatorResult<()> {
|
||||
// Dup is special -- don't actually run it if l needs to be flushed
|
||||
@ -441,7 +447,7 @@ impl Calculator {
|
||||
}
|
||||
CalculatorOperation::Negate => self.unary_op(|a| OpArgs::Unary(-a)),
|
||||
CalculatorOperation::AbsoluteValue => self.unary_op(|a| OpArgs::Unary(a.abs())),
|
||||
CalculatorOperation::Inverse => self.unary_op(|a| OpArgs::Unary(1.0 / a)),
|
||||
CalculatorOperation::Inverse => self.unary_op(|a| OpArgs::Unary(a.recip())),
|
||||
CalculatorOperation::Modulo => self.binary_op(|[a, b]| OpArgs::Unary(b % a)),
|
||||
//CalculatorOperation::Remainder => self.binary_op(|[a, b]| OpArgs::Unary(b.rem_euclid(a))),
|
||||
CalculatorOperation::Dup => self.unary_op(|a| OpArgs::Binary([a, a])),
|
||||
@ -493,7 +499,7 @@ impl Calculator {
|
||||
CalculatorOperation::Log => self.unary_op(|a| OpArgs::Unary(a.log10())),
|
||||
CalculatorOperation::Ln => self.unary_op(|a| OpArgs::Unary(a.ln())),
|
||||
CalculatorOperation::Pow => self.binary_op(|[a, b]| OpArgs::Unary(b.powf(a))),
|
||||
CalculatorOperation::E => self.binary_op(|[a, b]| OpArgs::Unary(b * 10.0f64.powf(a))),
|
||||
CalculatorOperation::E => self.binary_op(|[a, b]| OpArgs::Unary(b * 10.0_f64.powf(a))),
|
||||
CalculatorOperation::Undo => return self.history_op(false),
|
||||
CalculatorOperation::Redo => return self.history_op(true),
|
||||
// Macros are a no-op operator; need to insert for undo/redo
|
||||
|
@ -27,30 +27,30 @@ impl error::Error for CalculatorError {}
|
||||
impl fmt::Display for CalculatorError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
CalculatorError::ArithmeticError => write!(f, "Arithmetic Error"),
|
||||
CalculatorError::NotEnoughStackEntries => write!(f, "Not enough items in the stack"),
|
||||
CalculatorError::CorruptStateChange(msg) => {
|
||||
Self::ArithmeticError => write!(f, "Arithmetic Error"),
|
||||
Self::NotEnoughStackEntries => write!(f, "Not enough items in the stack"),
|
||||
Self::CorruptStateChange(msg) => {
|
||||
write!(f, "Corrupt state change: {}", msg)
|
||||
}
|
||||
CalculatorError::EmptyHistory(msg) => write!(f, "No history to {}", msg),
|
||||
CalculatorError::NoSuchOperator(c) => write!(f, "No such operator '{}'", c),
|
||||
CalculatorError::NoSuchConstant(c) => write!(f, "No such constant '{}'", c),
|
||||
CalculatorError::NoSuchRegister(c) => write!(f, "No such register '{}'", 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::ParseError => write!(f, "Parse error"),
|
||||
CalculatorError::PrecisionTooHigh => write!(f, "Precision too high"),
|
||||
CalculatorError::SaveError(None) => write!(f, "Could not save"),
|
||||
CalculatorError::SaveError(Some(ConfyError::SerializeTomlError(e))) => {
|
||||
Self::EmptyHistory(msg) => write!(f, "No history to {}", msg),
|
||||
Self::NoSuchOperator(c) => write!(f, "No such operator '{}'", c),
|
||||
Self::NoSuchConstant(c) => write!(f, "No such constant '{}'", c),
|
||||
Self::NoSuchRegister(c) => write!(f, "No such register '{}'", c),
|
||||
Self::NoSuchMacro(c) => write!(f, "No such macro '{}'", c),
|
||||
Self::NoSuchSetting(c) => write!(f, "No such setting '{}'", c),
|
||||
Self::RecursiveMacro(c) => write!(f, "Recursive macro '{}'", c),
|
||||
Self::ParseError => write!(f, "Parse error"),
|
||||
Self::PrecisionTooHigh => write!(f, "Precision too high"),
|
||||
Self::SaveError(None) => write!(f, "Could not save"),
|
||||
Self::SaveError(Some(ConfyError::SerializeTomlError(e))) => {
|
||||
write!(f, "Save serialization error: {}", e)
|
||||
}
|
||||
CalculatorError::SaveError(Some(e)) => write!(f, "Could not save: {}", e),
|
||||
CalculatorError::LoadError(None) => write!(f, "Could not load"),
|
||||
CalculatorError::LoadError(Some(ConfyError::SerializeTomlError(e))) => {
|
||||
Self::SaveError(Some(e)) => write!(f, "Could not save: {}", e),
|
||||
Self::LoadError(None) => write!(f, "Could not load"),
|
||||
Self::LoadError(Some(ConfyError::SerializeTomlError(e))) => {
|
||||
write!(f, "Load serialization error: {}", e)
|
||||
}
|
||||
CalculatorError::LoadError(Some(e)) => write!(f, "Could not load: {}", e),
|
||||
Self::LoadError(Some(e)) => write!(f, "Could not load: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ pub enum CalculatorState {
|
||||
|
||||
impl Default for CalculatorState {
|
||||
fn default() -> Self {
|
||||
CalculatorState::Normal
|
||||
Self::Normal
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,16 +53,16 @@ pub enum CalculatorAngleMode {
|
||||
|
||||
impl Default for CalculatorAngleMode {
|
||||
fn default() -> Self {
|
||||
CalculatorAngleMode::Degrees
|
||||
Self::Degrees
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CalculatorAngleMode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
CalculatorAngleMode::Degrees => write!(f, "DEG"),
|
||||
CalculatorAngleMode::Radians => write!(f, "RAD"),
|
||||
CalculatorAngleMode::Grads => write!(f, "GRD"),
|
||||
Self::Degrees => write!(f, "DEG"),
|
||||
Self::Radians => write!(f, "RAD"),
|
||||
Self::Grads => write!(f, "GRD"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -81,18 +81,18 @@ pub enum CalculatorDisplayMode {
|
||||
impl fmt::Display for CalculatorDisplayMode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
CalculatorDisplayMode::Default => write!(f, "DEF"),
|
||||
CalculatorDisplayMode::Separated { separator } => write!(f, "SEP({})", separator),
|
||||
CalculatorDisplayMode::Scientific { precision } => write!(f, "SCI({})", precision),
|
||||
CalculatorDisplayMode::Engineering { precision } => write!(f, "ENG({})", precision),
|
||||
CalculatorDisplayMode::Fixed { precision } => write!(f, "FIX({})", precision),
|
||||
Self::Default => write!(f, "DEF"),
|
||||
Self::Separated { separator } => write!(f, "SEP({})", separator),
|
||||
Self::Scientific { precision } => write!(f, "SCI({})", precision),
|
||||
Self::Engineering { precision } => write!(f, "ENG({})", precision),
|
||||
Self::Fixed { precision } => write!(f, "FIX({})", precision),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CalculatorDisplayMode {
|
||||
fn default() -> Self {
|
||||
CalculatorDisplayMode::Default
|
||||
Self::Default
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,15 +104,15 @@ pub enum CalculatorAlignment {
|
||||
|
||||
impl Default for CalculatorAlignment {
|
||||
fn default() -> Self {
|
||||
CalculatorAlignment::Left
|
||||
Self::Left
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CalculatorAlignment {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
CalculatorAlignment::Left => write!(f, "L"),
|
||||
CalculatorAlignment::Right => write!(f, "R"),
|
||||
Self::Left => write!(f, "L"),
|
||||
Self::Right => write!(f, "R"),
|
||||
}
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ pub struct Events {
|
||||
}
|
||||
|
||||
impl Events {
|
||||
pub fn new(tick_rate: u64) -> Events {
|
||||
pub fn new(tick_rate: u64) -> Self {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let tick_handle = {
|
||||
let tx = tx.clone();
|
||||
@ -44,14 +44,14 @@ impl Events {
|
||||
}
|
||||
})
|
||||
};
|
||||
Events {
|
||||
Self {
|
||||
tx,
|
||||
rx,
|
||||
tick_handle,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a chain of the next element (blocking) and a TryIter of everything after it.
|
||||
/// Returns a chain of the next element (blocking) and a `TryIter` of everything after it.
|
||||
/// Useful for reading a single Iterator of all elements once after blocking, so there are not too many UI redraws.
|
||||
pub fn blocking_iter(
|
||||
&self,
|
||||
|
@ -2,13 +2,11 @@
|
||||
pub fn scientific(f: f64, precision: usize) -> String {
|
||||
let mut ret = format!("{:.precision$E}", f, precision = precision);
|
||||
let exp = ret.split_off(ret.find('E').unwrap_or(0));
|
||||
let (exp_sign, exp) = if let Some(stripped) = exp.strip_prefix("E-") {
|
||||
('-', stripped)
|
||||
} else {
|
||||
('+', &exp[1..])
|
||||
};
|
||||
let (exp_sign, exp) = exp
|
||||
.strip_prefix("E-")
|
||||
.map_or_else(|| ('+', &exp[1..]), |stripped| ('-', stripped));
|
||||
|
||||
let sign = if !ret.starts_with('-') { " " } else { "" };
|
||||
let sign = if ret.starts_with('-') { "" } else { " " };
|
||||
format!("{}{} E{}{:0>pad$}", sign, ret, exp_sign, exp, pad = 2)
|
||||
}
|
||||
|
||||
@ -48,9 +46,9 @@ pub fn engineering(f: f64, precision: usize) -> String {
|
||||
|
||||
// Whole portion of number. Slice is safe because the num_whole_digits is always 3 and the num_str will always have length >= 3 since precision in all=2 (+original whole digit)
|
||||
// Original number is 1,000 => whole will be 1, if original is 0.01, whole will be 10
|
||||
let whole = &num_str[0..(num_whole_digits + 1)];
|
||||
let whole = &num_str[0..=num_whole_digits];
|
||||
// Decimal portion of the number. Sliced from the number of whole digits to the *requested* precision. Precision generated in all will be requested precision + 2
|
||||
let decimal = &num_str[(num_whole_digits + 1)..(precision + num_whole_digits + 1)];
|
||||
let decimal = &num_str[(num_whole_digits + 1)..=(precision + num_whole_digits)];
|
||||
// Right align whole portion, always have decimal point
|
||||
format!(
|
||||
"{: >4}.{} E{}{:0>pad$}",
|
||||
|
32
src/main.rs
32
src/main.rs
@ -1,10 +1,16 @@
|
||||
#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]
|
||||
// This is intended behavior
|
||||
#![allow(clippy::cast_possible_truncation)]
|
||||
// Cannot fix this, so don't warn me about it
|
||||
#![allow(clippy::multiple_crate_versions)]
|
||||
|
||||
mod calc;
|
||||
mod event;
|
||||
mod format;
|
||||
|
||||
use calc::{
|
||||
constants::{CalculatorAlignment, CalculatorDisplayMode, CalculatorState, RegisterState},
|
||||
errors::CalculatorResult,
|
||||
types::{CalculatorAlignment, CalculatorDisplayMode, CalculatorState, RegisterState},
|
||||
Calculator,
|
||||
};
|
||||
use crossterm::{
|
||||
@ -53,7 +59,7 @@ impl Default for App {
|
||||
Ok(c) => (c, None),
|
||||
Err(e) => (Calculator::default(), Some(format!("{}", e))),
|
||||
};
|
||||
App {
|
||||
Self {
|
||||
calculator,
|
||||
error_msg,
|
||||
state: AppState::Calculator,
|
||||
@ -61,11 +67,13 @@ impl Default for App {
|
||||
}
|
||||
}
|
||||
impl App {
|
||||
fn draw_clippy_dialogs<T: std::io::Write>(&mut self, f: &mut Frame<CrosstermBackend<T>>) {
|
||||
// This function is long because it contains help text
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn draw_clippy_dialogs<T: Write>(&mut self, f: &mut Frame<CrosstermBackend<T>>) {
|
||||
match (&self.state, &self.calculator.state) {
|
||||
(AppState::Help, _) => {
|
||||
draw_clippy_rect(
|
||||
ClippyRectangle {
|
||||
&ClippyRectangle {
|
||||
title: "Help",
|
||||
msg: "\
|
||||
+ => Add s => Sin\n\
|
||||
@ -92,7 +100,7 @@ impl App {
|
||||
}
|
||||
(AppState::Calculator, CalculatorState::WaitingForConstant) => {
|
||||
draw_clippy_rect(
|
||||
ClippyRectangle {
|
||||
&ClippyRectangle {
|
||||
title: "Constants",
|
||||
msg: self
|
||||
.calculator
|
||||
@ -113,7 +121,7 @@ impl App {
|
||||
RegisterState::Load => "Registers",
|
||||
};
|
||||
draw_clippy_rect(
|
||||
ClippyRectangle {
|
||||
&ClippyRectangle {
|
||||
title,
|
||||
msg: self
|
||||
.calculator
|
||||
@ -128,7 +136,7 @@ impl App {
|
||||
}
|
||||
(AppState::Calculator, CalculatorState::WaitingForMacro) => {
|
||||
draw_clippy_rect(
|
||||
ClippyRectangle {
|
||||
&ClippyRectangle {
|
||||
title: "Macros",
|
||||
msg: self
|
||||
.calculator
|
||||
@ -143,7 +151,7 @@ impl App {
|
||||
}
|
||||
(AppState::Calculator, CalculatorState::WaitingForSetting) => {
|
||||
draw_clippy_rect(
|
||||
ClippyRectangle {
|
||||
&ClippyRectangle {
|
||||
title: "Settings",
|
||||
msg: "\
|
||||
d => Degrees\n\
|
||||
@ -170,7 +178,7 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn terminal_draw_func<T: std::io::Write>(&mut self, f: &mut Frame<CrosstermBackend<T>>) {
|
||||
pub fn terminal_draw_func<T: Write>(&mut self, f: &mut Frame<CrosstermBackend<T>>) {
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.margin(2)
|
||||
@ -304,7 +312,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
Err(e) => Some(format!("{}", e)),
|
||||
};
|
||||
}
|
||||
_ => continue,
|
||||
Event::Tick => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -318,6 +326,8 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
app.calculator.close().map_err(|e| e.into())
|
||||
}
|
||||
|
||||
// This function is long since it maps keys to their proper value
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn handle_key(app: &mut App, key: KeyEvent) -> CalculatorResult<CalculatorResponse> {
|
||||
match (&app.state, &app.calculator.state) {
|
||||
(AppState::Calculator, CalculatorState::Normal) => match key {
|
||||
@ -452,7 +462,7 @@ impl ClippyRectangle<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_clippy_rect<T: std::io::Write>(c: ClippyRectangle, f: &mut Frame<CrosstermBackend<T>>) {
|
||||
fn draw_clippy_rect<T: Write>(c: &ClippyRectangle, f: &mut Frame<CrosstermBackend<T>>) {
|
||||
// let block = Block::default().title(c.title).borders(Borders::ALL);
|
||||
let dimensions = c.size();
|
||||
let popup_layout = Layout::default()
|
||||
|
Loading…
Reference in New Issue
Block a user