Compare commits

..

No commits in common. "09996801d818eed2b81565d1861e31529058bcd7" and "36540f37b89c79fa691b4837cb75a50a26f77ef8" have entirely different histories.

15 changed files with 112 additions and 287 deletions

2
Cargo.lock generated
View File

@ -28,7 +28,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "daisycalc" name = "daisycalc"
version = "1.0.1" version = "1.0.0"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"rug", "rug",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "daisycalc" name = "daisycalc"
version = "1.0.1" version = "1.0.0"
edition = "2021" edition = "2021"
build = "buildscript/main.rs" build = "buildscript/main.rs"
license = "GPL-3.0-only" license = "GPL-3.0-only"

View File

@ -5,7 +5,6 @@ A high-precision scientific calculator with support for units, derivatives, and
Many features are missing, this is still under development. Many features are missing, this is still under development.
# 📦 Installation # 📦 Installation
- **Cargo:** `cargo install daisycalc`
- **Arch:** `yay -S daisy` - **Arch:** `yay -S daisy`
- **Debian:** coming soon - **Debian:** coming soon

11
TODO.md
View File

@ -2,9 +2,9 @@
- update Cargo.toml - update Cargo.toml
- run cargo test - run cargo test
- commit - commit
- push - git tag -a v1.0.0 -m "Version 1.0.0"
- merge - git push
- git tag -a v1.0.0 -m "Version 1.0.0" on merge commit - git push origin v1.0.0
- cargo publish - cargo publish
- Update packages - Update packages
@ -27,6 +27,11 @@
- Optional history file - Optional history file
- daisyrc file - daisyrc file
- Compile to WASM, publish a webapp - Compile to WASM, publish a webapp
- Options:
- disable replacement
- disable special characters
- 1/ as -1 power toggle
- powers as superscripts toggle
- evaluate straight from command line - evaluate straight from command line
- Auto-push to crates.io - Auto-push to crates.io
- Package for debian - Package for debian

View File

@ -170,7 +170,7 @@ pub fn do_command(
t.push(&format!( t.push(&format!(
" {key}{padding} = [c]{v}[n]\n", " {key}{padding} = [c]{v}[n]\n",
v = value.display(context), v = value.to_string(),
)); ));
} }
} }
@ -184,7 +184,7 @@ pub fn do_command(
t.push(&format!( t.push(&format!(
" {s}{padding} = [c]{v}[n]\n", " {s}{padding} = [c]{v}[n]\n",
v = exp.display(context), v = exp.to_string(),
)); ));
} }
} }

View File

