forked from extern/nushell
@ -14,6 +14,7 @@ fn from_delimited_string_to_value(
|
||||
.delimiter(separator as u8)
|
||||
.from_reader(s.as_bytes());
|
||||
let tag = tag.into();
|
||||
let span = tag.span;
|
||||
|
||||
let headers = if headerless {
|
||||
(1..=reader.headers()?.len())
|
||||
@ -30,7 +31,10 @@ fn from_delimited_string_to_value(
|
||||
if let Ok(i) = value.parse::<i64>() {
|
||||
tagged_row.insert_value(header, UntaggedValue::int(i).into_value(&tag))
|
||||
} else if let Ok(f) = value.parse::<f64>() {
|
||||
tagged_row.insert_value(header, UntaggedValue::decimal(f).into_value(&tag))
|
||||
tagged_row.insert_value(
|
||||
header,
|
||||
UntaggedValue::decimal_from_float(f, span).into_value(&tag),
|
||||
)
|
||||
} else {
|
||||
tagged_row.insert_value(header, UntaggedValue::string(value).into_value(&tag))
|
||||
}
|
||||
|
@ -39,11 +39,12 @@ impl WholeStreamCommand for FromJSON {
|
||||
|
||||
fn convert_json_value_to_nu_value(v: &serde_hjson::Value, tag: impl Into<Tag>) -> Value {
|
||||
let tag = tag.into();
|
||||
let span = tag.span;
|
||||
|
||||
match v {
|
||||
serde_hjson::Value::Null => UntaggedValue::Primitive(Primitive::Nothing).into_value(&tag),
|
||||
serde_hjson::Value::Bool(b) => UntaggedValue::boolean(*b).into_value(&tag),
|
||||
serde_hjson::Value::F64(n) => UntaggedValue::decimal(*n).into_value(&tag),
|
||||
serde_hjson::Value::F64(n) => UntaggedValue::decimal_from_float(*n, span).into_value(&tag),
|
||||
serde_hjson::Value::U64(n) => UntaggedValue::int(*n).into_value(&tag),
|
||||
serde_hjson::Value::I64(n) => UntaggedValue::int(*n).into_value(&tag),
|
||||
serde_hjson::Value::String(s) => {
|
||||
|
@ -45,6 +45,7 @@ async fn from_ods(
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let span = tag.span;
|
||||
let registry = registry.clone();
|
||||
|
||||
let (
|
||||
@ -73,7 +74,7 @@ async fn from_ods(
|
||||
let value = match cell {
|
||||
DataType::Empty => UntaggedValue::nothing(),
|
||||
DataType::String(s) => UntaggedValue::string(s),
|
||||
DataType::Float(f) => UntaggedValue::decimal(*f),
|
||||
DataType::Float(f) => UntaggedValue::decimal_from_float(*f, span),
|
||||
DataType::Int(i) => UntaggedValue::int(*i),
|
||||
DataType::Bool(b) => UntaggedValue::boolean(*b),
|
||||
_ => UntaggedValue::nothing(),
|
||||
|
@ -30,11 +30,12 @@ impl WholeStreamCommand for FromTOML {
|
||||
|
||||
pub fn convert_toml_value_to_nu_value(v: &toml::Value, tag: impl Into<Tag>) -> Value {
|
||||
let tag = tag.into();
|
||||
let span = tag.span;
|
||||
|
||||
match v {
|
||||
toml::Value::Boolean(b) => UntaggedValue::boolean(*b).into_value(tag),
|
||||
toml::Value::Integer(n) => UntaggedValue::int(*n).into_value(tag),
|
||||
toml::Value::Float(n) => UntaggedValue::decimal(*n).into_value(tag),
|
||||
toml::Value::Float(n) => UntaggedValue::decimal_from_float(*n, span).into_value(tag),
|
||||
toml::Value::String(s) => {
|
||||
UntaggedValue::Primitive(Primitive::String(String::from(s))).into_value(tag)
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ async fn from_xlsx(
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let tag = args.call_info.name_tag.clone();
|
||||
let span = tag.span;
|
||||
let registry = registry.clone();
|
||||
let (
|
||||
FromXLSXArgs {
|
||||
@ -73,7 +74,7 @@ async fn from_xlsx(
|
||||
let value = match cell {
|
||||
DataType::Empty => UntaggedValue::nothing(),
|
||||
DataType::String(s) => UntaggedValue::string(s),
|
||||
DataType::Float(f) => UntaggedValue::decimal(*f),
|
||||
DataType::Float(f) => UntaggedValue::decimal_from_float(*f, span),
|
||||
DataType::Int(i) => UntaggedValue::int(*i),
|
||||
DataType::Bool(b) => UntaggedValue::boolean(*b),
|
||||
_ => UntaggedValue::nothing(),
|
||||
|
@ -58,6 +58,7 @@ fn convert_yaml_value_to_nu_value(
|
||||
tag: impl Into<Tag>,
|
||||
) -> Result<Value, ShellError> {
|
||||
let tag = tag.into();
|
||||
let span = tag.span;
|
||||
|
||||
let err_not_compatible_number = ShellError::labeled_error(
|
||||
"Expected a compatible number",
|
||||
@ -69,10 +70,11 @@ fn convert_yaml_value_to_nu_value(
|
||||
serde_yaml::Value::Number(n) if n.is_i64() => {
|
||||
UntaggedValue::int(n.as_i64().ok_or_else(|| err_not_compatible_number)?).into_value(tag)
|
||||
}
|
||||
serde_yaml::Value::Number(n) if n.is_f64() => {
|
||||
UntaggedValue::decimal(n.as_f64().ok_or_else(|| err_not_compatible_number)?)
|
||||
.into_value(tag)
|
||||
}
|
||||
serde_yaml::Value::Number(n) if n.is_f64() => UntaggedValue::decimal_from_float(
|
||||
n.as_f64().ok_or_else(|| err_not_compatible_number)?,
|
||||
span,
|
||||
)
|
||||
.into_value(tag),
|
||||
serde_yaml::Value::String(s) => UntaggedValue::string(s).into_value(tag),
|
||||
serde_yaml::Value::Sequence(a) => {
|
||||
let result: Result<Vec<Value>, ShellError> = a
|
||||
|
@ -53,7 +53,11 @@ impl WholeStreamCommand for SubCommand {
|
||||
vec![Example {
|
||||
description: "Get the average of a list of numbers",
|
||||
example: "echo [-50 100.0 25] | math avg",
|
||||
result: Some(vec![UntaggedValue::decimal(25).into()]),
|
||||
result: Some(vec![UntaggedValue::decimal_from_float(
|
||||
25.0,
|
||||
Span::unknown(),
|
||||
)
|
||||
.into()]),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ mod tests {
|
||||
sum::summation, utils::calculate, utils::MathFunction, variance::variance,
|
||||
};
|
||||
use nu_plugin::row;
|
||||
use nu_plugin::test_helpers::value::{decimal, int, table};
|
||||
use nu_plugin::test_helpers::value::{decimal, decimal_from_float, int, table};
|
||||
use nu_protocol::Value;
|
||||
use std::str::FromStr;
|
||||
|
||||
@ -98,17 +98,17 @@ mod tests {
|
||||
},
|
||||
TestCase {
|
||||
description: "Mixed Values",
|
||||
values: vec![int(10), decimal(26.5), decimal(26.5)],
|
||||
values: vec![int(10), decimal_from_float(26.5), decimal_from_float(26.5)],
|
||||
expected_err: None,
|
||||
expected_res: vec![
|
||||
Ok(decimal(21)),
|
||||
Ok(int(10)),
|
||||
Ok(decimal(26.5)),
|
||||
Ok(decimal(26.5)),
|
||||
Ok(table(&[decimal(26.5)])),
|
||||
Ok(decimal_from_float(26.5)),
|
||||
Ok(decimal_from_float(26.5)),
|
||||
Ok(table(&[decimal_from_float(26.5)])),
|
||||
Ok(decimal(BigDecimal::from_str("7.77817459305202276840928798315333943213319531457321440247173855894902863154158871367713143880202865").expect("Could not convert to decimal from string"))),
|
||||
Ok(decimal(63)),
|
||||
Ok(decimal(60.5)),
|
||||
Ok(decimal_from_float(60.5)),
|
||||
],
|
||||
},
|
||||
TestCase {
|
||||
@ -128,14 +128,14 @@ mod tests {
|
||||
},
|
||||
TestCase {
|
||||
description: "Mixed Negative Values",
|
||||
values: vec![decimal(-13.5), decimal(-11.5), int(10)],
|
||||
values: vec![decimal_from_float(-13.5), decimal_from_float(-11.5), int(10)],
|
||||
expected_err: None,
|
||||
expected_res: vec![
|
||||
Ok(decimal(-5)),
|
||||
Ok(decimal(-13.5)),
|
||||
Ok(decimal_from_float(-13.5)),
|
||||
Ok(int(10)),
|
||||
Ok(decimal(-11.5)),
|
||||
Ok(table(&[decimal(-13.5), decimal(-11.5), int(10)])),
|
||||
Ok(decimal_from_float(-11.5)),
|
||||
Ok(table(&[decimal_from_float(-13.5), decimal_from_float(-11.5), int(10)])),
|
||||
Ok(decimal(BigDecimal::from_str("10.63798226482196513098036125801342585449179971588207816421068645273754903468375890632981926875247027").expect("Could not convert to decimal from string"))),
|
||||
Ok(decimal(-15)),
|
||||
Ok(decimal(BigDecimal::from_str("113.1666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667").expect("Could not convert to decimal from string"))),
|
||||
@ -151,10 +151,10 @@ mod tests {
|
||||
],
|
||||
expected_err: None,
|
||||
expected_res: vec![
|
||||
Ok(row!["col1".to_owned() => decimal(2.5), "col2".to_owned() => decimal(6.5)]),
|
||||
Ok(row!["col1".to_owned() => decimal_from_float(2.5), "col2".to_owned() => decimal_from_float(6.5)]),
|
||||
Ok(row!["col1".to_owned() => int(1), "col2".to_owned() => int(5)]),
|
||||
Ok(row!["col1".to_owned() => int(4), "col2".to_owned() => int(8)]),
|
||||
Ok(row!["col1".to_owned() => decimal(2.5), "col2".to_owned() => decimal(6.5)]),
|
||||
Ok(row!["col1".to_owned() => decimal_from_float(2.5), "col2".to_owned() => decimal_from_float(6.5)]),
|
||||
Ok(row![
|
||||
"col1".to_owned() => table(&[int(1), int(2), int(3), int(4)]),
|
||||
"col2".to_owned() => table(&[int(5), int(6), int(7), int(8)])
|
||||
@ -164,7 +164,7 @@ mod tests {
|
||||
"col2".to_owned() => decimal(BigDecimal::from_str("1.118033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137").expect("Could not convert to decimal from string"))
|
||||
]),
|
||||
Ok(row!["col1".to_owned() => int(10), "col2".to_owned() => int(26)]),
|
||||
Ok(row!["col1".to_owned() => decimal(1.25), "col2".to_owned() => decimal(1.25)]),
|
||||
Ok(row!["col1".to_owned() => decimal_from_float(1.25), "col2".to_owned() => decimal_from_float(1.25)]),
|
||||
],
|
||||
},
|
||||
// TODO-Uncomment once Issue: https://github.com/nushell/nushell/issues/1883 is resolved
|
||||
|
@ -41,7 +41,11 @@ impl WholeStreamCommand for SubCommand {
|
||||
vec![Example {
|
||||
description: "Evalulate math in the pipeline",
|
||||
example: "echo '10 / 4' | math eval",
|
||||
result: Some(vec![UntaggedValue::decimal(2.5).into()]),
|
||||
result: Some(vec![UntaggedValue::decimal_from_float(
|
||||
2.5,
|
||||
Span::unknown(),
|
||||
)
|
||||
.into()]),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,11 @@ impl WholeStreamCommand for SubCommand {
|
||||
vec![Example {
|
||||
description: "Get the median of a list of numbers",
|
||||
example: "echo [3 8 9 12 12 15] | math median",
|
||||
result: Some(vec![UntaggedValue::decimal(10.5).into()]),
|
||||
result: Some(vec![UntaggedValue::decimal_from_float(
|
||||
10.5,
|
||||
Span::unknown(),
|
||||
)
|
||||
.into()]),
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
@ -99,12 +99,20 @@ impl WholeStreamCommand for SubCommand {
|
||||
Example {
|
||||
description: "Get the variance of a list of numbers",
|
||||
example: "echo [1 2 3 4 5] | math variance",
|
||||
result: Some(vec![UntaggedValue::decimal(2).into()]),
|
||||
result: Some(vec![UntaggedValue::decimal_from_float(
|
||||
2.0,
|
||||
Span::unknown(),
|
||||
)
|
||||
.into()]),
|
||||
},
|
||||
Example {
|
||||
description: "Get the sample variance of a list of numbers",
|
||||
example: "echo [1 2 3 4 5] | math variance -s",
|
||||
result: Some(vec![UntaggedValue::decimal(2.5).into()]),
|
||||
result: Some(vec![UntaggedValue::decimal_from_float(
|
||||
2.5,
|
||||
Span::unknown(),
|
||||
)
|
||||
.into()]),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use nu_source::Tagged;
|
||||
use num_bigint::{BigInt, BigUint, ToBigInt};
|
||||
|
||||
// TODO num_format::SystemLocale once platform-specific dependencies are stable (see Cargo.toml)
|
||||
use num_format::{Locale, ToFormattedString};
|
||||
use num_format::Locale;
|
||||
use num_traits::{Pow, Signed};
|
||||
use std::iter;
|
||||
|
||||
@ -40,12 +40,15 @@ impl WholeStreamCommand for SubCommand {
|
||||
"decimal digits to which to round",
|
||||
Some('d'),
|
||||
)
|
||||
.switch(
|
||||
"group-digits",
|
||||
// TODO according to system localization
|
||||
"group digits, currently by thousand with commas",
|
||||
Some('g'),
|
||||
)
|
||||
/*
|
||||
FIXME: this isn't currently supported because of num_format being out of date. Once it's updated, re-enable this
|
||||
.switch(
|
||||
"group-digits",
|
||||
// TODO according to system localization
|
||||
"group digits, currently by thousand with commas",
|
||||
Some('g'),
|
||||
)
|
||||
*/
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
@ -67,6 +70,8 @@ impl WholeStreamCommand for SubCommand {
|
||||
example: "= 1.7 | str from -d 0",
|
||||
result: Some(vec![UntaggedValue::string("2").into_untagged_value()]),
|
||||
},
|
||||
/*
|
||||
FIXME: this isn't currently supported because of num_format being out of date. Once it's updated, re-enable this
|
||||
Example {
|
||||
description: "format large number with localized digit grouping",
|
||||
example: "= 1000000.2 | str from -g",
|
||||
@ -74,6 +79,7 @@ impl WholeStreamCommand for SubCommand {
|
||||
UntaggedValue::string("1,000,000.2").into_untagged_value()
|
||||
]),
|
||||
},
|
||||
*/
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -147,7 +153,7 @@ pub fn action(
|
||||
}
|
||||
|
||||
fn format_bigint(int: &BigInt) -> String {
|
||||
int.to_formatted_string(&Locale::en)
|
||||
format!("{}", int)
|
||||
|
||||
// TODO once platform-specific dependencies are stable (see Cargo.toml)
|
||||
// #[cfg(windows)]
|
||||
@ -200,10 +206,8 @@ fn format_decimal(mut decimal: BigDecimal, digits: Option<u64>, group_digits: bo
|
||||
|
||||
let format_default_loc = |int_part: BigInt| {
|
||||
let loc = Locale::en;
|
||||
let (int_str, sep) = (
|
||||
int_part.to_formatted_string(&loc),
|
||||
String::from(loc.decimal()),
|
||||
);
|
||||
//TODO: when num_format is available for recent bigint, replace this with the locale-based format
|
||||
let (int_str, sep) = (format!("{}", int_part), String::from(loc.decimal()));
|
||||
|
||||
format!("{}{}{}", int_str, sep, dec_str)
|
||||
};
|
||||
|
@ -113,7 +113,7 @@ fn action(input: &Value, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{action, SubCommand};
|
||||
use nu_plugin::test_helpers::value::{decimal, string};
|
||||
use nu_plugin::test_helpers::value::{decimal_from_float, string};
|
||||
use nu_source::Tag;
|
||||
|
||||
#[test]
|
||||
@ -127,7 +127,7 @@ mod tests {
|
||||
#[allow(clippy::approx_constant)]
|
||||
fn turns_to_integer() {
|
||||
let word = string("3.1415");
|
||||
let expected = decimal(3.1415);
|
||||
let expected = decimal_from_float(3.1415);
|
||||
|
||||
let actual = action(&word, Tag::unknown()).unwrap();
|
||||
assert_eq!(actual, expected);
|
||||
|
Reference in New Issue
Block a user