mirror of
https://mzte.de/git/LordMZTE/dotfiles.git
synced 2024-12-13 16:03:02 +01:00
add custom i3status
This commit is contained in:
parent
3d69167fdb
commit
42fa35e223
7 changed files with 261 additions and 0 deletions
2
i3status/.gitignore
vendored
Normal file
2
i3status/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
target
|
||||
Cargo.lock
|
19
i3status/Cargo.toml
Normal file
19
i3status/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "i3status"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
heim = "0.0.11"
|
||||
serde_json = "1.0.66"
|
||||
chrono = "0.4.19"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0.127"
|
||||
features = ["derive"]
|
||||
|
||||
[dependencies.tokio]
|
||||
version = "1.9.0"
|
||||
features = ["macros", "rt-multi-thread", "time", "sync", "process"]
|
3
i3status/README.md
Normal file
3
i3status/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# i3status
|
||||
custom i3status replacement.
|
||||
to use with my config, build this and move it to `~/.config/i3/i3status`
|
11
i3status/src/colors.rs
Normal file
11
i3status/src/colors.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
#![allow(dead_code)]
|
||||
pub const CYAN: &str = "#8be9fd";
|
||||
pub const GREEN: &str = "#50fa7b";
|
||||
pub const GREY: &str = "#6272a4";
|
||||
pub const ORANGE: &str = "#ffb86c";
|
||||
pub const PINK: &str = "#ff79c6";
|
||||
pub const PURPLE: &str = "#bd93f9";
|
||||
pub const RED: &str = "#ff5555";
|
||||
pub const WHITE: &str = "#f8f8f2";
|
||||
pub const YELLOW: &str = "#f1fa8c";
|
||||
|
7
i3status/src/json.rs
Normal file
7
i3status/src/json.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
use serde::Serialize;
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Block {
|
||||
pub full_text: String,
|
||||
// this is always a const color string, so this is fine for now
|
||||
pub color: &'static str,
|
||||
}
|
65
i3status/src/main.rs
Normal file
65
i3status/src/main.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use std::{sync::Arc, time::Duration};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::json::Block;
|
||||
|
||||
mod colors;
|
||||
mod json;
|
||||
mod workers;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let mut int = tokio::time::interval(Duration::from_millis(100));
|
||||
let bar = Arc::new(RwLock::new(Bar::default()));
|
||||
|
||||
spawn_workers(Arc::clone(&bar)).await;
|
||||
|
||||
println!("{}\n[[]", r#"{ "version": 1 }"#);
|
||||
loop {
|
||||
int.tick().await;
|
||||
let bar = bar.read().await;
|
||||
|
||||
let blocks = vec![
|
||||
Block {
|
||||
full_text: format!("龍 {:>7}", &bar.cpu_freq),
|
||||
color: colors::CYAN,
|
||||
},
|
||||
Block {
|
||||
full_text: format!(" {}", &bar.ram),
|
||||
color: colors::PURPLE,
|
||||
},
|
||||
Block {
|
||||
full_text: format!("{:>5}", &bar.vol),
|
||||
color: colors::ORANGE,
|
||||
},
|
||||
Block {
|
||||
full_text: format!("{:>5}", &bar.battery),
|
||||
color: colors::GREEN,
|
||||
},
|
||||
Block {
|
||||
full_text: bar.time.clone(),
|
||||
color: colors::WHITE,
|
||||
},
|
||||
];
|
||||
|
||||
let json = serde_json::to_string(&blocks).expect("failed to create json");
|
||||
println!(",{}", json);
|
||||
}
|
||||
}
|
||||
|
||||
async fn spawn_workers(bar: Arc<RwLock<Bar>>) {
|
||||
tokio::spawn(workers::ram(Arc::clone(&bar)));
|
||||
tokio::spawn(workers::time(Arc::clone(&bar)));
|
||||
tokio::spawn(workers::pulseaudio_vol(Arc::clone(&bar)));
|
||||
tokio::spawn(workers::cpu_freq(Arc::clone(&bar)));
|
||||
tokio::spawn(workers::battery(Arc::clone(&bar)));
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Bar {
|
||||
ram: String,
|
||||
time: String,
|
||||
vol: String,
|
||||
cpu_freq: String,
|
||||
battery: String,
|
||||
}
|
154
i3status/src/workers.rs
Normal file
154
i3status/src/workers.rs
Normal file
|
@ -0,0 +1,154 @@
|
|||
use crate::Bar;
|
||||
use chrono::Local;
|
||||
use heim::units::frequency::megahertz;
|
||||
use heim::{memory::os::linux::MemoryExt, units::information::megabyte};
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::process::Command;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
pub(crate) async fn ram(bar: Arc<RwLock<Bar>>) {
|
||||
let mut int = tokio::time::interval(Duration::from_secs(1));
|
||||
|
||||
loop {
|
||||
let mem = heim::memory::memory().await;
|
||||
let ram;
|
||||
if let Ok(mem) = mem {
|
||||
ram = format!(
|
||||
"{}MB/{}MB",
|
||||
mem.used().get::<megabyte>(),
|
||||
mem.free().get::<megabyte>()
|
||||
);
|
||||
} else {
|
||||
ram = String::from("error reading ram :(");
|
||||
}
|
||||
bar.write().await.ram = ram;
|
||||
int.tick().await;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn time(bar: Arc<RwLock<Bar>>) {
|
||||
let mut int = tokio::time::interval(Duration::from_millis(200));
|
||||
|
||||
loop {
|
||||
let time = Local::now().format("%a %d.%m.%Y %T").to_string();
|
||||
|
||||
bar.write().await.time = time;
|
||||
int.tick().await;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn pulseaudio_vol(bar: Arc<RwLock<Bar>>) {
|
||||
let mut int = tokio::time::interval(Duration::from_secs(2));
|
||||
|
||||
loop {
|
||||
let res = Command::new("pactl")
|
||||
.arg("get-sink-volume")
|
||||
.arg("@DEFAULT_SINK@")
|
||||
.output()
|
||||
.await
|
||||
.ok()
|
||||
.and_then(|o| String::from_utf8(o.stdout).ok());
|
||||
|
||||
let mute = Command::new("pactl")
|
||||
.arg("get-sink-mute")
|
||||
.arg("@DEFAULT_SINK@")
|
||||
.output()
|
||||
.await
|
||||
.map(|o| o.stdout.contains(&b'y'))
|
||||
.unwrap_or(false);
|
||||
|
||||
let msg;
|
||||
|
||||
match res {
|
||||
Some(out) => {
|
||||
// get first line
|
||||
let out = out.lines().next().unwrap_or(&out);
|
||||
let volumes = out
|
||||
.split(' ')
|
||||
.filter(|s| s.contains('%'))
|
||||
.map(|s| s.trim().replace('%', "").parse::<u8>())
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.unwrap_or_else(|_| vec![]);
|
||||
|
||||
let mut avg = 0u8;
|
||||
for v in &volumes {
|
||||
avg += v / volumes.len() as u8;
|
||||
}
|
||||
|
||||
let symbol = if mute { '遼' } else { '蓼' };
|
||||
|
||||
msg = format!("{} {}%", symbol, avg);
|
||||
}
|
||||
None => msg = String::from("PA Error :("),
|
||||
}
|
||||
|
||||
bar.write().await.vol = msg;
|
||||
int.tick().await;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn cpu_freq(bar: Arc<RwLock<Bar>>) {
|
||||
let mut int = tokio::time::interval(Duration::from_secs(2));
|
||||
|
||||
loop {
|
||||
let freq = heim::cpu::frequency().await;
|
||||
let txt;
|
||||
if let Ok(freq) = freq {
|
||||
let freq = freq.current().get::<megahertz>();
|
||||
txt = format!("{}MHz", freq);
|
||||
} else {
|
||||
txt = String::from("Error reading CPU frequency :(");
|
||||
}
|
||||
bar.write().await.cpu_freq = txt;
|
||||
int.tick().await;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn battery(bar: Arc<RwLock<Bar>>) {
|
||||
enum BatteryState {
|
||||
Charging,
|
||||
Discharging,
|
||||
NotCharging,
|
||||
}
|
||||
|
||||
let mut int = tokio::time::interval(Duration::from_secs(10));
|
||||
|
||||
loop {
|
||||
let out = Command::new("acpi")
|
||||
.output()
|
||||
.await
|
||||
.ok()
|
||||
.and_then(|o| String::from_utf8(o.stdout).ok());
|
||||
|
||||
let txt;
|
||||
if let Some(s) = out {
|
||||
if let Some(bat) = s.lines().next() {
|
||||
let percent = bat.split(' ').find(|s| s.contains('%')).unwrap_or("0%");
|
||||
let state = if bat.contains("Charging") {
|
||||
BatteryState::Charging
|
||||
} else if bat.contains("Discharging") {
|
||||
BatteryState::Discharging
|
||||
} else {
|
||||
BatteryState::NotCharging
|
||||
};
|
||||
|
||||
let icon = match state {
|
||||
BatteryState::Charging => '',
|
||||
BatteryState::Discharging => '',
|
||||
BatteryState::NotCharging => '',
|
||||
};
|
||||
|
||||
txt = format!("{} {}", icon, percent);
|
||||
} else {
|
||||
txt = String::from("No bat")
|
||||
}
|
||||
} else {
|
||||
txt = String::from("Battery Error :(");
|
||||
}
|
||||
|
||||
bar.write().await.battery = txt;
|
||||
int.tick().await;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue