Lots of misc code changes
This commit is contained in:
parent
c0f832bcef
commit
5fab9bc98b
|
@ -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<str>,
|
||||
#[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::<str>::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<Config> {
|
||||
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()
|
||||
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") {
|
||||
[&home, ".config", "rustybar", "config.toml"]
|
||||
.iter()
|
||||
.collect()
|
||||
PathBuf::from_iter([&home, ".config/rustybar/config.toml"])
|
||||
} else {
|
||||
eyre::bail!("Could not find RUSTYBAR_CONFIG, XDG_CONFIG_HOME, or HOME environment variables");
|
||||
}
|
||||
}
|
||||
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),
|
||||
}
|
||||
})
|
||||
|
|
|
@ -45,12 +45,11 @@ pub async fn run(num_tiles: usize, mut receiver: mpsc::Receiver<TileData>) -> 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?;
|
||||
|
|
|
@ -74,7 +74,7 @@ pub struct Block {
|
|||
pub min_width: Option<u32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub align: Option<Alignment>,
|
||||
pub name: Box<str>,
|
||||
pub name: &'static str,
|
||||
#[serde(serialize_with = "arc_default")]
|
||||
#[default = ""]
|
||||
pub instance: Arc<str>,
|
||||
|
|
|
@ -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<Infallible> {
|
||||
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<u32> {
|
||||
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?;
|
||||
|
|
|
@ -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<SyncConnection>,
|
||||
) -> eyre::Result<()> {
|
||||
) -> eyre::Result<Infallible> {
|
||||
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?;
|
||||
|
|
|
@ -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<Infallible> {
|
||||
// "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?;
|
||||
|
|
|
@ -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<SyncConnection>,
|
||||
) -> eyre::Result<()> {
|
||||
) -> eyre::Result<Infallible> {
|
||||
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?;
|
||||
|
|
|
@ -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<Infallible> {
|
||||
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?;
|
||||
|
|
|
@ -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<State>) -
|
|||
}
|
||||
}
|
||||
|
||||
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<Infallible> {
|
||||
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?;
|
||||
|
|
|
@ -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<str> {
|
|||
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<u64> {
|
|||
.parse()?)
|
||||
}
|
||||
|
||||
pub async fn memory(config: MemoryConfig, output: OutputChannel) -> eyre::Result<()> {
|
||||
pub async fn memory(config: MemoryConfig, output: OutputChannel) -> eyre::Result<Infallible> {
|
||||
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?;
|
||||
|
|
|
@ -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<SyncConnection>,
|
||||
) -> eyre::Result<()> {
|
||||
) -> eyre::Result<Infallible> {
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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<Infallible> {
|
||||
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?;
|
||||
|
|
|
@ -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<Infallible> {
|
||||
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?;
|
||||
|
|
Loading…
Reference in a new issue