Merge branch 'master' into units

This commit is contained in:
PaddiM8 2020-06-13 21:57:27 +02:00
commit 7a4fefe1d0
6 changed files with 76 additions and 23 deletions

4
Cargo.lock generated
View File

@ -138,7 +138,7 @@ dependencies = [
[[package]]
name = "kalk"
version = "0.1.9"
version = "0.1.10"
dependencies = [
"phf",
"regex",
@ -148,7 +148,7 @@ dependencies = [
[[package]]
name = "kalk_cli"
version = "0.1.8"
version = "0.1.9"
dependencies = [
"ansi_term",
"kalk",

View File

@ -5,7 +5,8 @@
![Build status](https://img.shields.io/travis/PaddiM8/kalk/master?label=build%20%26%20test)
Kalk is a calculator (both program and library) that supports user-defined variables and functions.
Kalk is a calculator (both program and library) that supports user-defined variables and functions.
[Project kanban board (Kolan)](https://kolan.smrk.me/Board/4RAdMjLDz)
![](example.png)

View File

@ -1,6 +1,6 @@
[package]
name = "kalk"
version = "0.1.9"
version = "0.1.10"
authors = ["PaddiM8"]
edition = "2018"
readme = "README.md"

View File

@ -1,6 +1,6 @@
[package]
name = "kalk_cli"
version = "0.1.8"
version = "0.1.9"
authors = ["PaddiM8"]
edition = "2018"
readme = "../README.md"
@ -15,7 +15,7 @@ path = "src/main.rs"
name = "kalk"
[dependencies]
kalk = { path = "../kalk", version = "^0.1.9" }
kalk = { path = "../kalk", version = "^0.1.10" }
rustyline = "6.1.2"
ansi_term = "0.12"
regex = "1"

View File

@ -21,22 +21,37 @@ fn main() {
break;
};
if arg == "-i" {
let file_name = &args.next().expect("Expected input file."); // The next argument will be the file name.
let mut file_content = String::new();
File::open(&file_name)
.expect("Couldn't find file.")
.read_to_string(&mut file_content)
.expect("Failed to read input file.");
match arg.as_ref() {
"-h" | "--help" => {
// The indentation... Will have to do something more scalable in the future.
println!(
"
-= kalk help =-\n
kalk [OPTIONS] [INPUT]
-h, --help : show this
-i : load a file with predefined functions/variables
"
);
return;
}
"-i" => {
let file_name = &args.next().expect("Expected input file."); // The next argument will be the file name.
let mut file_content = String::new();
File::open(&file_name)
.expect("Couldn't find file.")
.read_to_string(&mut file_content)
.expect("Failed to read input file.");
// Parse the input file content, resulting in the symbol table being filled out.
// Output is not needed here.
parser::eval(&mut parser_context, &file_content, 53)
.expect("Failed to parse input file.");
} else {
// Main argument. This is expected to be a maths expression.
// After the loop is finished, this will be parsed and outputted.
expr_input = Some(arg);
// Parse the input file content, resulting in the symbol table being filled out.
// Output is not needed here.
parser::eval(&mut parser_context, &file_content, 53)
.expect("Failed to parse input file.");
}
_ => {
// Main argument. This is expected to be a maths expression.
// After the loop is finished, this will be parsed and outputted.
expr_input = Some(arg);
}
}
}

View File

@ -16,7 +16,11 @@ pub fn eval(parser: &mut parser::Context, input: &str) {
let num = if exp <= 0 {
// 0 < x < 1
format!("0.{}{}", "0".repeat(exp.abs() as usize), digits)
round(
format!("0.{}{}", "0".repeat(exp.abs() as usize), digits)
.trim_end_matches('0'),
)
.to_string()
} else if use_sci_notation || result.fract() != 0 {
// Insert the comma if there are supposed to be decimals.
let mut chars: Vec<char> = digits
@ -25,7 +29,7 @@ pub fn eval(parser: &mut parser::Context, input: &str) {
.chars()
.collect();
chars.insert(comma_pos, '.');
chars.into_iter().collect::<String>()
round(&chars.into_iter().collect::<String>()).to_string()
} else {
// Regular number
digits[..(exp as usize)].to_string()
@ -47,6 +51,39 @@ pub fn print_err(msg: &str) {
println!("{}", Red.paint(msg));
}
fn round(value: &str) -> String {
let mut value_iter = value.chars().into_iter().rev().skip(1);
let last_char = value_iter.next().unwrap();
let mut last_char_count = 1;
// Find out how many repeating trailing (equal) characters there are
for c in value_iter {
if c == last_char {
last_char_count += 1;
} else {
break;
}
}
// Don't round if there aren't that many
if last_char_count < 5 {
return value.to_string();
}
// Remove zeroes.
// If it's nines, round it up.
// Otherwise, only show 3 of them and then three dots:
match last_char {
'0' => value[..value.len() - last_char_count - 1].to_string(),
'9' => value.parse::<f32>().unwrap().ceil().to_string(),
_ => format!(
"{}{}...",
&value[..value.len() - last_char_count - 1],
last_char.to_string().repeat(3)
),
}
}
fn print_calc_err(err: CalcError) {
print_err(&match err {
IncorrectAmountOfArguments(expected, func, got) => format!(