@ -3,68 +3,7 @@ use crate::quantity::freeunit_from_string;
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug)] #[derive(Debug)]
#[derive(Clone)]
pub struct Config {
// How to color terminal text.
// 0: No colors
// 1: ANSI-compatible, 8 colors
// 2: Full 256 color and special styles
pub term_color_type: u8,
// Should we accept input and print in unicode?
//pub enable_unicode: bool,
// Should we replace certain strings (like "pi")
// with prettier unicode alternatives?
//
// Automatically disabled if enable_unicode is off.
//pub enable_substituion: bool,
// Should we print simple powers
// as unicode superscript chars?
//
// Automatically disables if enable_unicode is off.
pub enable_super_powers: bool,
// Should we write "one-over" fractions
// as -1 powers?
//
// Automatically disabled if enable_super_powers is off.
pub enable_one_over_power: bool,
}
impl Config {
pub fn new() -> Config {
Config{
term_color_type: 2,
//enable_substituion: true,
//enable_unicode: true,
enable_super_powers: true,
enable_one_over_power: true
}
}
pub fn check(&mut self) {
//if !self.enable_unicode {
// self.enable_substituion = false;
// self.enable_super_powers = false;
//}
if !self.enable_super_powers {
self.enable_one_over_power = false
}
}
}
#[derive(Debug)]
#[derive(Clone)]
pub struct Context { pub struct Context {
pub config: Config,
history: Vec<Expression>, history: Vec<Expression>,
variables: HashMap<String, Expression>, variables: HashMap<String, Expression>,
functions: HashMap<String, (Vec<String>, Expression)>, functions: HashMap<String, (Vec<String>, Expression)>,
@ -77,7 +16,6 @@ pub struct Context {
impl Context { impl Context {
pub fn new() -> Context { pub fn new() -> Context {
Context{ Context{
config: Config::new(),
history: Vec::new(), history: Vec::new(),
variables: HashMap::new(), variables: HashMap::new(),
functions: HashMap::new(), functions: HashMap::new(),

View File

@ -1,3 +1,4 @@
use std::io::Write;
use std::io::stdout; use std::io::stdout;
use std::io::stdin; use std::io::stdin;
use std::env; use std::env;
@ -5,33 +6,19 @@ use std::env;
use termion::{ use termion::{
event::Key, event::Key,
input::TermRead, input::TermRead,
raw::IntoRawMode, raw::IntoRawMode
color::DetectColors
}; };
use super::promptbuffer::PromptBuffer; use super::promptbuffer::PromptBuffer;
use crate::command; use crate::command;
use crate::context::Context; use crate::context::Context;
use crate::FormattedText;
#[inline(always)] #[inline(always)]
pub fn main() -> Result<(), std::io::Error> { pub fn main() -> Result<(), std::io::Error> {
let mut stdout = stdout().into_raw_mode().unwrap(); let mut stdout = stdout().into_raw_mode().unwrap();
let mut pb: PromptBuffer = PromptBuffer::new(64); let mut pb: PromptBuffer = PromptBuffer::new(64);
let mut context = Context::new(); let mut context: Context = Context::new();
// Set color compatibilty
let term_colors = stdout.available_colors().unwrap_or(0);
if term_colors >= 256 {
context.config.term_color_type = 2
} else if term_colors >= 8 {
context.config.term_color_type = 1
} else {
context.config.term_color_type = 0
}
context.config.check();
// Handle command-line arguments // Handle command-line arguments
@ -41,21 +28,7 @@ pub fn main() -> Result<(), std::io::Error> {
t.write(&context, &mut stdout)?; t.write(&context, &mut stdout)?;
return Ok(()); return Ok(());
} else if args.iter().any(|s| s == "--version") { } else if args.iter().any(|s| s == "--version") {
let t = FormattedText::new(format!( write!(stdout, "Daisy v{}\r\n", env!("CARGO_PKG_VERSION"))?;
"Daisy v{}\n", env!("CARGO_PKG_VERSION")
));
t.write(&context, &mut stdout)?;
return Ok(());
} else if args.iter().any(|s| s == "--debug") {
let t = FormattedText::new(format!(
concat!(
"Daisy v{}\n",
"Your terminal supports {} colors.\n"
),
env!("CARGO_PKG_VERSION"),
term_colors
));
t.write(&context, &mut stdout)?;
return Ok(()); return Ok(());
} }
@ -72,7 +45,7 @@ pub fn main() -> Result<(), std::io::Error> {
// while inside a substitution // while inside a substitution
pb.write_prompt_nocursor(&mut context, &mut stdout)?; pb.write_prompt_nocursor(&mut context, &mut stdout)?;
let in_str = pb.enter(); let in_str = pb.enter();
FormattedText::newline(&mut stdout)?; write!(stdout, "\r\n")?;
if in_str == "" { break; } if in_str == "" { break; }
if in_str.trim() == "quit" { if in_str.trim() == "quit" {
@ -110,6 +83,6 @@ pub fn main() -> Result<(), std::io::Error> {
} }
} }
FormattedText::newline(&mut stdout)?; write!(stdout, "\r\n")?;
return Ok(()); return Ok(());
} }

View File

@ -78,8 +78,8 @@ pub fn eval_operator(context: &mut Context, g: &Expression) -> Result<Option<Exp
return Err(( return Err((
*la + *lb + *op_loc, *la + *lb + *op_loc,
DaisyError::IncompatibleUnits( DaisyError::IncompatibleUnits(
a.convert_to_base().unit.display(context), a.convert_to_base().unit.to_string(),
b.convert_to_base().unit.display(context) b.convert_to_base().unit.to_string()
) )
)); ));
} }
@ -101,8 +101,8 @@ pub fn eval_operator(context: &mut Context, g: &Expression) -> Result<Option<Exp
return Err(( return Err((
*la + *lb + *op_loc, *la + *lb + *op_loc,
DaisyError::IncompatibleUnits( DaisyError::IncompatibleUnits(
a.convert_to_base().unit.display(context), a.convert_to_base().unit.to_string(),
b.convert_to_base().unit.display(context) b.convert_to_base().unit.to_string()
) )
)); ));
} }
@ -179,8 +179,8 @@ pub fn eval_operator(context: &mut Context, g: &Expression) -> Result<Option<Exp
return Err(( return Err((
*la + *lb + *op_loc, *la + *lb + *op_loc,
DaisyError::IncompatibleUnits( DaisyError::IncompatibleUnits(
va.convert_to_base().unit.display(context), va.convert_to_base().unit.to_string(),
vb.convert_to_base().unit.display(context) vb.convert_to_base().unit.to_string()
) )
)); ));
} }

View File

@ -5,7 +5,6 @@ use termion::style;
use termion::clear; use termion::clear;
use termion::cursor; use termion::cursor;
use std::ops::Add; use std::ops::Add;
use crate::context::Context;
#[derive(Debug)] #[derive(Debug)]
@ -19,92 +18,8 @@ impl ToString for FormattedText {
} }
fn format_map_none(c: char) -> Option<String> {
Some(match c {
'n'|'i'|'t'|'a'|
'e'|'c'|'s'|'r'
=> { "".to_string() },
_ => { return None }
})
}
fn format_map_ansi(c: char) -> Option<String> {
Some(match c {
'n' => { // Normal text
format!("{}{}", color::Fg(color::Reset), color::Bg(color::Reset))
},
'i' => { // Normal italic text
format!("{}{}", color::Fg(color::Reset), color::Bg(color::Reset))
},
't' => { // Title text
format!("{}{}", color::Fg(color::AnsiValue(6)), color::Bg(color::Reset))
},
'a' => { // Colored text
format!("{}{}", color::Fg(color::AnsiValue(5)), color::Bg(color::Reset))
},
'e' => { // Error titles
format!("{}{}", color::Fg(color::AnsiValue(1)), color::Bg(color::Reset))
},
'c' => { // Console text
format!("{}{}", color::Fg(color::AnsiValue(0)), color::Bg(color::AnsiValue(7)))
},
's' => { // Repeat prompt (how => is styled)
format!("{}{}", color::Fg(color::AnsiValue(2)), color::Bg(color::Reset))
},
'r' => { // Result prompt (how = is styled)
format!("{}{}", color::Fg(color::AnsiValue(4)), color::Bg(color::Reset))
},
_ => { return None }
})
}
fn format_map_full(c: char) -> Option<String> {
Some(match c {
'n' => { // Normal text
format!("{}{}", color::Fg(color::Reset), style::Reset)
},
'i' => { // Normal italic text
format!("{}{}", color::Fg(color::Reset), style::Italic)
},
't' => { // Title text
format!("{}{}", color::Fg(color::Magenta), style::Bold)
},
'a' => { // Colored text
format!("{}{}", color::Fg(color::Magenta), style::Reset)
},
'e' => { // Error titles
format!("{}{}", color::Fg(color::Red), style::Bold)
},
'c' => { // Console text
format!("{}{}", color::Fg(color::LightBlack), style::Italic)
},
's' => { // Repeat prompt (how => is styled)
format!("{}{}", color::Fg(color::Magenta), style::Bold)
},
'r' => { // Result prompt (how = is styled)
format!("{}{}", color::Fg(color::Green), style::Bold)
},
_ => { return None }
})
}
impl FormattedText { impl FormattedText {
pub fn newline(stdout: &mut RawTerminal<std::io::Stdout>) -> Result<(), std::io::Error> {
write!(
stdout,
"\r\n",
)?;
return Ok(());
}
}
impl FormattedText {
pub fn new(s: String) -> FormattedText { pub fn new(s: String) -> FormattedText {
return FormattedText { return FormattedText {
text: s text: s
@ -143,22 +58,30 @@ impl FormattedText {
let b = chars.next().unwrap(); let b = chars.next().unwrap();
match (a, b) { match (a, b) {
(c, ']') => { // Normal text ('n', ']') => { // Normal text
s.push_str(&format!("{}{}", color::Fg(color::Reset), style::Reset));
},
('i', ']') => { // Normal italic text
s.push_str(&format!("{}{}", color::Fg(color::Reset), style::Italic));
},
('t', ']') => { // Title text
s.push_str(&format!("{}{}", color::Fg(color::Magenta), style::Bold));
},
('a', ']') => { // Colored text
s.push_str(&format!("{}{}", color::Fg(color::Magenta), style::Reset));
},
('e', ']') => { // Error titles
s.push_str(&format!("{}{}", color::Fg(color::Red), style::Bold));
},
('c', ']') => { // Console text
s.push_str(&format!("{}{}", color::Fg(color::LightBlack), style::Italic));
},
let q = match context.config.term_color_type { ('s', ']') => { // Repeat prompt (how => is styled)
0 => format_map_none(c), s.push_str(&format!("{}{}", color::Fg(color::Magenta), style::Bold));
1 => format_map_ansi(c), },
2 => format_map_full(c), ('r', ']') => { // Result prompt (how = is styled)
_ => unreachable!("Invalid term_color_type") s.push_str(&format!("{}{}", color::Fg(color::Green), style::Bold));
};
if q.is_some() {
s.push_str(&q.unwrap());
} else {
s.push('[');
s.push(a);
s.push(b);
}
}, },
_ => { _ => {

View File

@ -85,13 +85,13 @@ fn do_expression(
// Display parsed string // Display parsed string
output.push(&format!( output.push(&format!(
" [s]=>[n] {}\n\n", " [s]=>[n] {}\n\n",
g.display(context) g.to_string()
)); ));
// Display result // Display result
output.push(&format!( output.push(&format!(
" [r]=[n] {}\n\n", " [r]=[n] {}\n\n",
g_evaluated.display_outer(context), g_evaluated.to_string_outer(),
)); ));
return Ok((output, g_evaluated)); return Ok((output, g_evaluated));
@ -224,7 +224,7 @@ fn do_assignment(
// Display parsed string // Display parsed string
output.push(&format!( output.push(&format!(
" [s]=>[n] {left} = {}\n\n", " [s]=>[n] {left} = {}\n\n",
g.display(context) g.to_string()
)); ));
// Evaluate expression with shadow variables // Evaluate expression with shadow variables
@ -266,7 +266,7 @@ fn do_assignment(
// Display parsed string // Display parsed string
output.push(&format!( output.push(&format!(
" [t]=>[n] {left} = {}\n\n", " [t]=>[n] {left} = {}\n\n",
g.display(context) g.to_string()
)); ));
// Evaluate expression // Evaluate expression

View File

@ -1,6 +1,5 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::quantity::Quantity; use crate::quantity::Quantity;
use crate::context::Context;
use super::Operator; use super::Operator;
use super::Constant; use super::Constant;
@ -18,17 +17,17 @@ pub enum Expression {
Tuple(LineLocation, VecDeque<Expression>), Tuple(LineLocation, VecDeque<Expression>),
} }
impl Expression { impl ToString for Expression {
pub fn display(&self, context: &Context) -> String { fn to_string(&self) -> String {
match self { match self {
Expression::Quantity(_, v) => v.display(context), Expression::Quantity(_, v) => v.to_string(),
Expression::Constant(_, c) => c.to_string(), Expression::Constant(_, c) => c.to_string(),
Expression::Variable(_, s) => s.clone(), Expression::Variable(_, s) => s.clone(),
Expression::Operator(_, o,a) => o.display(context, a), Expression::Operator(_, o,a) => o.print(a),
Expression::Tuple(_, v) => { Expression::Tuple(_, v) => {
format!("({})", format!("({})",
v.iter() v.iter()
.map(|x| x.display(context)) .map(|x| x.to_string())
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(", ") .join(", ")
) )
@ -40,16 +39,16 @@ impl Expression {
impl Expression { impl Expression {
// This is called only when this is the outermost Expression. // This is called only when this is the outermost Expression.
// This sometimes leads to different--usually more verbose--behavior. // This sometimes leads to different--usually more verbose--behavior.
pub fn display_outer(&self, context: &Context) -> String { pub fn to_string_outer(&self) -> String {
match self { match self {
Expression::Quantity(_, v) => v.display_outer(context), Expression::Quantity(_, v) => v.to_string_outer(),
Expression::Constant(_, c) => c.to_string(), Expression::Constant(_, c) => c.to_string(),
Expression::Variable(_, s) => s.clone(), Expression::Variable(_, s) => s.clone(),
Expression::Operator(_, o,a) => o.display(context, a), Expression::Operator(_, o,a) => o.print(a),
Expression::Tuple(_, v) => { Expression::Tuple(_, v) => {
format!("({})", format!("({})",
v.iter() v.iter()
.map(|x| x.display(context)) .map(|x| x.to_string())
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(", ") .join(", ")
) )

View File

@ -128,8 +128,8 @@ impl Operator {
} }
#[inline(always)] #[inline(always)]
fn add_parens_to_arg(&self, context: &Context, arg: &Expression) -> String { fn add_parens_to_arg(&self, arg: &Expression) -> String {
let mut astr: String = arg.display(context); let mut astr: String = arg.to_string();
if let Expression::Operator(_, o,_) = arg { if let Expression::Operator(_, o,_) = arg {
if o.print_map() < self.print_map() { if o.print_map() < self.print_map() {
astr = format!("({})", astr); astr = format!("({})", astr);
@ -139,8 +139,8 @@ impl Operator {
} }
#[inline(always)] #[inline(always)]
fn add_parens_to_arg_strict(&self, context: &Context, arg: &Expression) -> String { fn add_parens_to_arg_strict(&self, arg: &Expression) -> String {
let mut astr: String = arg.display(context); let mut astr: String = arg.to_string();
if let Expression::Operator(_, o,_) = arg { if let Expression::Operator(_, o,_) = arg {
if o.print_map() <= self.print_map() { if o.print_map() <= self.print_map() {
astr = format!("({})", astr); astr = format!("({})", astr);
@ -150,56 +150,56 @@ impl Operator {
} }
pub fn display(&self, context: &Context, args: &VecDeque<Expression>) -> String { pub fn print(&self, args: &VecDeque<Expression>) -> String {
match self { match self {
Operator::Negative => { Operator::Negative => {
return format!("-{}", self.add_parens_to_arg(context, &args[0])); return format!("-{}", self.add_parens_to_arg(&args[0]));
}, },
Operator::Sqrt => { Operator::Sqrt => {
return format!( return format!(
"√{}", "√{}",
self.add_parens_to_arg(context, &args[0]), self.add_parens_to_arg(&args[0]),
); );
}, },
Operator::ModuloLong => { Operator::ModuloLong => {
return format!( return format!(
"{} mod {}", "{} mod {}",
self.add_parens_to_arg(context, &args[0]), self.add_parens_to_arg(&args[0]),
self.add_parens_to_arg(context, &args[1]) self.add_parens_to_arg(&args[1])
); );
}, },
Operator::DivideLong => { Operator::DivideLong => {
return format!( return format!(
"{} per {}", "{} per {}",
self.add_parens_to_arg(context, &args[0]), self.add_parens_to_arg(&args[0]),
self.add_parens_to_arg(context, &args[1]) self.add_parens_to_arg(&args[1])
); );
}, },
Operator::UnitConvert => { Operator::UnitConvert => {
return format!( return format!(
"{} to {}", "{} to {}",
self.add_parens_to_arg(context, &args[0]), self.add_parens_to_arg(&args[0]),
self.add_parens_to_arg(context, &args[1]) self.add_parens_to_arg(&args[1])
); );
}, },
Operator::Modulo => { Operator::Modulo => {
return format!( return format!(
"{} % {}", "{} % {}",
self.add_parens_to_arg(context, &args[0]), self.add_parens_to_arg(&args[0]),
self.add_parens_to_arg(context, &args[1]) self.add_parens_to_arg(&args[1])
); );
}, },
Operator::Subtract => { Operator::Subtract => {
return format!( return format!(
"{} - {}", "{} - {}",
self.add_parens_to_arg(context, &args[0]), self.add_parens_to_arg(&args[0]),
self.add_parens_to_arg(context, &args[1]) self.add_parens_to_arg(&args[1])
); );
}, },
@ -208,13 +208,13 @@ impl Operator {
let q = &args[1]; let q = &args[1];
if { if {
context.config.enable_super_powers && //context.config.enable_super_powers &&
q.is_unitless_integer() && q.is_unitless_integer() &&
!q.display(context).contains("e") !q.to_string().contains("e")
} { } {
// Write integer powers as a superscript // Write integer powers as a superscript
let mut b = String::new(); let mut b = String::new();
for c in q.display(context).chars() { for c in q.to_string().chars() {
b.push(match c { b.push(match c {
'-' => '⁻', '-' => '⁻',
'0' => '⁰', '0' => '⁰',
@ -233,27 +233,27 @@ impl Operator {
return format!( return format!(
"{}{}", "{}{}",
self.add_parens_to_arg_strict(context, &args[0]), self.add_parens_to_arg_strict(&args[0]),
b b
); );
} else { } else {
return format!( return format!(
"{}^{}", "{}^{}",
self.add_parens_to_arg_strict(context, &args[0]), self.add_parens_to_arg_strict(&args[0]),
self.add_parens_to_arg_strict(context, &args[1]) self.add_parens_to_arg_strict(&args[1])
); );
} }
}, },
Operator::Factorial => { Operator::Factorial => {
return format!("{}!", self.add_parens_to_arg(context, &args[0])); return format!("{}!", self.add_parens_to_arg(&args[0]));
}, },
Operator::Add => { Operator::Add => {
return format!( return format!(
"{} + {}", "{} + {}",
self.add_parens_to_arg(context, &args[0]), self.add_parens_to_arg(&args[0]),
self.add_parens_to_arg(context, &args[1]) self.add_parens_to_arg(&args[1])
); );
}, },
@ -283,26 +283,26 @@ impl Operator {
if let Expression::Quantity(_, u) = b { if let Expression::Quantity(_, u) = b {
if u.unit.no_space() { if u.unit.no_space() {
return format!("{}{}", return format!("{}{}",
self.add_parens_to_arg_strict(context, a), self.add_parens_to_arg_strict(a),
self.add_parens_to_arg_strict(context, b) self.add_parens_to_arg_strict(b)
); );
} else { } else {
return format!("{} {}", return format!("{} {}",
self.add_parens_to_arg_strict(context, a), self.add_parens_to_arg_strict(a),
self.add_parens_to_arg_strict(context, b) self.add_parens_to_arg_strict(b)
); );
} }
} else { } else {
return format!("{}{}", return format!("{}{}",
self.add_parens_to_arg_strict(context, a), self.add_parens_to_arg_strict(a),
self.add_parens_to_arg_strict(context, b) self.add_parens_to_arg_strict(b)
); );
}; };
} else { } else {
return format!("{} × {}", return format!("{} × {}",
self.add_parens_to_arg_strict(context, a), self.add_parens_to_arg_strict(a),
self.add_parens_to_arg_strict(context, b) self.add_parens_to_arg_strict(b)
); );
} }
}, },
@ -313,25 +313,25 @@ impl Operator {
if let Expression::Quantity(_, q) = a { if let Expression::Quantity(_, q) = a {
if q.is_one() && context.config.enable_one_over_power { if q.is_one() {
return format!("{}⁻¹", return format!("{}⁻¹",
self.add_parens_to_arg_strict(context, b) self.add_parens_to_arg_strict(b)
); );
} }
} }
return format!("{} ÷ {}", return format!("{} ÷ {}",
self.add_parens_to_arg_strict(context, a), self.add_parens_to_arg_strict(a),
self.add_parens_to_arg_strict(context, b) self.add_parens_to_arg_strict(b)
); );
}, },
Operator::Function(s) => { Operator::Function(s) => {
return format!("{}({})", s.to_string(), args[0].display(context)); return format!("{}({})", s.to_string(), args[0].to_string());
}, },
Operator::UserFunction(s) => { Operator::UserFunction(s) => {
return format!("{}({})", s, args[0].display(context)); return format!("{}({})", s.to_string(), args[0].to_string());
} }
}; };
} }

View File

@ -7,7 +7,6 @@ use std::ops::{
}; };
use std::cmp::Ordering; use std::cmp::Ordering;
use crate::context::Context;
use crate::quantity::Unit; use crate::quantity::Unit;
use crate::quantity::FreeUnit; use crate::quantity::FreeUnit;
@ -22,12 +21,12 @@ pub struct Quantity {
impl Quantity { impl ToString for Quantity {
pub fn display(&self, context: &Context) -> String { fn to_string(&self) -> String {
let n = self.scalar.to_string(); let n = self.scalar.to_string();
if self.unitless() { return n; } if self.unitless() { return n; }
let u = self.unit.display(context); let u = self.unit.to_string();
if self.is_one() { return u; }; if self.is_one() { return u; };
if self.unit.no_space() { if self.unit.no_space() {
@ -39,11 +38,11 @@ impl Quantity {
} }
impl Quantity { impl Quantity {
pub fn display_outer(&self, context: &Context) -> String { pub fn to_string_outer(&self) -> String {
let n = self.scalar.to_string(); let n = self.scalar.to_string();
if self.unitless() { return n; } if self.unitless() { return n; }
let u = self.unit.display(context); let u = self.unit.to_string();
if self.unit.no_space() { if self.unit.no_space() {
return format!("{n}{u}"); return format!("{n}{u}");
} else { } else {

View File

@ -4,7 +4,6 @@ use std::ops::{
MulAssign, DivAssign MulAssign, DivAssign
}; };
use crate::context::Context;
use crate::quantity::Scalar; use crate::quantity::Scalar;
use crate::quantity::Quantity; use crate::quantity::Quantity;
use super::FreeUnit; use super::FreeUnit;
@ -17,8 +16,8 @@ pub struct Unit {
pub val: HashMap<FreeUnit, Scalar> pub val: HashMap<FreeUnit, Scalar>
} }
impl Unit { impl ToString for Unit {
pub fn display(&self, context: &Context) -> String { fn to_string(&self) -> String {
if self.unitless() { return String::new(); }; if self.unitless() { return String::new(); };
@ -38,11 +37,7 @@ impl Unit {
if *p == Scalar::new_rational(1f64).unwrap() { if *p == Scalar::new_rational(1f64).unwrap() {
t.push_str(&format!("{c}·")); t.push_str(&format!("{c}·"));
} else if { } else if p.is_int() && !p.to_string().contains("e"){
context.config.enable_super_powers &&
p.is_int() &&
!p.to_string().contains("e")
} {
t.push_str(&c); t.push_str(&c);
for c in p.to_string().chars() { for c in p.to_string().chars() {
t.push( match c { t.push( match c {
@ -79,11 +74,7 @@ impl Unit {
bottom_count += 1; bottom_count += 1;
if t.len() != 0 && *p == Scalar::new_rational(-1f64).unwrap() { if t.len() != 0 && *p == Scalar::new_rational(-1f64).unwrap() {
b.push_str(&format!("{c}·")); b.push_str(&format!("{c}·"));
} else if { } else if p.is_int() && !p.to_string().contains("e") {
context.config.enable_super_powers &&
p.is_int() &&
!p.to_string().contains("e")
} {
b.push_str(&c); b.push_str(&c);
for c in p.to_string().chars() { for c in p.to_string().chars() {
if c == '-' && t.len() != 0 { continue; } if c == '-' && t.len() != 0 { continue; }

View File

@ -10,10 +10,8 @@ fn eval_to_str(s: &str) -> Result<String, ()> {
}; };
//let out_str = g.print(); //let out_str = g.print();
let mut c = Context::new(); return match evaluate(&mut Context::new(), &g) {
Ok(x) => Ok(x.to_string_outer()),
return match evaluate(&mut c, &g) {
Ok(x) => Ok(x.display_outer(&c)),
Err(_) => Err(()) Err(_) => Err(())
}; };
} }