use colored::{ColoredString, Colorize};
use itertools::Itertools;
use once_cell::sync::Lazy;
use std::env;
use std::fmt::Write;
use sysinfo::{CpuRefreshKind, DiskKind, Disks, MemoryRefreshKind, RefreshKind, System};
use time::Duration;
use users::get_current_username;
const KIB: u64 = 1024;
const MIB: u64 = 1048576;
const GIB: u64 = 1073741000;
const TIB: u64 = 1099511000000;
const PIB: u64 = 1125899000000000;
fn b_to_human_readable(value: u64, higher_precision: bool) -> String {
if value < KIB || (higher_precision && value < MIB) {
format!("{}{}", value, "B")
} else if value < MIB || (higher_precision && value < GIB) {
format!("{}{}", value / KIB, "KiB")
} else if value < GIB || (higher_precision && value < TIB) {
format!("{}{}", value / MIB, "MiB")
} else if value < TIB || (higher_precision && value < PIB) {
format!("{}{}", value / GIB, "GiB")
} else if value < PIB || higher_precision {
format!("{:.2}{}", (value as f64 / TIB as f64), "TiB")
} else {
format!("{:.2}{}", (value as f64 / PIB as f64), "PiB")
}
}
fn memory_usage(used: u64, total: u64) -> ColoredString {
let factor = used as f64 / total as f64;
let color = (factor * 255.0).min(u8::MAX as f64) as u8;
format!("{}%", (factor * 100.0) as u8)
.truecolor(color, 128, 255 - color)
.bold()
}
pub static USERNAME: Lazy<String> = Lazy::new(|| match get_current_username() {
Some(user_name) => match user_name.into_string() {
Ok(user_name) => user_name,
Err(_) => String::from("unknown"),
},
None => String::from("unknown"),
});
pub static HOSTNAME: Lazy<String> = Lazy::new(|| match sysinfo::System::host_name() {
Some(host_name) => host_name,
None => String::from("unknown"),
});
pub static OS_NAME: Lazy<String> = Lazy::new(|| match sysinfo::System::long_os_version() {
Some(name) => name,
None => String::from("unknown"),
});
pub static KERNEL: Lazy<String> = Lazy::new(|| match sysinfo::System::kernel_version() {
Some(kernel_version) => kernel_version,
None => String::from("unknown"),
});
pub static UPTIME: Lazy<String> =
Lazy::new(|| Duration::seconds(sysinfo::System::uptime() as i64).to_string());
pub static SHELL: Lazy<String> = Lazy::new(|| match env::var("SHELL") {
Ok(shell) => match shell.rsplit_once('/') {
Some((_, shell)) => String::from(shell),
None => shell,
},
Err(_) => String::from("unknown"),
});
pub static TERM: Lazy<String> = Lazy::new(|| match env::var("TERM") {
Err(_) => String::from("unknown"),
Ok(term) => term,
});
pub static TERMINAL: Lazy<String> = Lazy::new(|| {
let term: &str = &TERM;
let shell: &str = &SHELL;
format!("{} + {}", term, shell)
});
pub static DESKTOP: Lazy<String> = Lazy::new(|| match env::var("XDG_CURRENT_DESKTOP") {
Err(_) => String::from("unknown"),
Ok(desktop) => desktop,
});
pub static CPU_NAME: Lazy<String> = Lazy::new(|| {
let sys = System::new_with_specifics(RefreshKind::new().with_cpu(CpuRefreshKind::new()));
itertools::Itertools::intersperse(sys.cpus().iter().map(|cpu| cpu.brand()).unique(), ", ")
.collect()
});
pub static MEMORY_USAGE: Lazy<String> = Lazy::new(|| {
let sys = System::new_with_specifics(
RefreshKind::new().with_memory(MemoryRefreshKind::new().with_ram()),
);
let used = sys.used_memory();
let total = sys.total_memory();
format!(
"{} / {} ({})",
b_to_human_readable(used, true),
b_to_human_readable(total, true),
memory_usage(used, total),
)
});
pub static COLORS: Lazy<String> = Lazy::new(|| {
format!(
"{}{}{}{}{}{}{}{}",
"██".black(),
"██".red(),
"██".green(),
"██".yellow(),
"██".blue(),
"██".magenta(),
"██".cyan(),
"██".white(),
)
});
pub static COLORS_BRIGHT: Lazy<String> = Lazy::new(|| {
format!(
"{}{}{}{}{}{}{}{}",
"██".bright_black(),
"██".bright_red(),
"██".bright_green(),
"██".bright_yellow(),
"██".bright_blue(),
"██".bright_magenta(),
"██".bright_cyan(),
"██".bright_white(),
)
});
pub static COLORS_DUAL: Lazy<String> = Lazy::new(|| {
format!(
"{}{}{}{}{}{}{}{}",
"▀▀".black().on_bright_black(),
"▀▀".red().on_bright_red(),
"▀▀".green().on_bright_green(),
"▀▀".yellow().on_bright_yellow(),
"▀▀".blue().on_bright_blue(),
"▀▀".magenta().on_bright_magenta(),
"▀▀".cyan().on_bright_cyan(),
"▀▀".white().on_bright_white(),
)
});
static DISKS_SYSINFO: Lazy<Disks> = Lazy::new(Disks::new_with_refreshed_list);
pub static DISK: Lazy<String> = Lazy::new(|| {
DISKS_SYSINFO
.iter()
.filter(|disk| (disk.kind() == DiskKind::HDD || disk.kind() == DiskKind::SSD))
.take(1)
.fold(String::new(), |mut acc, disk| {
let total = disk.total_space();
let used = total - disk.available_space();
write!(
&mut acc,
"{} / {} ({})",
b_to_human_readable(used, false),
b_to_human_readable(total, false),
memory_usage(used, total)
)
.expect("Could not format disk string!");
acc
})
});
pub static DISKS: Lazy<String> = Lazy::new(|| {
DISKS_SYSINFO
.iter()
.filter(|disk| {
(disk.kind() == DiskKind::HDD || disk.kind() == DiskKind::SSD)
|| (disk.file_system() == "tmpfs" && !disk.mount_point().starts_with("/dev"))
})
.unique_by(|disk| disk.name())
.map(|disk| {
let total = disk.total_space();
let used = total - disk.available_space();
format!(
"[{}]: {} / {} ({})",
disk.mount_point().to_string_lossy(),
b_to_human_readable(used, false),
b_to_human_readable(total, false),
memory_usage(used, total),
)
})
.join("\n")
});