mirror of
https://github.com/nushell/nushell.git
synced 2024-12-22 15:13:01 +01:00
Basic support for decimal numbers
This commit is more substantial than it looks: there was basically no real support for decimals before, and that impacted values all the way through. I also made Size contain a decimal instead of an integer (`1.6kb` is a reasonable thing to type), which impacted a bunch of code. The biggest impact of this commit is that it creates many more possible ways for valid nu types to fail to serialize as toml, json, etc. which typically can't support the full range of Decimal (or Bigint, which I also think we should support). This commit makes to-toml fallible, and a similar effort is necessary for the rest of the serializations. We also need to figure out how to clearly communicate to users what has happened, but failing to serialize to toml seems clearly superior to me than weird errors in basic math operations.
This commit is contained in:
parent
f274df6753
commit
138b5af82b
50
Cargo.lock
generated
50
Cargo.lock
generated
@ -1614,8 +1614,8 @@ dependencies = [
|
||||
"neso 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nom5_locate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"onig_sys 69.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pretty-hex 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1626,6 +1626,7 @@ dependencies = [
|
||||
"regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"roxmltree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rust_decimal 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustyline 5.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1648,6 +1649,37 @@ dependencies = [
|
||||
"which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.2.5"
|
||||
@ -1683,6 +1715,7 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1789,7 +1822,6 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2303,6 +2335,16 @@ name = "rust-ini"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rust_decimal"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.15"
|
||||
@ -3319,6 +3361,9 @@ dependencies = [
|
||||
"checksum nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9761d859320e381010a4f7f8ed425f2c924de33ad121ace447367c713ad561b"
|
||||
"checksum nom5_locate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d4312467f8b28d909344b934207e502212fa5a3adf1bff7428b0b86a666223d"
|
||||
"checksum ntapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f26e041cd983acbc087e30fcba770380cfa352d0e392e175b2344ebaf7ea0602"
|
||||
"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db"
|
||||
"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718"
|
||||
"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc"
|
||||
"checksum num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2"
|
||||
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
|
||||
"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e"
|
||||
@ -3393,6 +3438,7 @@ dependencies = [
|
||||
"checksum rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a194373ef527035645a1bc21b10dc2125f73497e6e155771233eb187aedd051"
|
||||
"checksum rust-argon2 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81ed8d04228b44a740c8d46ff872a28e50fff3d659f307ab4da2cc502e019ff3"
|
||||
"checksum rust-ini 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
|
||||
"checksum rust_decimal 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f7a28ded8f10361cefb69a8d8e1d195acf59344150534c165c401d6611cf013d"
|
||||
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum rustyline 5.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8ee0838a6594169a1c5f4bb9af0fe692cc99691941710a8cc6576395ede804e"
|
||||
|
@ -25,14 +25,15 @@ dunce = "1.0.0"
|
||||
indexmap = { version = "1.0.2", features = ["serde-1"] }
|
||||
chrono-humanize = "0.0.11"
|
||||
byte-unit = "3.0.1"
|
||||
ordered-float = {version = "1.0.2", features = ["serde"]}
|
||||
futures-preview = { version = "=0.3.0-alpha.18", features = ["compat", "io-compat"] }
|
||||
futures-async-stream = "=0.1.0-alpha.5"
|
||||
futures_codec = "0.2.5"
|
||||
num-traits = "0.2.8"
|
||||
term = "0.5.2"
|
||||
bytes = "0.4.12"
|
||||
log = "0.4.8"
|
||||
pretty_env_logger = "0.3.1"
|
||||
rust_decimal = "1.0.3"
|
||||
serde = { version = "1.0.98", features = ["derive"] }
|
||||
bson = "=0.13.0"
|
||||
serde_json = "1.0.40"
|
||||
|
@ -1 +1 @@
|
||||
nightly-2019-08-22
|
||||
nightly-2019-08-30
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::object::base::OF64;
|
||||
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::prelude::*;
|
||||
use bson::{decode_document, spec::BinarySubtype, Bson};
|
||||
@ -28,7 +27,7 @@ fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into<Tag>) -> Tagged<Value
|
||||
let tag = tag.into();
|
||||
|
||||
match v {
|
||||
Bson::FloatingPoint(n) => Value::Primitive(Primitive::Float(OF64::from(*n))).tagged(tag),
|
||||
Bson::FloatingPoint(n) => Value::Primitive(Primitive::from(*n)).tagged(tag),
|
||||
Bson::String(s) => Value::Primitive(Primitive::String(String::from(s))).tagged(tag),
|
||||
Bson::Array(a) => Value::List(
|
||||
a.iter()
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::object::base::OF64;
|
||||
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::prelude::*;
|
||||
|
||||
@ -34,9 +33,7 @@ fn convert_json_value_to_nu_value(v: &serde_hjson::Value, tag: impl Into<Tag>) -
|
||||
match v {
|
||||
serde_hjson::Value::Null => Value::Primitive(Primitive::Nothing).tagged(tag),
|
||||
serde_hjson::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(tag),
|
||||
serde_hjson::Value::F64(n) => {
|
||||
Value::Primitive(Primitive::Float(OF64::from(*n))).tagged(tag)
|
||||
}
|
||||
serde_hjson::Value::F64(n) => Value::Primitive(Primitive::from(*n)).tagged(tag),
|
||||
serde_hjson::Value::U64(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(tag),
|
||||
serde_hjson::Value::I64(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(tag),
|
||||
serde_hjson::Value::String(s) => {
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ShellError;
|
||||
use crate::object::base::OF64;
|
||||
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::prelude::*;
|
||||
use rusqlite::{types::ValueRef, Connection, Row, NO_PARAMS};
|
||||
@ -94,7 +93,7 @@ fn convert_sqlite_value_to_nu_value(value: ValueRef, tag: impl Into<Tag> + Clone
|
||||
match value {
|
||||
ValueRef::Null => Value::Primitive(Primitive::String(String::from(""))).tagged(tag),
|
||||
ValueRef::Integer(i) => Value::Primitive(Primitive::Int(i)).tagged(tag),
|
||||
ValueRef::Real(f) => Value::Primitive(Primitive::Float(OF64::from(f))).tagged(tag),
|
||||
ValueRef::Real(f) => Value::number(f).tagged(tag),
|
||||
t @ ValueRef::Text(_) => {
|
||||
// this unwrap is safe because we know the ValueRef is Text.
|
||||
Value::Primitive(Primitive::String(t.as_str().unwrap().to_string())).tagged(tag)
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::object::base::OF64;
|
||||
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::prelude::*;
|
||||
|
||||
@ -29,7 +28,7 @@ pub fn convert_toml_value_to_nu_value(v: &toml::Value, tag: impl Into<Tag>) -> T
|
||||
match v {
|
||||
toml::Value::Boolean(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(tag),
|
||||
toml::Value::Integer(n) => Value::Primitive(Primitive::Int(*n)).tagged(tag),
|
||||
toml::Value::Float(n) => Value::Primitive(Primitive::Float(OF64::from(*n))).tagged(tag),
|
||||
toml::Value::Float(n) => Value::Primitive(Primitive::from(*n)).tagged(tag),
|
||||
toml::Value::String(s) => Value::Primitive(Primitive::String(String::from(s))).tagged(tag),
|
||||
toml::Value::Array(a) => Value::List(
|
||||
a.iter()
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::object::base::OF64;
|
||||
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
||||
use crate::prelude::*;
|
||||
|
||||
@ -52,7 +51,7 @@ fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, tag: impl Into<Tag>) ->
|
||||
Value::Primitive(Primitive::Int(n.as_i64().unwrap())).tagged(tag)
|
||||
}
|
||||
serde_yaml::Value::Number(n) if n.is_f64() => {
|
||||
Value::Primitive(Primitive::Float(OF64::from(n.as_f64().unwrap()))).tagged(tag)
|
||||
Value::Primitive(Primitive::from(n.as_f64().unwrap())).tagged(tag)
|
||||
}
|
||||
serde_yaml::Value::String(s) => Value::string(s).tagged(tag),
|
||||
serde_yaml::Value::Sequence(a) => Value::List(
|
||||
|
@ -62,7 +62,7 @@ fn ps(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, She
|
||||
if let Ok(status) = process.status().await {
|
||||
dict.insert("status", Value::string(format!("{:?}", status)));
|
||||
}
|
||||
dict.insert("cpu", Value::float(usage.get::<ratio::percent>() as f64));
|
||||
dict.insert("cpu", Value::number(usage.get::<ratio::percent>()));
|
||||
yield ReturnSuccess::value(dict.into_tagged_value());
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::commands::UnevaluatedCallInfo;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::commands::{UnevaluatedCallInfo, WholeStreamCommand};
|
||||
use crate::errors::ShellError;
|
||||
use crate::object::Value;
|
||||
use crate::prelude::*;
|
||||
|
@ -27,11 +27,16 @@ impl WholeStreamCommand for ToBSON {
|
||||
pub fn value_to_bson_value(v: &Value) -> Bson {
|
||||
match v {
|
||||
Value::Primitive(Primitive::Boolean(b)) => Bson::Boolean(*b),
|
||||
Value::Primitive(Primitive::Bytes(b)) => Bson::I64(*b as i64),
|
||||
// FIXME: What about really big decimals?
|
||||
Value::Primitive(Primitive::Bytes(decimal)) => Bson::FloatingPoint(
|
||||
(*decimal)
|
||||
.to_f64()
|
||||
.expect("Unimplemented BUG: What about big decimals?"),
|
||||
),
|
||||
Value::Primitive(Primitive::Date(d)) => Bson::UtcDatetime(*d),
|
||||
Value::Primitive(Primitive::EndOfStream) => Bson::Null,
|
||||
Value::Primitive(Primitive::BeginningOfStream) => Bson::Null,
|
||||
Value::Primitive(Primitive::Float(f)) => Bson::FloatingPoint(f.into_inner()),
|
||||
Value::Primitive(Primitive::Decimal(d)) => Bson::FloatingPoint(d.to_f64().unwrap()),
|
||||
Value::Primitive(Primitive::Int(i)) => Bson::I64(*i),
|
||||
Value::Primitive(Primitive::Nothing) => Bson::Null,
|
||||
Value::Primitive(Primitive::String(s)) => Bson::String(s.clone()),
|
||||
|
@ -45,7 +45,7 @@ pub fn value_to_csv_value(v: &Value) -> Value {
|
||||
fn to_string_helper(v: &Value) -> Result<String, Box<dyn std::error::Error>> {
|
||||
match v {
|
||||
Value::Primitive(Primitive::Date(d)) => Ok(d.to_string()),
|
||||
Value::Primitive(Primitive::Bytes(b)) => Ok(format!("{}", *b as u64)),
|
||||
Value::Primitive(Primitive::Bytes(b)) => Ok(format!("{}", b)),
|
||||
Value::Primitive(Primitive::Boolean(_)) => Ok(v.as_string()?),
|
||||
Value::List(_) => return Ok(String::from("[list list]")),
|
||||
Value::Object(_) => return Ok(String::from("[object]")),
|
||||
|
@ -25,15 +25,18 @@ impl WholeStreamCommand for ToJSON {
|
||||
pub fn value_to_json_value(v: &Value) -> serde_json::Value {
|
||||
match v {
|
||||
Value::Primitive(Primitive::Boolean(b)) => serde_json::Value::Bool(*b),
|
||||
Value::Primitive(Primitive::Bytes(b)) => {
|
||||
serde_json::Value::Number(serde_json::Number::from(*b as u64))
|
||||
}
|
||||
Value::Primitive(Primitive::Bytes(b)) => serde_json::Value::Number(
|
||||
serde_json::Number::from(b.to_u64().expect("What about really big numbers")),
|
||||
),
|
||||
Value::Primitive(Primitive::Date(d)) => serde_json::Value::String(d.to_string()),
|
||||
Value::Primitive(Primitive::EndOfStream) => serde_json::Value::Null,
|
||||
Value::Primitive(Primitive::BeginningOfStream) => serde_json::Value::Null,
|
||||
Value::Primitive(Primitive::Float(f)) => {
|
||||
serde_json::Value::Number(serde_json::Number::from_f64(f.into_inner()).unwrap())
|
||||
}
|
||||
Value::Primitive(Primitive::Decimal(f)) => serde_json::Value::Number(
|
||||
serde_json::Number::from_f64(
|
||||
f.to_f64().expect("TODO: What about really big decimals?"),
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
Value::Primitive(Primitive::Int(i)) => {
|
||||
serde_json::Value::Number(serde_json::Number::from(*i))
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ fn nu_value_to_sqlite_string(v: Value) -> String {
|
||||
Value::Primitive(p) => match p {
|
||||
Primitive::Nothing => "NULL".into(),
|
||||
Primitive::Int(i) => format!("{}", i),
|
||||
Primitive::Float(f) => format!("{}", f.into_inner()),
|
||||
Primitive::Decimal(f) => format!("{}", f),
|
||||
Primitive::Bytes(u) => format!("{}", u),
|
||||
Primitive::String(s) => format!("'{}'", s.replace("'", "''")),
|
||||
Primitive::Boolean(true) => "1".into(),
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::errors::ranged;
|
||||
use crate::object::{Primitive, Value};
|
||||
use crate::prelude::*;
|
||||
|
||||
@ -22,10 +23,12 @@ impl WholeStreamCommand for ToTOML {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn value_to_toml_value(v: &Value) -> toml::Value {
|
||||
match v {
|
||||
pub fn value_to_toml_value(v: &Value) -> Result<toml::Value, ShellError> {
|
||||
Ok(match v {
|
||||
Value::Primitive(Primitive::Boolean(b)) => toml::Value::Boolean(*b),
|
||||
Value::Primitive(Primitive::Bytes(b)) => toml::Value::Integer(*b as i64),
|
||||
Value::Primitive(Primitive::Bytes(b)) => {
|
||||
toml::Value::Integer(ranged(b.to_i64(), "i64", b.tagged_unknown())?)
|
||||
}
|
||||
Value::Primitive(Primitive::Date(d)) => toml::Value::String(d.to_string()),
|
||||
Value::Primitive(Primitive::EndOfStream) => {
|
||||
toml::Value::String("<End of Stream>".to_string())
|
||||
@ -33,13 +36,15 @@ pub fn value_to_toml_value(v: &Value) -> toml::Value {
|
||||
Value::Primitive(Primitive::BeginningOfStream) => {
|
||||
toml::Value::String("<Beginning of Stream>".to_string())
|
||||
}
|
||||
Value::Primitive(Primitive::Float(f)) => toml::Value::Float(f.into_inner()),
|
||||
Value::Primitive(Primitive::Decimal(f)) => {
|
||||
toml::Value::Float(ranged(f.to_f64(), "f64", f.tagged_unknown())?)
|
||||
}
|
||||
Value::Primitive(Primitive::Int(i)) => toml::Value::Integer(*i),
|
||||
Value::Primitive(Primitive::Nothing) => toml::Value::String("<Nothing>".to_string()),
|
||||
Value::Primitive(Primitive::String(s)) => toml::Value::String(s.clone()),
|
||||
Value::Primitive(Primitive::Path(s)) => toml::Value::String(s.display().to_string()),
|
||||
|
||||
Value::List(l) => toml::Value::Array(l.iter().map(|x| value_to_toml_value(x)).collect()),
|
||||
Value::List(l) => toml::Value::Array(collect_values(l)?),
|
||||
Value::Block(_) => toml::Value::String("<Block>".to_string()),
|
||||
Value::Binary(b) => {
|
||||
toml::Value::Array(b.iter().map(|x| toml::Value::Integer(*x as i64)).collect())
|
||||
@ -47,11 +52,21 @@ pub fn value_to_toml_value(v: &Value) -> toml::Value {
|
||||
Value::Object(o) => {
|
||||
let mut m = toml::map::Map::new();
|
||||
for (k, v) in o.entries.iter() {
|
||||
m.insert(k.clone(), value_to_toml_value(v));
|
||||
m.insert(k.clone(), value_to_toml_value(v)?);
|
||||
}
|
||||
toml::Value::Table(m)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn collect_values(input: &Vec<Tagged<Value>>) -> Result<Vec<toml::Value>, ShellError> {
|
||||
let mut out = vec![];
|
||||
|
||||
for value in input {
|
||||
out.push(value_to_toml_value(value)?);
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn to_toml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||
@ -61,7 +76,7 @@ fn to_toml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream
|
||||
|
||||
Ok(out
|
||||
.values
|
||||
.map(move |a| match toml::to_string(&value_to_toml_value(&a)) {
|
||||
.map(move |a| match toml::to_string(&value_to_toml_value(&a)?) {
|
||||
Ok(val) => {
|
||||
return ReturnSuccess::value(
|
||||
Value::Primitive(Primitive::String(val)).simple_spanned(name_span),
|
||||
|
@ -45,7 +45,7 @@ pub fn value_to_tsv_value(v: &Value) -> Value {
|
||||
fn to_string_helper(v: &Value) -> Result<String, Box<dyn std::error::Error>> {
|
||||
match v {
|
||||
Value::Primitive(Primitive::Date(d)) => Ok(d.to_string()),
|
||||
Value::Primitive(Primitive::Bytes(b)) => Ok(format!("{}", *b as u64)),
|
||||
Value::Primitive(Primitive::Bytes(b)) => Ok(format!("{}", b)),
|
||||
Value::Primitive(Primitive::Boolean(_)) => Ok(v.as_string()?),
|
||||
Value::List(_) => return Ok(String::from("[list list]")),
|
||||
Value::Object(_) => return Ok(String::from("[object]")),
|
||||
|
@ -26,13 +26,13 @@ pub fn value_to_yaml_value(v: &Value) -> serde_yaml::Value {
|
||||
match v {
|
||||
Value::Primitive(Primitive::Boolean(b)) => serde_yaml::Value::Bool(*b),
|
||||
Value::Primitive(Primitive::Bytes(b)) => {
|
||||
serde_yaml::Value::Number(serde_yaml::Number::from(*b as u64))
|
||||
serde_yaml::Value::Number(serde_yaml::Number::from(b.to_f64().unwrap()))
|
||||
}
|
||||
Value::Primitive(Primitive::Date(d)) => serde_yaml::Value::String(d.to_string()),
|
||||
Value::Primitive(Primitive::EndOfStream) => serde_yaml::Value::Null,
|
||||
Value::Primitive(Primitive::BeginningOfStream) => serde_yaml::Value::Null,
|
||||
Value::Primitive(Primitive::Float(f)) => {
|
||||
serde_yaml::Value::Number(serde_yaml::Number::from(f.into_inner()))
|
||||
Value::Primitive(Primitive::Decimal(f)) => {
|
||||
serde_yaml::Value::Number(serde_yaml::Number::from(f.to_f64().unwrap()))
|
||||
}
|
||||
Value::Primitive(Primitive::Int(i)) => {
|
||||
serde_yaml::Value::Number(serde_yaml::Number::from(*i))
|
||||
|
@ -27,7 +27,7 @@ impl PerItemCommand for Where {
|
||||
let stream = match condition {
|
||||
Tagged {
|
||||
item: Value::Block(block),
|
||||
tag,
|
||||
..
|
||||
} => {
|
||||
let result = block.invoke(&input_clone);
|
||||
match result {
|
||||
@ -39,11 +39,7 @@ impl PerItemCommand for Where {
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(ShellError::labeled_error(
|
||||
format!("Could not evaluate ({})", e.to_string()),
|
||||
"could not evaluate",
|
||||
tag.span,
|
||||
))
|
||||
return Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,17 @@ impl ShellError {
|
||||
.start()
|
||||
}
|
||||
|
||||
pub(crate) fn range_error(
|
||||
expected: impl Into<String>,
|
||||
actual: Tagged<impl fmt::Debug>,
|
||||
) -> ShellError {
|
||||
ProximateShellError::RangeError {
|
||||
kind: expected.into(),
|
||||
actual_kind: actual.map(|a| format!("{:?}", a)),
|
||||
}
|
||||
.start()
|
||||
}
|
||||
|
||||
pub(crate) fn syntax_error(problem: Tagged<impl Into<String>>) -> ShellError {
|
||||
ProximateShellError::SyntaxError {
|
||||
problem: problem.map(|p| p.into()),
|
||||
@ -242,6 +253,20 @@ impl ShellError {
|
||||
} => Diagnostic::new(Severity::Error, "Type Error")
|
||||
.with_label(Label::new_primary(span).with_message(expected)),
|
||||
|
||||
ProximateShellError::RangeError {
|
||||
kind,
|
||||
actual_kind:
|
||||
Tagged {
|
||||
item,
|
||||
tag: Tag { span, .. },
|
||||
},
|
||||
} => Diagnostic::new(Severity::Error, "Range Error").with_label(
|
||||
Label::new_primary(span).with_message(format!(
|
||||
"Expected to covert {} to {}, but it was out of range",
|
||||
item, kind
|
||||
)),
|
||||
),
|
||||
|
||||
ProximateShellError::SyntaxError {
|
||||
problem:
|
||||
Tagged {
|
||||
@ -344,6 +369,10 @@ pub enum ProximateShellError {
|
||||
error: ArgumentError,
|
||||
span: Span,
|
||||
},
|
||||
RangeError {
|
||||
kind: String,
|
||||
actual_kind: Tagged<String>,
|
||||
},
|
||||
Diagnostic(ShellDiagnostic),
|
||||
CoerceError {
|
||||
left: Tagged<String>,
|
||||
@ -423,6 +452,7 @@ impl std::fmt::Display for ShellError {
|
||||
ProximateShellError::MissingValue { .. } => write!(f, "MissingValue"),
|
||||
ProximateShellError::InvalidCommand { .. } => write!(f, "InvalidCommand"),
|
||||
ProximateShellError::TypeError { .. } => write!(f, "TypeError"),
|
||||
ProximateShellError::RangeError { .. } => write!(f, "RangeError"),
|
||||
ProximateShellError::SyntaxError { .. } => write!(f, "SyntaxError"),
|
||||
ProximateShellError::MissingProperty { .. } => write!(f, "MissingProperty"),
|
||||
ProximateShellError::ArgumentError { .. } => write!(f, "ArgumentError"),
|
||||
@ -526,3 +556,14 @@ impl<T> ShellErrorUtils<Tagged<T>> for Option<Tagged<T>> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ranged<T>(
|
||||
input: Option<T>,
|
||||
expected: impl Into<String>,
|
||||
actual: Tagged<impl fmt::Debug>,
|
||||
) -> Result<T, ShellError> {
|
||||
match input {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(ShellError::range_error(expected, actual)),
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ pub(crate) fn evaluate_baseline_expr(
|
||||
|
||||
fn evaluate_literal(literal: Tagged<hir::Literal>, source: &Text) -> Tagged<Value> {
|
||||
let result = match literal.item {
|
||||
hir::Literal::Integer(int) => Value::int(int),
|
||||
hir::Literal::Number(int) => int.into(),
|
||||
hir::Literal::Size(int, unit) => unit.compute(int),
|
||||
hir::Literal::String(span) => Value::string(span.slice(source)),
|
||||
hir::Literal::Bare => Value::string(literal.span().slice(source)),
|
||||
|
@ -25,12 +25,12 @@ mod utils;
|
||||
pub use crate::commands::command::{CallInfo, ReturnSuccess, ReturnValue};
|
||||
pub use crate::context::{SourceMap, SpanSource};
|
||||
pub use crate::env::host::BasicHost;
|
||||
pub use crate::object::base::OF64;
|
||||
pub use crate::parser::hir::SyntaxType;
|
||||
pub use crate::plugin::{serve_plugin, Plugin};
|
||||
pub use crate::utils::{AbsoluteFile, AbsolutePath, RelativePath};
|
||||
pub use cli::cli;
|
||||
pub use errors::ShellError;
|
||||
pub use num_traits::cast::ToPrimitive;
|
||||
pub use object::base::{Primitive, Value};
|
||||
pub use object::dict::{Dictionary, TaggedDictBuilder};
|
||||
pub use object::meta::{Span, Tag, Tagged, TaggedItem};
|
||||
|
@ -8,35 +8,16 @@ use crate::Text;
|
||||
use chrono::{DateTime, Utc};
|
||||
use chrono_humanize::Humanize;
|
||||
use derive_new::new;
|
||||
use ordered_float::OrderedFloat;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::path::PathBuf;
|
||||
use std::time::SystemTime;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, new, Serialize, Deserialize)]
|
||||
pub struct OF64 {
|
||||
pub(crate) inner: OrderedFloat<f64>,
|
||||
}
|
||||
|
||||
impl OF64 {
|
||||
pub(crate) fn into_inner(&self) -> f64 {
|
||||
self.inner.into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for OF64 {
|
||||
fn from(float: f64) -> Self {
|
||||
OF64::new(OrderedFloat(float))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Deserialize, Serialize)]
|
||||
pub enum Primitive {
|
||||
Nothing,
|
||||
Int(i64),
|
||||
#[allow(unused)]
|
||||
Float(OF64),
|
||||
Decimal(Decimal),
|
||||
Bytes(u64),
|
||||
String(String),
|
||||
Boolean(bool),
|
||||
@ -48,6 +29,24 @@ pub enum Primitive {
|
||||
EndOfStream,
|
||||
}
|
||||
|
||||
impl From<i64> for Primitive {
|
||||
fn from(int: i64) -> Primitive {
|
||||
Primitive::Int(int)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Decimal> for Primitive {
|
||||
fn from(decimal: Decimal) -> Primitive {
|
||||
Primitive::Decimal(decimal)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for Primitive {
|
||||
fn from(float: f64) -> Primitive {
|
||||
Primitive::Decimal(Decimal::from_f64(float).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Primitive {
|
||||
pub(crate) fn type_name(&self) -> String {
|
||||
use Primitive::*;
|
||||
@ -58,7 +57,7 @@ impl Primitive {
|
||||
EndOfStream => "end-of-stream",
|
||||
Path(_) => "path",
|
||||
Int(_) => "int",
|
||||
Float(_) => "float",
|
||||
Decimal(_) => "decimal",
|
||||
Bytes(_) => "bytes",
|
||||
String(_) => "string",
|
||||
Boolean(_) => "boolean",
|
||||
@ -76,7 +75,7 @@ impl Primitive {
|
||||
EndOfStream => write!(f, "EndOfStream"),
|
||||
Int(int) => write!(f, "{}", int),
|
||||
Path(path) => write!(f, "{}", path.display()),
|
||||
Float(float) => write!(f, "{:?}", float),
|
||||
Decimal(decimal) => write!(f, "{}", decimal),
|
||||
Bytes(bytes) => write!(f, "{}", bytes),
|
||||
String(string) => write!(f, "{:?}", string),
|
||||
Boolean(boolean) => write!(f, "{}", boolean),
|
||||
@ -84,6 +83,15 @@ impl Primitive {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn number(number: impl Into<Number>) -> Primitive {
|
||||
let number = number.into();
|
||||
|
||||
match number {
|
||||
Number::Int(int) => Primitive::Int(int),
|
||||
Number::Decimal(decimal) => Primitive::Decimal(decimal),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format(&self, field_name: Option<&String>) -> String {
|
||||
match self {
|
||||
Primitive::Nothing => String::new(),
|
||||
@ -105,7 +113,7 @@ impl Primitive {
|
||||
}
|
||||
}
|
||||
Primitive::Int(i) => format!("{}", i),
|
||||
Primitive::Float(OF64 { inner: f }) => format!("{:.*}", 2, f.into_inner()),
|
||||
Primitive::Decimal(decimal) => format!("{}", decimal),
|
||||
Primitive::String(s) => format!("{}", s),
|
||||
Primitive::Boolean(b) => match (b, field_name) {
|
||||
(true, None) => format!("Yes"),
|
||||
@ -122,7 +130,7 @@ impl Primitive {
|
||||
pub fn style(&self) -> &'static str {
|
||||
match self {
|
||||
Primitive::Bytes(0) => "c", // centre 'missing' indicator
|
||||
Primitive::Int(_) | Primitive::Bytes(_) | Primitive::Float(_) => "r",
|
||||
Primitive::Int(_) | Primitive::Bytes(_) | Primitive::Decimal(_) => "r",
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
@ -176,6 +184,15 @@ pub enum Value {
|
||||
Block(Block),
|
||||
}
|
||||
|
||||
impl Into<Value> for Number {
|
||||
fn into(self) -> Value {
|
||||
match self {
|
||||
Number::Int(int) => Value::int(int),
|
||||
Number::Decimal(decimal) => Value::decimal(decimal),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_list(values: &Vec<Tagged<Value>>) -> ValuesDebug<'_> {
|
||||
ValuesDebug { values }
|
||||
}
|
||||
@ -518,7 +535,11 @@ impl Value {
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn compare(&self, operator: &Operator, other: &Value) -> Result<bool, (String, String)> {
|
||||
pub(crate) fn compare(
|
||||
&self,
|
||||
operator: &Operator,
|
||||
other: &Value,
|
||||
) -> Result<bool, (String, String)> {
|
||||
match operator {
|
||||
_ => {
|
||||
let coerced = coerce_compare(self, other)?;
|
||||
@ -566,7 +587,7 @@ impl Value {
|
||||
match self {
|
||||
Value::Primitive(Primitive::String(s)) => Ok(s.clone()),
|
||||
Value::Primitive(Primitive::Boolean(x)) => Ok(format!("{}", x)),
|
||||
Value::Primitive(Primitive::Float(x)) => Ok(format!("{}", x.into_inner())),
|
||||
Value::Primitive(Primitive::Decimal(x)) => Ok(format!("{}", x)),
|
||||
Value::Primitive(Primitive::Int(x)) => Ok(format!("{}", x)),
|
||||
Value::Primitive(Primitive::Bytes(x)) => Ok(format!("{}", x)),
|
||||
// TODO: this should definitely be more general with better errors
|
||||
@ -612,8 +633,17 @@ impl Value {
|
||||
Value::Primitive(Primitive::Int(s.into()))
|
||||
}
|
||||
|
||||
pub fn float(s: impl Into<OF64>) -> Value {
|
||||
Value::Primitive(Primitive::Float(s.into()))
|
||||
pub fn decimal(s: impl Into<Decimal>) -> Value {
|
||||
Value::Primitive(Primitive::Decimal(s.into()))
|
||||
}
|
||||
|
||||
pub fn number(s: impl Into<Number>) -> Value {
|
||||
let num = s.into();
|
||||
|
||||
match num {
|
||||
Number::Int(int) => Value::int(int),
|
||||
Number::Decimal(decimal) => Value::decimal(decimal),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn boolean(s: impl Into<bool>) -> Value {
|
||||
@ -722,32 +752,34 @@ pub(crate) fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool
|
||||
(Operator::NotEqual, Value::Primitive(Primitive::Int(i2))) => i != *i2,
|
||||
_ => false,
|
||||
},
|
||||
Value::Primitive(Primitive::Float(i)) => match (op, rhs) {
|
||||
(Operator::LessThan, Value::Primitive(Primitive::Float(i2))) => i < *i2,
|
||||
(Operator::GreaterThan, Value::Primitive(Primitive::Float(i2))) => i > *i2,
|
||||
(Operator::LessThanOrEqual, Value::Primitive(Primitive::Float(i2))) => i <= *i2,
|
||||
(Operator::GreaterThanOrEqual, Value::Primitive(Primitive::Float(i2))) => {
|
||||
Value::Primitive(Primitive::Decimal(i)) => match (op, rhs) {
|
||||
(Operator::LessThan, Value::Primitive(Primitive::Decimal(i2))) => i < *i2,
|
||||
(Operator::GreaterThan, Value::Primitive(Primitive::Decimal(i2))) => i > *i2,
|
||||
(Operator::LessThanOrEqual, Value::Primitive(Primitive::Decimal(i2))) => {
|
||||
i <= *i2
|
||||
}
|
||||
(Operator::GreaterThanOrEqual, Value::Primitive(Primitive::Decimal(i2))) => {
|
||||
i >= *i2
|
||||
}
|
||||
(Operator::Equal, Value::Primitive(Primitive::Float(i2))) => i == *i2,
|
||||
(Operator::NotEqual, Value::Primitive(Primitive::Float(i2))) => i != *i2,
|
||||
(Operator::Equal, Value::Primitive(Primitive::Decimal(i2))) => i == *i2,
|
||||
(Operator::NotEqual, Value::Primitive(Primitive::Decimal(i2))) => i != *i2,
|
||||
(Operator::LessThan, Value::Primitive(Primitive::Int(i2))) => {
|
||||
(i.into_inner()) < *i2 as f64
|
||||
i < Decimal::from(*i2)
|
||||
}
|
||||
(Operator::GreaterThan, Value::Primitive(Primitive::Int(i2))) => {
|
||||
i.into_inner() > *i2 as f64
|
||||
i > Decimal::from(*i2)
|
||||
}
|
||||
(Operator::LessThanOrEqual, Value::Primitive(Primitive::Int(i2))) => {
|
||||
i.into_inner() <= *i2 as f64
|
||||
i <= Decimal::from(*i2)
|
||||
}
|
||||
(Operator::GreaterThanOrEqual, Value::Primitive(Primitive::Int(i2))) => {
|
||||
i.into_inner() >= *i2 as f64
|
||||
i >= Decimal::from(*i2)
|
||||
}
|
||||
(Operator::Equal, Value::Primitive(Primitive::Int(i2))) => {
|
||||
i.into_inner() == *i2 as f64
|
||||
i == Decimal::from(*i2)
|
||||
}
|
||||
(Operator::NotEqual, Value::Primitive(Primitive::Int(i2))) => {
|
||||
i.into_inner() != *i2 as f64
|
||||
i != Decimal::from(*i2)
|
||||
}
|
||||
|
||||
_ => false,
|
||||
@ -765,8 +797,8 @@ pub(crate) fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool
|
||||
|
||||
enum CompareValues {
|
||||
Ints(i64, i64),
|
||||
Floats(OF64, OF64),
|
||||
Bytes(i128, i128),
|
||||
Decimals(Decimal, Decimal),
|
||||
Bytes(u64, u64),
|
||||
String(String, String),
|
||||
}
|
||||
|
||||
@ -774,7 +806,7 @@ impl CompareValues {
|
||||
fn compare(&self) -> std::cmp::Ordering {
|
||||
match self {
|
||||
CompareValues::Ints(left, right) => left.cmp(right),
|
||||
CompareValues::Floats(left, right) => left.cmp(right),
|
||||
CompareValues::Decimals(left, right) => left.cmp(right),
|
||||
CompareValues::Bytes(left, right) => left.cmp(right),
|
||||
CompareValues::String(left, right) => left.cmp(right),
|
||||
}
|
||||
@ -797,10 +829,11 @@ fn coerce_compare_primitive(
|
||||
|
||||
Ok(match (left, right) {
|
||||
(Int(left), Int(right)) => CompareValues::Ints(*left, *right),
|
||||
(Float(left), Int(right)) => CompareValues::Floats(*left, (*right as f64).into()),
|
||||
(Int(left), Float(right)) => CompareValues::Floats((*left as f64).into(), *right),
|
||||
(Int(left), Bytes(right)) => CompareValues::Bytes(*left as i128, *right as i128),
|
||||
(Bytes(left), Int(right)) => CompareValues::Bytes(*left as i128, *right as i128),
|
||||
(Decimal(left), Decimal(right)) => CompareValues::Decimals(*left, *right),
|
||||
(Decimal(left), Int(right)) => CompareValues::Decimals(*left, (*right).into()),
|
||||
(Int(left), Decimal(right)) => CompareValues::Decimals((*left).into(), *right),
|
||||
(Int(left), Bytes(right)) => CompareValues::Bytes(*left as u64, *right),
|
||||
(Bytes(left), Int(right)) => CompareValues::Bytes(*left, *right as u64),
|
||||
(String(left), String(right)) => CompareValues::String(left.clone(), right.clone()),
|
||||
_ => return Err((left.type_name(), right.type_name())),
|
||||
})
|
||||
|
@ -36,7 +36,7 @@ pub(crate) fn write_config(config: &IndexMap<String, Tagged<Value>>) -> Result<(
|
||||
let filename = location.join("config.toml");
|
||||
touch(&filename)?;
|
||||
|
||||
let contents = value_to_toml_value(&Value::Object(Dictionary::new(config.clone())));
|
||||
let contents = value_to_toml_value(&Value::Object(Dictionary::new(config.clone())))?;
|
||||
|
||||
let contents = toml::to_string(&contents)?;
|
||||
|
||||
|
29
src/object/process.rs
Normal file
29
src/object/process.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use crate::object::{TaggedDictBuilder, Value};
|
||||
use crate::prelude::*;
|
||||
use itertools::join;
|
||||
use sysinfo::ProcessExt;
|
||||
|
||||
pub(crate) fn process_dict(proc: &sysinfo::Process, tag: impl Into<Tag>) -> Tagged<Value> {
|
||||
let mut dict = TaggedDictBuilder::new(tag);
|
||||
|
||||
let cmd = proc.cmd();
|
||||
|
||||
let cmd_value = if cmd.len() == 0 {
|
||||
Value::nothing()
|
||||
} else {
|
||||
Value::string(join(cmd, ""))
|
||||
};
|
||||
|
||||
dict.insert("pid", Value::int(proc.pid() as i64));
|
||||
dict.insert("status", Value::string(proc.status().to_string()));
|
||||
dict.insert("cpu", Value::number(proc.cpu_usage()));
|
||||
|
||||
match cmd_value {
|
||||
Value::Primitive(Primitive::Nothing) => {
|
||||
dict.insert("name", Value::string(proc.name()));
|
||||
}
|
||||
_ => dict.insert("name", cmd_value),
|
||||
}
|
||||
|
||||
dict.into_tagged_value()
|
||||
}
|
@ -129,11 +129,15 @@ impl RawExpression {
|
||||
pub type Expression = Tagged<RawExpression>;
|
||||
|
||||
impl Expression {
|
||||
pub(crate) fn int(i: impl Into<i64>, span: impl Into<Span>) -> Expression {
|
||||
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Integer(i.into())), span)
|
||||
pub(crate) fn number(i: impl Into<Number>, span: impl Into<Span>) -> Expression {
|
||||
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Number(i.into())), span)
|
||||
}
|
||||
|
||||
pub(crate) fn size(i: impl Into<i64>, unit: impl Into<Unit>, span: impl Into<Span>) -> Expression {
|
||||
pub(crate) fn size(
|
||||
i: impl Into<Number>,
|
||||
unit: impl Into<Unit>,
|
||||
span: impl Into<Span>,
|
||||
) -> Expression {
|
||||
Tagged::from_simple_spanned_item(
|
||||
RawExpression::Literal(Literal::Size(i.into(), unit.into())),
|
||||
span,
|
||||
@ -224,8 +228,8 @@ impl From<Tagged<Path>> for Expression {
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
|
||||
pub enum Literal {
|
||||
Integer(i64),
|
||||
Size(i64, Unit),
|
||||
Number(Number),
|
||||
Size(Number, Unit),
|
||||
String(Span),
|
||||
Bare,
|
||||
}
|
||||
@ -233,8 +237,8 @@ pub enum Literal {
|
||||
impl ToDebug for Tagged<&Literal> {
|
||||
fn fmt_debug(&self, f: &mut fmt::Formatter, source: &str) -> fmt::Result {
|
||||
match self.item() {
|
||||
Literal::Integer(int) => write!(f, "{}", *int),
|
||||
Literal::Size(int, unit) => write!(f, "{}{:?}", *int, unit),
|
||||
Literal::Number(number) => write!(f, "{:?}", *number),
|
||||
Literal::Size(number, unit) => write!(f, "{:?}{:?}", *number, unit),
|
||||
Literal::String(span) => write!(f, "{}", span.slice(source)),
|
||||
Literal::Bare => write!(f, "{}", self.span().slice(source)),
|
||||
}
|
||||
@ -244,7 +248,7 @@ impl ToDebug for Tagged<&Literal> {
|
||||
impl Literal {
|
||||
fn type_name(&self) -> &'static str {
|
||||
match self {
|
||||
Literal::Integer(_) => "integer",
|
||||
Literal::Number(..) => "number",
|
||||
Literal::Size(..) => "size",
|
||||
Literal::String(..) => "string",
|
||||
Literal::Bare => "string",
|
||||
|
@ -5,7 +5,7 @@ use std::path::PathBuf;
|
||||
|
||||
pub fn baseline_parse_single_token(token: &Token, source: &Text) -> hir::Expression {
|
||||
match *token.item() {
|
||||
RawToken::Integer(int) => hir::Expression::int(int, token.span()),
|
||||
RawToken::Number(number) => hir::Expression::number(number, token.span()),
|
||||
RawToken::Size(int, unit) => hir::Expression::size(int, unit, token.span()),
|
||||
RawToken::String(span) => hir::Expression::string(span, token.span()),
|
||||
RawToken::Variable(span) if span.slice(source) == "it" => {
|
||||
@ -24,8 +24,8 @@ pub fn baseline_parse_token_as_number(token: &Token, source: &Text) -> hir::Expr
|
||||
}
|
||||
RawToken::External(span) => hir::Expression::external_command(span, token.span()),
|
||||
RawToken::Variable(span) => hir::Expression::variable(span, token.span()),
|
||||
RawToken::Integer(int) => hir::Expression::int(int, token.span()),
|
||||
RawToken::Size(int, unit) => hir::Expression::size(int, unit, token.span()),
|
||||
RawToken::Number(number) => hir::Expression::number(number, token.span()),
|
||||
RawToken::Size(number, unit) => hir::Expression::size(number, unit, token.span()),
|
||||
RawToken::Bare => hir::Expression::bare(token.span()),
|
||||
RawToken::String(span) => hir::Expression::string(span, token.span()),
|
||||
}
|
||||
@ -38,7 +38,7 @@ pub fn baseline_parse_token_as_string(token: &Token, source: &Text) -> hir::Expr
|
||||
}
|
||||
RawToken::External(span) => hir::Expression::external_command(span, token.span()),
|
||||
RawToken::Variable(span) => hir::Expression::variable(span, token.span()),
|
||||
RawToken::Integer(_) => hir::Expression::bare(token.span()),
|
||||
RawToken::Number(_) => hir::Expression::bare(token.span()),
|
||||
RawToken::Size(_, _) => hir::Expression::bare(token.span()),
|
||||
RawToken::Bare => hir::Expression::bare(token.span()),
|
||||
RawToken::String(span) => hir::Expression::string(span, token.span()),
|
||||
@ -56,7 +56,7 @@ pub fn baseline_parse_token_as_path(
|
||||
}
|
||||
RawToken::External(span) => hir::Expression::external_command(span, token.span()),
|
||||
RawToken::Variable(span) => hir::Expression::variable(span, token.span()),
|
||||
RawToken::Integer(_) => hir::Expression::bare(token.span()),
|
||||
RawToken::Number(_) => hir::Expression::bare(token.span()),
|
||||
RawToken::Size(_, _) => hir::Expression::bare(token.span()),
|
||||
RawToken::Bare => hir::Expression::file_path(
|
||||
expand_path(token.span().slice(source), context),
|
||||
|
@ -294,7 +294,7 @@ pub fn baseline_parse_path(
|
||||
TokenNode::Token(token) => match token.item() {
|
||||
RawToken::Bare => token.span().slice(source),
|
||||
RawToken::String(span) => span.slice(source),
|
||||
RawToken::Integer(_)
|
||||
RawToken::Number(_)
|
||||
| RawToken::Size(..)
|
||||
| RawToken::Variable(_)
|
||||
| RawToken::External(_) => {
|
||||
|
@ -4,6 +4,7 @@ use crate::parser::parse::{
|
||||
call_node::*, flag::*, operator::*, pipeline::*, token_tree::*, token_tree_builder::*,
|
||||
tokens::*, unit::*,
|
||||
};
|
||||
use crate::prelude::*;
|
||||
use crate::{Span, Tagged};
|
||||
use nom;
|
||||
use nom::branch::*;
|
||||
@ -18,6 +19,7 @@ use nom::dbg;
|
||||
use nom::*;
|
||||
use nom::{AsBytes, FindSubstring, IResult, InputLength, InputTake, Slice};
|
||||
use nom5_locate::{position, LocatedSpan};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Debug;
|
||||
use std::str::FromStr;
|
||||
|
||||
@ -68,16 +70,94 @@ fn trace_step<'a, T: Debug>(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn raw_integer(input: NomSpan) -> IResult<NomSpan, Tagged<i64>> {
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
pub enum Number {
|
||||
Int(i64),
|
||||
Decimal(Decimal),
|
||||
}
|
||||
|
||||
impl std::ops::Mul for Number {
|
||||
type Output = Number;
|
||||
|
||||
fn mul(self, other: Number) -> Number {
|
||||
match (self, other) {
|
||||
(Number::Int(a), Number::Int(b)) => Number::Int(a * b),
|
||||
(Number::Int(a), Number::Decimal(b)) => Number::Decimal(Decimal::from(a) * b),
|
||||
(Number::Decimal(a), Number::Int(b)) => Number::Decimal(a * Decimal::from(b)),
|
||||
(Number::Decimal(a), Number::Decimal(b)) => Number::Decimal(a * b),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For literals
|
||||
impl std::ops::Mul<u32> for Number {
|
||||
type Output = Number;
|
||||
|
||||
fn mul(self, other: u32) -> Number {
|
||||
match self {
|
||||
Number::Int(left) => Number::Int(left * (other as i64)),
|
||||
Number::Decimal(left) => Number::Decimal(left * Decimal::from(other)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Number> for f32 {
|
||||
fn into(self) -> Number {
|
||||
Number::Decimal(Decimal::from_f32(self).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Number> for f64 {
|
||||
fn into(self) -> Number {
|
||||
Number::Decimal(Decimal::from_f64(self).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Number> for i64 {
|
||||
fn into(self) -> Number {
|
||||
Number::Int(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Number> for Decimal {
|
||||
fn into(self) -> Number {
|
||||
Number::Decimal(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn raw_number(input: NomSpan) -> IResult<NomSpan, Tagged<Number>> {
|
||||
let original = input;
|
||||
let start = input.offset;
|
||||
trace_step(input, "raw_integer", move |input| {
|
||||
trace_step(input, "raw_decimal", move |input| {
|
||||
let (input, neg) = opt(tag("-"))(input)?;
|
||||
let (input, num) = digit1(input)?;
|
||||
let (input, head) = digit1(input)?;
|
||||
let dot: IResult<NomSpan, NomSpan, (NomSpan, nom::error::ErrorKind)> = tag(".")(input);
|
||||
|
||||
let input = match dot {
|
||||
Ok((input, dot)) => input,
|
||||
|
||||
// it's just an integer
|
||||
Err(_) => {
|
||||
return Ok((
|
||||
input,
|
||||
Tagged::from_simple_spanned_item(
|
||||
Number::Int(int(head.fragment, neg)),
|
||||
(start, input.offset),
|
||||
),
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let (input, tail) = digit1(input)?;
|
||||
|
||||
let end = input.offset;
|
||||
|
||||
let decimal = Decimal::from_str(&format!("{}.{}", head.fragment, tail.fragment))
|
||||
.expect("BUG: Should have already ensured that the input is a valid decimal");
|
||||
|
||||
Ok((
|
||||
input,
|
||||
Tagged::from_simple_spanned_item(int(num.fragment, neg), (start, end)),
|
||||
Tagged::from_simple_spanned_item(Number::Decimal(decimal), (start, end)),
|
||||
))
|
||||
})
|
||||
}
|
||||
@ -245,7 +325,7 @@ pub fn size(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||
trace_step(input, "size", move |input| {
|
||||
let mut is_size = false;
|
||||
let start = input.offset;
|
||||
let (input, int) = raw_integer(input)?;
|
||||
let (input, number) = raw_number(input)?;
|
||||
if let Ok((input, Some(size))) = opt(raw_unit)(input) {
|
||||
let end = input.offset;
|
||||
|
||||
@ -256,7 +336,7 @@ pub fn size(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||
|
||||
Ok((
|
||||
input,
|
||||
TokenTreeBuilder::spanned_size((*int, *size), (start, end)),
|
||||
TokenTreeBuilder::spanned_size((number.item, *size), (start, end)),
|
||||
))
|
||||
} else {
|
||||
let end = input.offset;
|
||||
@ -266,7 +346,10 @@ pub fn size(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||
return Err(nom::Err::Error((input, nom::error::ErrorKind::Char)));
|
||||
}
|
||||
|
||||
Ok((input, TokenTreeBuilder::spanned_int((*int), (start, end))))
|
||||
Ok((
|
||||
input,
|
||||
TokenTreeBuilder::spanned_number(number.item, number.tag),
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -625,12 +708,12 @@ mod tests {
|
||||
fn test_integer() {
|
||||
assert_leaf! {
|
||||
parsers [ size ]
|
||||
"123" -> 0..3 { Integer(123) }
|
||||
"123" -> 0..3 { Number(Number::Int(123)) }
|
||||
}
|
||||
|
||||
assert_leaf! {
|
||||
parsers [ size ]
|
||||
"-123" -> 0..4 { Integer(-123) }
|
||||
"-123" -> 0..4 { Number(Number::Int(-123)) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -638,12 +721,12 @@ mod tests {
|
||||
fn test_size() {
|
||||
assert_leaf! {
|
||||
parsers [ size ]
|
||||
"123MB" -> 0..5 { Size(123, Unit::MB) }
|
||||
"123MB" -> 0..5 { Size(Number::Int(123), Unit::MB) }
|
||||
}
|
||||
|
||||
assert_leaf! {
|
||||
parsers [ size ]
|
||||
"10GB" -> 0..4 { Size(10, Unit::GB) }
|
||||
"10GB" -> 0..4 { Size(Number::Int(10), Unit::GB) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ use crate::prelude::*;
|
||||
|
||||
use crate::parser::parse::flag::{Flag, FlagKind};
|
||||
use crate::parser::parse::operator::Operator;
|
||||
use crate::parser::parse::parser::Number;
|
||||
use crate::parser::parse::pipeline::{Pipeline, PipelineElement};
|
||||
use crate::parser::parse::token_tree::{DelimitedNode, Delimiter, PathNode, TokenNode};
|
||||
use crate::parser::parse::tokens::{RawToken, Token};
|
||||
@ -170,9 +171,23 @@ impl TokenTreeBuilder {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn spanned_int(input: impl Into<i64>, span: impl Into<Span>) -> TokenNode {
|
||||
pub fn spanned_number(input: impl Into<Number>, span: impl Into<Span>) -> TokenNode {
|
||||
match input.into() {
|
||||
Number::Int(int) => TokenTreeBuilder::spanned_int(int, span),
|
||||
Number::Decimal(decimal) => TokenTreeBuilder::spanned_decimal(decimal, span),
|
||||
}
|
||||
}
|
||||
|
||||
fn spanned_int(input: i64, span: impl Into<Span>) -> TokenNode {
|
||||
TokenNode::Token(Token::from_simple_spanned_item(
|
||||
RawToken::Integer(input.into()),
|
||||
RawToken::Number(Number::Int(input)),
|
||||
span,
|
||||
))
|
||||
}
|
||||
|
||||
fn spanned_decimal(input: Decimal, span: impl Into<Span>) -> TokenNode {
|
||||
TokenNode::Token(Token::from_simple_spanned_item(
|
||||
RawToken::Number(Number::Decimal(input)),
|
||||
span,
|
||||
))
|
||||
}
|
||||
@ -191,7 +206,7 @@ impl TokenTreeBuilder {
|
||||
}
|
||||
|
||||
pub fn spanned_size(
|
||||
input: (impl Into<i64>, impl Into<Unit>),
|
||||
input: (impl Into<Number>, impl Into<Unit>),
|
||||
span: impl Into<Span>,
|
||||
) -> TokenNode {
|
||||
let (int, unit) = (input.0.into(), input.1.into());
|
||||
|
@ -1,11 +1,12 @@
|
||||
use crate::parser::parse::unit::*;
|
||||
use crate::prelude::*;
|
||||
use crate::{Span, Tagged, Text};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub enum RawToken {
|
||||
Integer(i64),
|
||||
Size(i64, Unit),
|
||||
Number(Number),
|
||||
Size(Number, Unit),
|
||||
String(Span),
|
||||
Variable(Span),
|
||||
External(Span),
|
||||
@ -15,7 +16,7 @@ pub enum RawToken {
|
||||
impl RawToken {
|
||||
pub fn type_name(&self) -> &'static str {
|
||||
match self {
|
||||
RawToken::Integer(_) => "Integer",
|
||||
RawToken::Number(_) => "Number",
|
||||
RawToken::Size(..) => "Size",
|
||||
RawToken::String(_) => "String",
|
||||
RawToken::Variable(_) => "Variable",
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::object::base::Value;
|
||||
use crate::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
@ -24,8 +25,8 @@ impl Unit {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn compute(&self, size: i64) -> Value {
|
||||
Value::int(match self {
|
||||
pub(crate) fn compute(&self, size: Number) -> Value {
|
||||
Value::number(match self {
|
||||
Unit::B => size,
|
||||
Unit::KB => size * 1024,
|
||||
Unit::MB => size * 1024 * 1024,
|
||||
|
@ -2,12 +2,12 @@ use std::ffi::OsStr;
|
||||
|
||||
use futures::executor::block_on;
|
||||
use futures::stream::StreamExt;
|
||||
use heim::units::{frequency, information, thermodynamic_temperature, time};
|
||||
use heim::{disk, host, memory, net, sensors};
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
||||
Tag, Tagged, TaggedDictBuilder, Value,
|
||||
};
|
||||
use heim::{disk, memory, net, sensors, host};
|
||||
use heim::units::{frequency, information, time, thermodynamic_temperature};
|
||||
|
||||
struct Sys;
|
||||
impl Sys {
|
||||
@ -17,30 +17,33 @@ impl Sys {
|
||||
}
|
||||
|
||||
async fn cpu(tag: Tag) -> Option<Tagged<Value>> {
|
||||
match futures::future::try_join(
|
||||
heim::cpu::logical_count(),
|
||||
heim::cpu::frequency(),
|
||||
).await {
|
||||
match futures::future::try_join(heim::cpu::logical_count(), heim::cpu::frequency()).await {
|
||||
Ok((num_cpu, cpu_speed)) => {
|
||||
let mut cpu_idx = TaggedDictBuilder::with_capacity(tag, 4);
|
||||
cpu_idx.insert("cores", Primitive::Int(num_cpu as i64));
|
||||
|
||||
let current_speed =
|
||||
(cpu_speed.current().get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round() / 100.0;
|
||||
cpu_idx.insert("current ghz", Primitive::Float(current_speed.into()));
|
||||
(cpu_speed.current().get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0)
|
||||
.round()
|
||||
/ 100.0;
|
||||
cpu_idx.insert("current ghz", Primitive::number(current_speed));
|
||||
|
||||
if let Some(min_speed) = cpu_speed.min() {
|
||||
let min_speed = (min_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round() / 100.0;
|
||||
cpu_idx.insert("min ghz", Primitive::Float(min_speed.into()));
|
||||
let min_speed =
|
||||
(min_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round()
|
||||
/ 100.0;
|
||||
cpu_idx.insert("min ghz", Primitive::number(min_speed));
|
||||
}
|
||||
|
||||
if let Some(max_speed) = cpu_speed.max() {
|
||||
let max_speed = (max_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round() / 100.0;
|
||||
cpu_idx.insert("max ghz", Primitive::Float(max_speed.into()));
|
||||
let max_speed =
|
||||
(max_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round()
|
||||
/ 100.0;
|
||||
cpu_idx.insert("max ghz", Primitive::number(max_speed));
|
||||
}
|
||||
|
||||
Some(cpu_idx.into_tagged_value())
|
||||
},
|
||||
}
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
@ -48,19 +51,29 @@ async fn cpu(tag: Tag) -> Option<Tagged<Value>> {
|
||||
async fn mem(tag: Tag) -> Tagged<Value> {
|
||||
let mut dict = TaggedDictBuilder::with_capacity(tag, 4);
|
||||
|
||||
let (memory_result, swap_result) = futures::future::join(
|
||||
memory::memory(),
|
||||
memory::swap()
|
||||
).await;
|
||||
let (memory_result, swap_result) =
|
||||
futures::future::join(memory::memory(), memory::swap()).await;
|
||||
|
||||
if let Ok(memory) = memory_result {
|
||||
dict.insert("total", Value::bytes(memory.total().get::<information::byte>()));
|
||||
dict.insert("free", Value::bytes(memory.free().get::<information::byte>()));
|
||||
dict.insert(
|
||||
"total",
|
||||
Value::bytes(memory.total().get::<information::byte>()),
|
||||
);
|
||||
dict.insert(
|
||||
"free",
|
||||
Value::bytes(memory.free().get::<information::byte>()),
|
||||
);
|
||||
}
|
||||
|
||||
if let Ok(swap) = swap_result {
|
||||
dict.insert("swap total", Value::bytes(swap.total().get::<information::byte>()));
|
||||
dict.insert("swap free", Value::bytes(swap.free().get::<information::byte>()));
|
||||
dict.insert(
|
||||
"swap total",
|
||||
Value::bytes(swap.total().get::<information::byte>()),
|
||||
);
|
||||
dict.insert(
|
||||
"swap free",
|
||||
Value::bytes(swap.free().get::<information::byte>()),
|
||||
);
|
||||
}
|
||||
|
||||
dict.into_tagged_value()
|
||||
@ -69,10 +82,8 @@ async fn mem(tag: Tag) -> Tagged<Value> {
|
||||
async fn host(tag: Tag) -> Tagged<Value> {
|
||||
let mut dict = TaggedDictBuilder::with_capacity(tag, 6);
|
||||
|
||||
let (platform_result, uptime_result) = futures::future::join(
|
||||
host::platform(),
|
||||
host::uptime(),
|
||||
).await;
|
||||
let (platform_result, uptime_result) =
|
||||
futures::future::join(host::platform(), host::uptime()).await;
|
||||
|
||||
// OS
|
||||
if let Ok(platform) = platform_result {
|
||||
@ -133,9 +144,18 @@ async fn disks(tag: Tag) -> Option<Value> {
|
||||
dict.insert("mount", Value::string(part.mount_point().to_string_lossy()));
|
||||
|
||||
if let Ok(usage) = disk::usage(part.mount_point().to_path_buf()).await {
|
||||
dict.insert("total", Value::bytes(usage.total().get::<information::byte>()));
|
||||
dict.insert("used", Value::bytes(usage.used().get::<information::byte>()));
|
||||
dict.insert("free", Value::bytes(usage.free().get::<information::byte>()));
|
||||
dict.insert(
|
||||
"total",
|
||||
Value::bytes(usage.total().get::<information::byte>()),
|
||||
);
|
||||
dict.insert(
|
||||
"used",
|
||||
Value::bytes(usage.used().get::<information::byte>()),
|
||||
);
|
||||
dict.insert(
|
||||
"free",
|
||||
Value::bytes(usage.free().get::<information::byte>()),
|
||||
);
|
||||
}
|
||||
|
||||
output.push(dict.into_tagged_value());
|
||||
@ -169,13 +189,13 @@ async fn battery(tag: Tag) -> Option<Value> {
|
||||
if let Some(time_to_full) = battery.time_to_full() {
|
||||
dict.insert(
|
||||
"mins to full",
|
||||
Value::float(time_to_full.get::<battery::units::time::minute>() as f64),
|
||||
Value::number(time_to_full.get::<battery::units::time::minute>()),
|
||||
);
|
||||
}
|
||||
if let Some(time_to_empty) = battery.time_to_empty() {
|
||||
dict.insert(
|
||||
"mins to empty",
|
||||
Value::float(time_to_empty.get::<battery::units::time::minute>() as f64),
|
||||
Value::number(time_to_empty.get::<battery::units::time::minute>()),
|
||||
);
|
||||
}
|
||||
output.push(dict.into_tagged_value());
|
||||
@ -202,12 +222,25 @@ async fn temp(tag: Tag) -> Option<Value> {
|
||||
if let Some(label) = sensor.label() {
|
||||
dict.insert("label", Value::string(label));
|
||||
}
|
||||
dict.insert("temp", Value::float(sensor.current().get::<thermodynamic_temperature::degree_celsius>() as f64));
|
||||
dict.insert(
|
||||
"temp",
|
||||
Value::number(
|
||||
sensor
|
||||
.current()
|
||||
.get::<thermodynamic_temperature::degree_celsius>(),
|
||||
),
|
||||
);
|
||||
if let Some(high) = sensor.high() {
|
||||
dict.insert("high", Value::float(high.get::<thermodynamic_temperature::degree_celsius>() as f64));
|
||||
dict.insert(
|
||||
"high",
|
||||
Value::number(high.get::<thermodynamic_temperature::degree_celsius>()),
|
||||
);
|
||||
}
|
||||
if let Some(critical) = sensor.critical() {
|
||||
dict.insert("critical", Value::float(critical.get::<thermodynamic_temperature::degree_celsius>() as f64));
|
||||
dict.insert(
|
||||
"critical",
|
||||
Value::number(critical.get::<thermodynamic_temperature::degree_celsius>()),
|
||||
);
|
||||
}
|
||||
|
||||
output.push(dict.into_tagged_value());
|
||||
@ -228,8 +261,14 @@ async fn net(tag: Tag) -> Option<Value> {
|
||||
if let Ok(nic) = nic {
|
||||
let mut network_idx = TaggedDictBuilder::with_capacity(tag, 3);
|
||||
network_idx.insert("name", Value::string(nic.interface()));
|
||||
network_idx.insert("sent", Value::bytes(nic.bytes_sent().get::<information::byte>()));
|
||||
network_idx.insert("recv", Value::bytes(nic.bytes_recv().get::<information::byte>()));
|
||||
network_idx.insert(
|
||||
"sent",
|
||||
Value::bytes(nic.bytes_sent().get::<information::byte>()),
|
||||
);
|
||||
network_idx.insert(
|
||||
"recv",
|
||||
Value::bytes(nic.bytes_recv().get::<information::byte>()),
|
||||
);
|
||||
output.push(network_idx.into_tagged_value());
|
||||
}
|
||||
}
|
||||
@ -243,17 +282,9 @@ async fn net(tag: Tag) -> Option<Value> {
|
||||
async fn sysinfo(tag: Tag) -> Vec<Tagged<Value>> {
|
||||
let mut sysinfo = TaggedDictBuilder::with_capacity(tag, 7);
|
||||
|
||||
let (host, cpu, disks, memory, temp) = futures::future::join5(
|
||||
host(tag),
|
||||
cpu(tag),
|
||||
disks(tag),
|
||||
mem(tag),
|
||||
temp(tag),
|
||||
).await;
|
||||
let (net, battery) = futures::future::join(
|
||||
net(tag),
|
||||
battery(tag),
|
||||
).await;
|
||||
let (host, cpu, disks, memory, temp) =
|
||||
futures::future::join5(host(tag), cpu(tag), disks(tag), mem(tag), temp(tag)).await;
|
||||
let (net, battery) = futures::future::join(net(tag), battery(tag)).await;
|
||||
|
||||
sysinfo.insert_tagged("host", host);
|
||||
if let Some(cpu) = cpu {
|
||||
|
@ -63,6 +63,7 @@ pub(crate) use crate::object::meta::{Tag, Tagged, TaggedItem};
|
||||
pub(crate) use crate::object::types::ExtractType;
|
||||
pub(crate) use crate::object::{Primitive, Value};
|
||||
pub(crate) use crate::parser::hir::SyntaxType;
|
||||
pub(crate) use crate::parser::parse::parser::Number;
|
||||
pub(crate) use crate::parser::registry::Signature;
|
||||
pub(crate) use crate::shell::filesystem_shell::FilesystemShell;
|
||||
pub(crate) use crate::shell::shell_manager::ShellManager;
|
||||
@ -74,6 +75,8 @@ pub(crate) use crate::Text;
|
||||
pub(crate) use futures::stream::BoxStream;
|
||||
pub(crate) use futures::{FutureExt, Stream, StreamExt};
|
||||
pub(crate) use futures_async_stream::async_stream_block;
|
||||
pub(crate) use num_traits::cast::{FromPrimitive, ToPrimitive};
|
||||
pub(crate) use rust_decimal::Decimal;
|
||||
#[allow(unused)]
|
||||
pub(crate) use serde::{Deserialize, Serialize};
|
||||
pub(crate) use std::collections::VecDeque;
|
||||
|
@ -116,7 +116,7 @@ fn paint_token_node(token_node: &TokenNode, line: &str) -> String {
|
||||
TokenNode::Operator(..) => Color::White.normal().paint(token_node.span().slice(line)),
|
||||
TokenNode::Pipeline(..) => Color::Blue.normal().paint(token_node.span().slice(line)),
|
||||
TokenNode::Token(Tagged {
|
||||
item: RawToken::Integer(..),
|
||||
item: RawToken::Number(..),
|
||||
..
|
||||
}) => Color::Purple.bold().paint(token_node.span().slice(line)),
|
||||
TokenNode::Token(Tagged {
|
||||
|
Loading…
Reference in New Issue
Block a user