diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eb4084..072640e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ All notable changes to eww will be listed here, starting at changes since versio - Add `:lines` and `:wrap-mode` properties to label widget (By: vaporii) - Add `value-pos` to scale widget (By: ipsvn) - Add `floor` and `ceil` function calls to simplexpr (By: wsbankenstein) +- Add `formatbytes` function calls to simplexpr (By: topongo) ## [0.6.0] (21.04.2024) diff --git a/Cargo.lock b/Cargo.lock index 158aff4..f479f98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -400,6 +400,12 @@ version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +[[package]] +name = "bytesize" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3c8f83209414aacf0eeae3cf730b18d6981697fba62f200fcfb92b9f082acba" + [[package]] name = "cached" version = "0.53.1" @@ -2683,6 +2689,7 @@ dependencies = [ name = "simplexpr" version = "0.1.0" dependencies = [ + "bytesize", "cached", "chrono", "chrono-tz", diff --git a/Cargo.toml b/Cargo.toml index 398a4c7..08f50fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ notifier_host = { version = "0.1.0", path = "crates/notifier_host" } anyhow = "1.0.86" bincode = "1.3.3" +bytesize = "2.0.1" cached = "0.53.1" chrono = "0.4.38" chrono-tz = "0.10.0" diff --git a/crates/simplexpr/Cargo.toml b/crates/simplexpr/Cargo.toml index 2b94ae9..dc5d7fd 100644 --- a/crates/simplexpr/Cargo.toml +++ b/crates/simplexpr/Cargo.toml @@ -14,6 +14,7 @@ build = "build.rs" [dependencies] eww_shared_util.workspace = true +bytesize.workspace = true cached.workspace = true chrono-tz.workspace = true chrono = { workspace = true, features = ["unstable-locales"] } diff --git a/crates/simplexpr/src/eval.rs b/crates/simplexpr/src/eval.rs index 556c72a..4c137a0 100644 --- a/crates/simplexpr/src/eval.rs +++ b/crates/simplexpr/src/eval.rs @@ -1,3 +1,4 @@ +use bytesize::ByteSize; use cached::proc_macro::cached; use chrono::{Local, LocalResult, TimeZone}; use itertools::Itertools; @@ -61,6 +62,9 @@ pub enum EvalError { #[error("Error parsing date: {0}")] ChronoError(String), + #[error("Error parsing byte format mode: {0}")] + ByteFormatModeError(String), + #[error("{1}")] Spanned(Span, Box), } @@ -534,6 +538,34 @@ fn call_expr_function(name: &str, args: Vec) -> Result Err(EvalError::WrongArgCount(name.to_string())), }, + "formatbytes" => { + let (bytes, short, mode) = match args.as_slice() { + [bytes] => (bytes.as_i64()?, false, "iec".to_owned()), + [bytes, short] => (bytes.as_i64()?, short.as_bool()?, "iec".to_owned()), + [bytes, short, mode] => (bytes.as_i64()?, short.as_bool()?, mode.as_string()?), + _ => return Err(EvalError::WrongArgCount(name.to_string())), + }; + let neg = bytes < 0; + let disp = ByteSize(bytes.abs() as u64).display(); + let disp = match mode.as_str() { + "iec" => { + if short { + disp.iec_short() + } else { + disp.iec() + } + } + "si" => { + if short { + disp.si_short() + } else { + disp.si() + } + } + _ => return Err(EvalError::ByteFormatModeError(mode)), + }; + Ok(DynVal::from(if neg { format!("-{disp}") } else { disp.to_string() })) + } _ => Err(EvalError::UnknownFunction(name.to_string())), } diff --git a/docs/src/expression_language.md b/docs/src/expression_language.md index 480b2d5..867b641 100644 --- a/docs/src/expression_language.md +++ b/docs/src/expression_language.md @@ -70,3 +70,8 @@ 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. + - `formatbytes(bytes, short, format_mode)`: Display bytes in a human-readable format. + Arguments: + - `bytes`: `i64` of bytes, supports negative sizes. + - `short`: set true for a compact version (default: false) + - `format_mode`: set to either to "iec" (eg. `1.0 GiB`) or "si" (eg. `1.2 GB`) (default: "iec")