diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b8ad175..65aa71a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ All notable changes to eww will be listed here, starting at changes since versio - Add trigonometric functions (`sin`, `cos`, `tan`, `cot`) and degree/radian conversions (`degtorad`, `radtodeg`) (By: end-4) - Add `substring` function to simplexpr - Add `--duration` flag to `eww open` +- Add `roundsize` function to simplexpr ## [0.4.0] (04.09.2022) diff --git a/Cargo.lock b/Cargo.lock index e3e9ca9c..fa39d835 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1632,6 +1632,12 @@ dependencies = [ "libc", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "object" version = "0.31.1" @@ -2181,6 +2187,7 @@ dependencies = [ "jaq-std", "lalrpop", "lalrpop-util", + "number_prefix", "once_cell", "regex", "serde", diff --git a/crates/simplexpr/Cargo.toml b/crates/simplexpr/Cargo.toml index 5b8ea399..c66ce31d 100644 --- a/crates/simplexpr/Cargo.toml +++ b/crates/simplexpr/Cargo.toml @@ -31,6 +31,7 @@ chrono-tz = "0.8.2" strum = { version = "0.24", features = ["derive"] } eww_shared_util = { version = "0.1.0", path = "../eww_shared_util" } +number_prefix = "0.4.0" [build-dependencies] diff --git a/crates/simplexpr/src/eval.rs b/crates/simplexpr/src/eval.rs index a77b703e..470333b9 100644 --- a/crates/simplexpr/src/eval.rs +++ b/crates/simplexpr/src/eval.rs @@ -1,12 +1,14 @@ use cached::proc_macro::cached; use chrono::{Local, LocalResult, TimeZone}; use itertools::Itertools; +use number_prefix::NumberPrefix; use crate::{ ast::{AccessType, BinOp, SimplExpr, UnaryOp}, dynval::{ConversionError, DynVal}, }; use eww_shared_util::{Span, Spanned, VarName}; +use serde_json::json; use std::{ collections::HashMap, convert::{TryFrom, TryInto}, @@ -320,6 +322,33 @@ fn call_expr_function(name: &str, args: Vec) -> Result Err(EvalError::WrongArgCount(name.to_string())), }, + "roundsize" => match args.as_slice() { + [size] => { + let size = size.as_f64()?; + Ok(match NumberPrefix::binary(size) { + NumberPrefix::Standalone(bytes) => DynVal::from(json!({"size": bytes, "units": "B"}).to_string()), + NumberPrefix::Prefixed(prefix, n) => { + DynVal::from(json!({"size": n, "units": format!("{}B", prefix)}).to_string()) + } + }) + } + [size, format_type] => { + let format_type = format_type.as_string()?; + let func = match format_type.as_str() { + "decimal" => NumberPrefix::decimal, + "binary" => NumberPrefix::binary, + _ => return Err(EvalError::NoVariablesAllowed(format_type.parse().unwrap())), + }; + let size = size.as_f64()?; + Ok(match func(size) { + NumberPrefix::Standalone(bytes) => DynVal::from(json!({"size": bytes, "units": "B"}).to_string()), + NumberPrefix::Prefixed(prefix, n) => { + DynVal::from(json!({"size": n, "units": format!("{}B", prefix)}).to_string()) + } + }) + } + _ => Err(EvalError::WrongArgCount(name.to_string())), + }, "sin" => match args.as_slice() { [num] => { let num = num.as_f64()?; diff --git a/docs/src/expression_language.md b/docs/src/expression_language.md index 574e8e56..c620ac17 100644 --- a/docs/src/expression_language.md +++ b/docs/src/expression_language.md @@ -59,3 +59,5 @@ Supported currently are the following features: Same as other `formattime`, but does not accept timezone. Instead, it uses system's local timezone. Check [chrono's documentation](https://docs.rs/chrono/latest/chrono/format/strftime/index.html) for more information about format string. + - `roundsize(bytes)`: Round a number of bytes to human-readable on binary base (KiB, MiB, GiB). Returned value format `{ size, units }` + - `roundsize(bytes, format_type)`: Round a number of bytes to human-readable with specific format type it's can be `binary (KiB, MiB, GiB...)` or `decimal (KB, MB, GB...)`. Returned value format `{ size, units }`