diff --git a/src/config.rs b/src/config.rs index 7373a2d..3871dec 100644 --- a/src/config.rs +++ b/src/config.rs @@ -73,6 +73,8 @@ pub struct BatteryConfig { #[serde(deserialize_with = "deserialize_duration")] #[default(_code = "Duration::from_secs(30)")] pub update: Duration, + #[default(true)] + pub use_symbols: bool, } #[derive(SmartDefault, Deserialize, Clone, Debug)] diff --git a/src/formatting.rs b/src/formatting.rs new file mode 100644 index 0000000..5ccf7aa --- /dev/null +++ b/src/formatting.rs @@ -0,0 +1,36 @@ +static BATTERY_DISCHARGING_SYMBOLS: &[char] = &[ + '\u{f008e}', // nf-md-battery_outline (󰂎) + '\u{f007a}', // nf-md-battery_10 (󰁺) + '\u{f007b}', // nf-md-battery_20 (󰁻) + '\u{f007c}', // nf-md-battery_30 (󰁼) + '\u{f007d}', // nf-md-battery_40 (󰁽) + '\u{f007e}', // nf-md-battery_50 (󰁾) + '\u{f007f}', // nf-md-battery_60 (󰁿) + '\u{f0080}', // nf-md-battery_70 (󰂀) + '\u{f0081}', // nf-md-battery_80 (󰂁) + '\u{f0082}', // nf-md-battery_90 (󰂂) + '\u{f0079}', // nf-md-battery (󰁹) +]; + +static BATTERY_CHARGING_SYMBOLS: &[char] = &[ + '\u{f089f}', // nf-md-battery_charging_outline (󰢟) + '\u{f089c}', // nf-md-battery_charging_10 (󰢜) + '\u{f0086}', // nf-md-battery_charging_20 (󰂆) + '\u{f0087}', // nf-md-battery_charging_30 (󰂇) + '\u{f0088}', // nf-md-battery_charging_40 (󰂈) + '\u{f089d}', // nf-md-battery_charging_50 (󰢝) + '\u{f0089}', // nf-md-battery_charging_60 (󰂉) + '\u{f089e}', // nf-md-battery_charging_70 (󰢞) + '\u{f008a}', // nf-md-battery_charging_80 (󰂊) + '\u{f008b}', // nf-md-battery_charging_90 (󰂋) + '\u{f0085}', // nf-md-battery_charging_100 (󰂅) +]; + +pub fn charging_symbol(percentage: f64, charging: bool) -> char { + let index = (percentage.clamp(0.0, 100.0) / 10.0).round() as usize; + if charging { + BATTERY_CHARGING_SYMBOLS[index] + } else { + BATTERY_DISCHARGING_SYMBOLS[index] + } +} diff --git a/src/main.rs b/src/main.rs index 820d42b..2c750d4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ mod config; +mod formatting; mod generated; mod output; mod tile; diff --git a/src/tiles/battery.rs b/src/tiles/battery.rs index e55f293..8fd2cc9 100644 --- a/src/tiles/battery.rs +++ b/src/tiles/battery.rs @@ -1,9 +1,11 @@ use crate::config::BatteryConfig; +use crate::formatting::charging_symbol; use crate::output::OutputChannel; use crate::tile::Block; use std::convert::Infallible; use std::path::Path; +use std::str::FromStr; use tokio::fs::try_exists; use tokio::try_join; @@ -22,21 +24,34 @@ pub async fn battery(config: BatteryConfig, output: OutputChannel) -> eyre::Resu loop { interval.tick().await; - async fn read_file_to_string(path: &Path) -> eyre::Result { + async fn read_and_parse(path: &Path) -> eyre::Result + where + ::Err: Send + Sync + std::error::Error + 'static, + { Ok(tokio::fs::read_to_string(path).await?.trim_end().parse()?) } - let charge_now = read_file_to_string(&now_path); - let charge_total = read_file_to_string(&full_path); - let status = read_file_to_string(&status_path); + let charge_now = read_and_parse::(&now_path); + let charge_total = read_and_parse::(&full_path); + let status = read_and_parse::(&status_path); let (charge_now, charge_total, status) = try_join!(charge_now, charge_total, status)?; - let percentage = charge_now * 100 / charge_total; - output - .send(Block { - full_text: format!("{}% {}", percentage, status).into(), - short_text: format!("{}%", percentage).into_boxed_str().into(), + + let percentage = charge_now * 100.0 / charge_total; + let is_charging = status != "Discharging"; + let block = if config.use_symbols { + let symbol = charging_symbol(percentage, is_charging); + Block { + full_text: format!("{} {:.0}%", symbol, percentage).into(), + short_text: symbol.to_string().into_boxed_str().into(), ..Default::default() - }) - .await?; + } + } else { + Block { + full_text: format!("{:.0}% {}", percentage, status).into(), + short_text: format!("{:.0}%", percentage).into_boxed_str().into(), + ..Default::default() + } + }; + output.send(block).await?; } }