i3status_rs/blocks/
uptime.rs1use super::prelude::*;
33use tokio::fs::read_to_string;
34
35#[derive(Deserialize, Debug, SmartDefault)]
36#[serde(deny_unknown_fields, default)]
37pub struct Config {
38 pub format: FormatConfig,
39 #[default(60.into())]
40 pub interval: Seconds,
41}
42
43pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
44 let format = config.format.with_default(" $icon $uptime ")?;
45
46 loop {
47 let uptime = read_to_string("/proc/uptime")
48 .await
49 .error("Failed to read /proc/uptime")?;
50 let mut seconds: u64 = uptime
51 .split('.')
52 .next()
53 .and_then(|u| u.parse().ok())
54 .error("/proc/uptime has invalid content")?;
55
56 let uptime = Duration::from_secs(seconds);
57
58 let weeks = seconds / 604_800;
59 seconds %= 604_800;
60 let days = seconds / 86_400;
61 seconds %= 86_400;
62 let hours = seconds / 3_600;
63 seconds %= 3_600;
64 let minutes = seconds / 60;
65 seconds %= 60;
66
67 let text = if weeks > 0 {
68 format!("{weeks}w {days}d")
69 } else if days > 0 {
70 format!("{days}d {hours}h")
71 } else if hours > 0 {
72 format!("{hours}h {minutes}m")
73 } else {
74 format!("{minutes}m {seconds}s")
75 };
76
77 let mut widget = Widget::new().with_format(format.clone());
78 widget.set_values(map! {
79 "icon" => Value::icon("uptime"),
80 "text" => Value::text(text),
81 "uptime" => Value::duration(uptime)
82 });
83 api.set_widget(widget)?;
84
85 select! {
86 _ = sleep(config.interval.0) => (),
87 _ = api.wait_for_update_request() => (),
88 }
89 }
90}