i3status_rs/blocks/
uptime.rs

1//! System's uptime
2//!
3//! This block displays system uptime in terms of two biggest units, so minutes and seconds, or
4//! hours and minutes or days and hours or weeks and days.
5//!
6//! # Configuration
7//!
8//! Key        | Values                     | Default
9//! -----------|----------------------------|--------
10//! `format` | A string to customise the output of this block. See below for available placeholders | `" $icon $uptime "`
11//! `interval` | Update interval in seconds | `60`
12//!
13//! Placeholder         | Value                   | Type     | Unit
14//! --------------------|-------------------------|----------|-----
15//! `icon`              | A static icon           | Icon     | -
16//! `text` *DEPRECATED* | Current uptime          | Text     | -
17//! `uptime`            | Current uptime          | Duration | -
18//!
19//! `text` has been deprecated in favor of `uptime`.
20//!
21//! # Example
22//!
23//! ```toml
24//! [[block]]
25//! block = "uptime"
26//! interval = 3600 # update every hour
27//! ```
28//!
29//! # Used Icons
30//! - `uptime`
31
32use 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}