From 5fab9bc98ba1a7c6765ccceb66d2cdf05370f58f Mon Sep 17 00:00:00 2001 From: Skye Date: Thu, 14 Dec 2023 23:01:39 -0500 Subject: [PATCH] Lots of misc code changes --- src/config.rs | 63 +++++++++++++++++++----------------- src/output.rs | 7 ++-- src/tile.rs | 2 +- src/tiles/battery.rs | 43 +++++++----------------- src/tiles/hostname.rs | 5 +-- src/tiles/internet_time.rs | 12 ++++--- src/tiles/iwd.rs | 7 ++-- src/tiles/load.rs | 16 ++++----- src/tiles/local_time.rs | 17 ++++++---- src/tiles/memory.rs | 17 +++++----- src/tiles/network_manager.rs | 19 ++++++----- src/tiles/system_time.rs | 9 ++++-- src/tiles/utc_time.rs | 6 ++-- 13 files changed, 112 insertions(+), 111 deletions(-) diff --git a/src/config.rs b/src/config.rs index eeade2c..61360c2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,18 +4,17 @@ use crate::tiles; use dbus::nonblock::SyncConnection; use log::error; -use log::warn; use serde::{Deserialize, Deserializer}; use smart_default::SmartDefault; -use std::env::var; +use std::env::var; +use std::iter::FromIterator as _; use std::path::Path; use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; use structopt::StructOpt; -use tokio::fs::File; -use tokio::io::AsyncReadExt; + use tokio::sync::mpsc; use tokio::task::JoinHandle; @@ -97,16 +96,24 @@ pub struct HostnameConfig { pub update: Duration, } +type StaticStr = &'static str; + #[derive(SmartDefault, Deserialize, Clone, Debug)] #[serde(default)] pub struct IwdConfig { #[default("wlan0")] - pub interface: Box, + #[serde(deserialize_with = "leak_str")] + // Gotta obfuscate the static lifetime or derive(Deserialize) misbehaves + pub interface: StaticStr, #[serde(deserialize_with = "deserialize_duration")] #[default(_code = "Duration::from_secs(5)")] pub update: Duration, } +fn leak_str<'de, D: Deserializer<'de>>(deserializer: D) -> Result<&'static str, D::Error> { + Ok(Box::leak(Box::::deserialize(deserializer)?)) +} + #[derive(SmartDefault, Deserialize, Clone, Debug)] #[serde(default)] pub struct UtcTimeConfig { @@ -173,31 +180,29 @@ struct Args { pub async fn read_config() -> eyre::Result { let args = Args::from_args(); - let config_path = match args.config { - Some(config) => config, - None => { - if let Ok(rustybar_config_env) = var("RUSTYBAR_CONFIG") { - rustybar_config_env.into() - } else if let Ok(xdg_config_home) = var("XDG_CONFIG_HOME") { - [&xdg_config_home, "rustybar", "config.toml"] - .iter() - .collect() - } else if let Ok(home) = var("HOME") { - [&home, ".config", "rustybar", "config.toml"] - .iter() - .collect() - } else { - eyre::bail!("Could not find RUSTYBAR_CONFIG, XDG_CONFIG_HOME, or HOME environment variables"); - } - } + let Some(config_path) = args.config.clone().or_else(|| { + Some(if let Ok(rusty_conf) = var("RUSTYBAR_CONFIG") { + rusty_conf.into() + } else if let Ok(config) = var("XDG_CONFIG_HOME") { + PathBuf::from_iter([&config, "rustybar/config.toml"]) + } else if let Ok(home) = var("HOME") { + PathBuf::from_iter([&home, ".config/rustybar/config.toml"]) + } else { + return None; + }) + }) else { + eyre::bail!( + "Could not find RUSTYBAR_CONFIG, XDG_CONFIG_HOME, or HOME environment variables" + ) }; - let mut config_contents = vec![]; - File::open(config_path) - .await? - .read_to_end(&mut config_contents) - .await?; - Ok(toml::from_str(std::str::from_utf8(&config_contents)?)?) + let string = tokio::fs::read_to_string(config_path) + .await + .or_else(|e| match e.kind() { + std::io::ErrorKind::NotFound => Ok(include_str!("../config.toml.example").to_owned()), + _ => Err(e), + })?; + Ok(toml::from_str(&string)?) } pub fn launch_tile( @@ -223,7 +228,7 @@ pub fn launch_tile( } }; match result { - Ok(_) => warn!("Tile {} exited without error", tile_id), + Ok(t) => match t {}, Err(e) => error!("Tile {} exited with error: {:?}", tile_id, e), } }) diff --git a/src/output.rs b/src/output.rs index a8d5ab9..cd45d28 100644 --- a/src/output.rs +++ b/src/output.rs @@ -45,12 +45,11 @@ pub async fn run(num_tiles: usize, mut receiver: mpsc::Receiver) -> ey .await .ok_or_eyre("No more messages to recieve")?; - if message.sender_id < num_tiles { - blocks[message.sender_id] = Some(message.block); - } else { + let Some(block) = blocks.get_mut(message.sender_id) else { eprintln!("Invalid message with sender id {}", message.sender_id); continue; - } + }; + *block = Some(message.block); let mut serialized = serde_json::to_vec(&blocks).unwrap(); serialized.extend_from_slice(b",\n"); stdout.write_all(&serialized).await?; diff --git a/src/tile.rs b/src/tile.rs index 2f0a23e..d01be35 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -74,7 +74,7 @@ pub struct Block { pub min_width: Option, #[serde(skip_serializing_if = "Option::is_none")] pub align: Option, - pub name: Box, + pub name: &'static str, #[serde(serialize_with = "arc_default")] #[default = ""] pub instance: Arc, diff --git a/src/tiles/battery.rs b/src/tiles/battery.rs index ea9c1ed..89ae447 100644 --- a/src/tiles/battery.rs +++ b/src/tiles/battery.rs @@ -2,12 +2,12 @@ use crate::config::BatteryConfig; use crate::output::OutputChannel; use crate::tile::Block; +use std::convert::Infallible; use std::path::Path; -use tokio::fs::{try_exists, File}; -use tokio::io::AsyncReadExt; +use tokio::fs::try_exists; use tokio::try_join; -pub async fn battery(config: BatteryConfig, output: OutputChannel) -> eyre::Result<()> { +pub async fn battery(config: BatteryConfig, output: OutputChannel) -> eyre::Result { let base_dir = Path::new("/sys/class/power_supply").join(&*config.battery); let file_prefix = if try_exists(base_dir.join("energy_now")).await? { "energy_" @@ -16,45 +16,26 @@ pub async fn battery(config: BatteryConfig, output: OutputChannel) -> eyre::Resu }; let now_path = base_dir.join(file_prefix.to_owned() + "now"); let full_path = base_dir.join(file_prefix.to_owned() + "full"); + let status_path = base_dir.join("status"); let mut interval = tokio::time::interval(config.update); loop { interval.tick().await; - let charge_now = async { - let mut raw = String::new(); - File::open(&now_path) - .await? - .read_to_string(&mut raw) - .await?; - let charge: u32 = raw.trim_end().parse()?; - eyre::Result::<_>::Ok(charge) - }; - let charge_total = async { - let mut raw = String::new(); - File::open(&full_path) - .await? - .read_to_string(&mut raw) - .await?; - let charge: u32 = raw.trim_end().parse()?; - eyre::Result::<_>::Ok(charge) - }; - let status = async { - let mut raw = String::new(); - File::open(base_dir.join("status")) - .await? - .read_to_string(&mut raw) - .await?; - raw.truncate(raw.trim_end().len()); - eyre::Result::<_>::Ok(raw) - }; + async fn read_file_to_string(path: &Path) -> eyre::Result { + 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, 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(), - name: "battery".into(), + name: "battery", ..Default::default() }) .await?; diff --git a/src/tiles/hostname.rs b/src/tiles/hostname.rs index 592bb5a..ea2e64a 100644 --- a/src/tiles/hostname.rs +++ b/src/tiles/hostname.rs @@ -3,6 +3,7 @@ use crate::generated::OrgFreedesktopHostname1; use crate::output::OutputChannel; use crate::tile::Block; use dbus::nonblock::{Proxy, SyncConnection}; +use std::convert::Infallible; use std::sync::Arc; use std::time::Duration; @@ -10,7 +11,7 @@ pub async fn hostname( config: HostnameConfig, output: OutputChannel, dbus_conn: Arc, -) -> eyre::Result<()> { +) -> eyre::Result { let proxy = Proxy::new( "org.freedesktop.hostname1", "/org/freedesktop/hostname1", @@ -26,7 +27,7 @@ pub async fn hostname( output .send(Block { full_text: hostname.into(), - name: "hostname".into(), + name: "hostname", ..Default::default() }) .await?; diff --git a/src/tiles/internet_time.rs b/src/tiles/internet_time.rs index 3ac36e7..a874ab0 100644 --- a/src/tiles/internet_time.rs +++ b/src/tiles/internet_time.rs @@ -1,10 +1,15 @@ +use std::convert::Infallible; + use crate::config::InternetTimeConfig; use crate::output::OutputChannel; use crate::tile::Block; use chrono::prelude::*; use tokio::time::sleep; -pub async fn internet_time(config: InternetTimeConfig, output: OutputChannel) -> eyre::Result<()> { +pub async fn internet_time( + config: InternetTimeConfig, + output: OutputChannel, +) -> eyre::Result { // "BMT" is actually just UTC+1 let offset = FixedOffset::east_opt(60 * 60).unwrap(); let factor = 10f64.powi(config.precision.into()); @@ -18,15 +23,14 @@ pub async fn internet_time(config: InternetTimeConfig, output: OutputChannel) -> output .send(Block { full_text: format!( - "@{time:0width$.prec$}", - time = internet_time, + "@{internet_time:0width$.prec$}", // 3 digits + and decimal point width = config.precision as usize + 4, prec = config.precision as usize ) .into_boxed_str(), short_text: Some(format!("@{:03.0}", internet_time).into_boxed_str()), - name: "internet_time".into(), + name: "internet_time", ..Default::default() }) .await?; diff --git a/src/tiles/iwd.rs b/src/tiles/iwd.rs index d8727b3..de9253d 100644 --- a/src/tiles/iwd.rs +++ b/src/tiles/iwd.rs @@ -7,6 +7,7 @@ use dbus::nonblock::{Proxy, SyncConnection}; use dbus::Path; use eyre::OptionExt; use std::collections::HashMap; +use std::convert::Infallible; use std::sync::Arc; use std::time::Duration; @@ -32,7 +33,7 @@ pub async fn iwd( config: IwdConfig, output: OutputChannel, dbus_conn: Arc, -) -> eyre::Result<()> { +) -> eyre::Result { let root_proxy = Proxy::new("net.connman.iwd", "/", Duration::from_secs(5), dbus_conn); let mut interval = tokio::time::interval(config.update); @@ -40,7 +41,7 @@ pub async fn iwd( interval.tick().await; let managed_objects = root_proxy.get_managed_objects().await?; - let interface_path = get_interface_path(&managed_objects, &config.interface) + let interface_path = get_interface_path(&managed_objects, config.interface) .ok_or_eyre("Couldn't find interface")?; let station_path = managed_objects .get(&interface_path) @@ -62,7 +63,7 @@ pub async fn iwd( output .send(Block { full_text: text.into(), - name: config.interface.clone(), + name: config.interface, ..Default::default() }) .await?; diff --git a/src/tiles/load.rs b/src/tiles/load.rs index d3616ed..be78477 100644 --- a/src/tiles/load.rs +++ b/src/tiles/load.rs @@ -1,22 +1,22 @@ +use std::convert::Infallible; + use crate::config::LoadConfig; use crate::output::OutputChannel; use crate::tile::Block; -use tokio::fs::File; -use tokio::io::AsyncReadExt; -pub async fn load(config: LoadConfig, output: OutputChannel) -> eyre::Result<()> { +pub async fn load(config: LoadConfig, output: OutputChannel) -> eyre::Result { let mut interval = tokio::time::interval(config.update); loop { interval.tick().await; - let mut raw = String::new(); - let mut file = File::open("/proc/loadavg").await?; - file.read_to_string(&mut raw).await?; - let (load, _rest) = raw.split_at(raw.find(' ').unwrap_or(0)); + let raw = tokio::fs::read_to_string("/proc/loadavg").await?; + let Some((load, _)) = raw.split_once(' ') else { + continue; + }; output .send(Block { full_text: load.into(), - name: "load".into(), + name: "load", ..Default::default() }) .await?; diff --git a/src/tiles/local_time.rs b/src/tiles/local_time.rs index 96da17f..343313a 100644 --- a/src/tiles/local_time.rs +++ b/src/tiles/local_time.rs @@ -4,6 +4,7 @@ use crate::tile::Block; use chrono::prelude::*; use maxminddb::geoip2; +use std::convert::Infallible; use std::net::IpAddr; use std::str::FromStr; use tokio::sync::watch; @@ -66,12 +67,14 @@ async fn find_time_zone(config: LocalTimeConfig, sender: watch::Sender) - } } -pub async fn local_time(config: LocalTimeConfig, output: OutputChannel) -> eyre::Result<()> { - let fallback_tz = if let Some(tz_name) = &config.fallback_zone { - chrono_tz::Tz::from_str(tz_name).ok() - } else { - None - }; +pub async fn local_time( + config: LocalTimeConfig, + output: OutputChannel, +) -> eyre::Result { + let fallback_tz = config + .fallback_zone + .as_ref() + .and_then(|tz_name| chrono_tz::Tz::from_str(tz_name).ok()); let (sender, mut receiver) = watch::channel(State { tz: fallback_tz }); let config_clone = config.clone(); @@ -97,7 +100,7 @@ pub async fn local_time(config: LocalTimeConfig, output: OutputChannel) -> eyre: .send(Block { full_text: local_now.format(&config.format).to_string().into(), short_text: Some(local_now.format(&config.short_format).to_string().into()), - name: "local_time".into(), + name: "local_time", ..Default::default() }) .await?; diff --git a/src/tiles/memory.rs b/src/tiles/memory.rs index 78fa569..b6d8efb 100644 --- a/src/tiles/memory.rs +++ b/src/tiles/memory.rs @@ -1,6 +1,7 @@ use crate::config::MemoryConfig; use crate::output::OutputChannel; use crate::tile::Block; +use std::convert::Infallible; use std::{io, str, u64}; use tokio::fs::File; use tokio::io::AsyncReadExt; @@ -9,11 +10,11 @@ fn prettify_kib(kib: u64) -> Box { let (mem, unit) = match kib { 0..=0x3ff => (kib, 'k'), 0x400..=0xfffff => (kib >> 10, 'M'), - 0x100000..=0x3fffffff => (kib >> 20, 'G'), - 0x40000000..=0xffffffffff => (kib >> 30, 'T'), - 0x10000000000..=0x3ffffffffffff => (kib >> 40, 'P'), - 0x4000000000000..=0xfffffffffffffff => (kib >> 50, 'E'), - 0x1000000000000000..=0xffffffffffffffff => (kib >> 60, 'Z'), + 0x10_0000..=0x3fff_ffff => (kib >> 20, 'G'), + 0x4000_0000..=0xff_ffff_ffff => (kib >> 30, 'T'), + 0x100_0000_0000..=0x3_ffff_ffff_ffff => (kib >> 40, 'P'), + 0x4_0000_0000_0000..=0xfff_ffff_ffff_ffff => (kib >> 50, 'E'), + 0x1000_0000_0000_0000..=0xffff_ffff_ffff_ffff => (kib >> 60, 'Z'), }; format!("{} {}iB", mem, unit).into_boxed_str() } @@ -27,7 +28,7 @@ fn extract_value(line: &str) -> eyre::Result { .parse()?) } -pub async fn memory(config: MemoryConfig, output: OutputChannel) -> eyre::Result<()> { +pub async fn memory(config: MemoryConfig, output: OutputChannel) -> eyre::Result { let mut interval = tokio::time::interval(config.update); loop { interval.tick().await; @@ -36,7 +37,7 @@ pub async fn memory(config: MemoryConfig, output: OutputChannel) -> eyre::Result let mut file = File::open("/proc/meminfo").await?; file.read_exact(&mut raw).await?; let string_data = str::from_utf8(&raw)?; - let mut lines = string_data.split('\n'); + let mut lines = string_data.lines(); let mem_total = prettify_kib(extract_value( lines .next() @@ -56,7 +57,7 @@ pub async fn memory(config: MemoryConfig, output: OutputChannel) -> eyre::Result .send(Block { full_text, short_text: Some(short_text), - name: "memory".into(), + name: "memory", ..Default::default() }) .await?; diff --git a/src/tiles/network_manager.rs b/src/tiles/network_manager.rs index 8c9789d..fbc6dae 100644 --- a/src/tiles/network_manager.rs +++ b/src/tiles/network_manager.rs @@ -3,21 +3,22 @@ use crate::generated::OrgFreedesktopNetworkManager; use crate::generated::OrgFreedesktopNetworkManagerAccessPoint; use crate::generated::OrgFreedesktopNetworkManagerConnectionActive; use crate::output::OutputChannel; -use crate::tile::Block; use dbus::nonblock::{Proxy, SyncConnection}; +use std::convert::Infallible; +use std::future::pending; use std::sync::Arc; use std::time::Duration; pub async fn network_manager( - config: NetworkManagerConfig, - output: OutputChannel, + _config: NetworkManagerConfig, + _output: OutputChannel, dbus_conn: Arc, -) -> eyre::Result<()> { +) -> eyre::Result { let root_proxy = Proxy::new( "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", Duration::from_secs(5), - dbus_conn.clone(), + dbus_conn.as_ref(), ); let primary_connection = root_proxy.primary_connection().await?; @@ -25,7 +26,7 @@ pub async fn network_manager( "org.freedesktop.NetworkManager", primary_connection, Duration::from_secs(5), - dbus_conn.clone(), + dbus_conn.as_ref(), ); let specific_object = primary_connection_proxy.specific_object().await?; @@ -33,14 +34,12 @@ pub async fn network_manager( "org.freedesktop.NetworkManager", specific_object, Duration::from_secs(5), - dbus_conn.clone(), + dbus_conn.as_ref(), ); let ssid = specific_object_proxy.ssid().await?; log::warn!("got ssid: {}", String::from_utf8_lossy(&ssid)); - loop { - tokio::time::sleep(Duration::from_secs(3600)).await; - } + pending().await } diff --git a/src/tiles/system_time.rs b/src/tiles/system_time.rs index a6e4822..eec5739 100644 --- a/src/tiles/system_time.rs +++ b/src/tiles/system_time.rs @@ -1,17 +1,22 @@ +use std::convert::Infallible; + use crate::config::SystemTimeConfig; use crate::output::OutputChannel; use crate::tile::Block; use chrono::prelude::*; use tokio::time::sleep; -pub async fn system_time(config: SystemTimeConfig, output: OutputChannel) -> eyre::Result<()> { +pub async fn system_time( + config: SystemTimeConfig, + output: OutputChannel, +) -> eyre::Result { loop { let now = Local::now(); output .send(Block { full_text: now.format(&config.format).to_string().into(), short_text: Some(now.format(&config.short_format).to_string().into()), - name: "system_time".into(), + name: "system_time", ..Default::default() }) .await?; diff --git a/src/tiles/utc_time.rs b/src/tiles/utc_time.rs index 5f73ee3..74157f6 100644 --- a/src/tiles/utc_time.rs +++ b/src/tiles/utc_time.rs @@ -1,17 +1,19 @@ +use std::convert::Infallible; + use crate::config::UtcTimeConfig; use crate::output::OutputChannel; use crate::tile::Block; use chrono::prelude::*; use tokio::time::sleep; -pub async fn utc_time(config: UtcTimeConfig, output: OutputChannel) -> eyre::Result<()> { +pub async fn utc_time(config: UtcTimeConfig, output: OutputChannel) -> eyre::Result { loop { let now = Utc::now(); output .send(Block { full_text: now.format(&config.format).to_string().into(), short_text: Some(now.format(&config.short_format).to_string().into()), - name: "utc_time".into(), + name: "utc_time", ..Default::default() }) .await?;