diff --git a/Cargo.lock b/Cargo.lock index f21044e..980d4ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -306,6 +306,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -330,6 +336,7 @@ version = "0.4.0" dependencies = [ "color-eyre", "criterion", + "lazy_static", "nix", ] diff --git a/Cargo.toml b/Cargo.toml index 5c346cb..107d793 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ path = "src/main.rs" [dependencies] nix = { version = "0.29", features = ["fs", "hostname", "feature"] } color-eyre = { version = "0.6", default-features = false } +lazy_static = "1.5.0" [dev-dependencies] criterion = "0.5" diff --git a/src/colors.rs b/src/colors.rs index a8aee60..061db15 100644 --- a/src/colors.rs +++ b/src/colors.rs @@ -1,11 +1,57 @@ -pub const RESET: &str = "\x1b[0m"; -pub const BLUE: &str = "\x1b[34m"; -pub const CYAN: &str = "\x1b[36m"; -pub const GREEN: &str = "\x1b[32m"; -pub const YELLOW: &str = "\x1b[33m"; -pub const RED: &str = "\x1b[31m"; -pub const MAGENTA: &str = "\x1b[35m"; +use std::env; + +pub struct Colors { + pub reset: &'static str, + pub blue: &'static str, + pub cyan: &'static str, + pub green: &'static str, + pub yellow: &'static str, + pub red: &'static str, + pub magenta: &'static str, +} + +impl Colors { + const fn new(is_no_color: bool) -> Self { + match is_no_color { + true => Self { + reset: "", + blue: "", + cyan: "", + green: "", + yellow: "", + red: "", + magenta: "", + }, + false => Self { + reset: "\x1b[0m", + blue: "\x1b[34m", + cyan: "\x1b[36m", + green: "\x1b[32m", + yellow: "\x1b[33m", + red: "\x1b[31m", + magenta: "\x1b[35m", + }, + } + } +} + +lazy_static::lazy_static! { + pub static ref COLORS: Colors = { + // check for NO_COLOR once at startup + let is_no_color = env::var("NO_COLOR").is_ok(); + Colors::new(is_no_color) + }; +} pub fn print_dots() -> String { - format!("{BLUE} {CYAN} {GREEN} {YELLOW} {RED} {MAGENTA} {RESET}") + format!( + "{} {} {} {} {} {} {}", + COLORS.blue, + COLORS.cyan, + COLORS.green, + COLORS.yellow, + COLORS.red, + COLORS.magenta, + COLORS.reset, + ) } diff --git a/src/main.rs b/src/main.rs index 5cb9904..0ea1672 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,15 +4,13 @@ mod release; mod system; mod uptime; -use std::io::Write; - -use crate::colors::{print_dots, BLUE, CYAN, RESET}; +use crate::colors::print_dots; use crate::desktop::get_desktop_info; use crate::release::{get_os_pretty_name, get_system_info}; use crate::system::{get_memory_usage, get_root_disk_usage, get_shell, get_username_and_hostname}; use crate::uptime::get_current; - use color_eyre::Report; +use std::io::Write; fn main() -> Result<(), Report> { color_eyre::install()?; @@ -56,6 +54,8 @@ struct Fields { } fn print_system_info(fields: &Fields) { + use crate::colors::COLORS; + let Fields { user_info, os_name, @@ -68,16 +68,22 @@ fn print_system_info(fields: &Fields) { colors, } = fields; - let _ = std::io::stdout().write_all(format!( - " - {CYAN} ▟█▖ {BLUE}▝█▙ ▗█▛ {user_info} ~{RESET} - {CYAN} ▗▄▄▟██▄▄▄▄▄{BLUE}▝█▙█▛ {CYAN}▖ {CYAN} {BLUE}System{RESET}  {os_name} - {CYAN} ▀▀▀▀▀▀▀▀▀▀▀▘{BLUE}▝██ {CYAN}▟█▖ {CYAN} {BLUE}Kernel{RESET}  {kernel_version} - {BLUE} ▟█▛ {BLUE}▝█▘{CYAN}▟█▛ {CYAN} {BLUE}Shell{RESET}  {shell} - {BLUE}▟█████▛ {CYAN}▟█████▛ {CYAN} {BLUE}Uptime{RESET}  {uptime} - {BLUE} ▟█▛{CYAN}▗█▖ {CYAN}▟█▛ {CYAN} {BLUE}Desktop{RESET}  {desktop} - {BLUE} ▝█▛ {CYAN}██▖{BLUE}▗▄▄▄▄▄▄▄▄▄▄▄ {CYAN}󰍛 {BLUE}Memory{RESET}  {memory_usage} - {BLUE} ▝ {CYAN}▟█▜█▖{BLUE}▀▀▀▀▀██▛▀▀▘ {CYAN}󱥎 {BLUE}Storage (/){RESET}  {storage} - {CYAN} ▟█▘ ▜█▖ {BLUE}▝█▛ {CYAN} {BLUE}Colors{RESET}  {colors} -").as_bytes()); + let cyan = COLORS.cyan; + let blue = COLORS.blue; + let reset = COLORS.reset; + let system_info = format!(" + {cyan} ▟█▖ {blue}▝█▙ ▗█▛ {user_info} ~{reset} + {cyan} ▗▄▄▟██▄▄▄▄▄{blue}▝█▙█▛ {cyan}▖ {cyan} {blue}System{reset}  {os_name} + {cyan} ▀▀▀▀▀▀▀▀▀▀▀▘{blue}▝██ {cyan}▟█▖ {cyan} {blue}Kernel{reset}  {kernel_version} + {blue} ▟█▛ {blue}▝█▘{cyan}▟█▛ {cyan} {blue}Shell{reset}  {shell} + {blue}▟█████▛ {cyan}▟█████▛ {cyan} {blue}Uptime{reset}  {uptime} + {blue} ▟█▛{cyan}▗█▖ {cyan}▟█▛ {cyan} {blue}Desktop{reset}  {desktop} + {blue} ▝█▛ {cyan}██▖{blue}▗▄▄▄▄▄▄▄▄▄▄▄ {cyan}󰍛 {blue}Memory{reset}  {memory_usage} + {blue} ▝ {cyan}▟█▜█▖{blue}▀▀▀▀▀██▛▀▀▘ {cyan}󱥎 {blue}Storage (/){reset}  {storage} + {cyan} ▟█▘ ▜█▖ {blue}▝█▛ {cyan} {blue}Colors{reset}  {colors}"); + + std::io::stdout() + .lock() + .write_all(system_info.as_bytes()) + .expect("Failed to write to stdout"); } diff --git a/src/system.rs b/src/system.rs index 74d774f..11a72d9 100644 --- a/src/system.rs +++ b/src/system.rs @@ -1,14 +1,12 @@ +use crate::colors::COLORS; use color_eyre::Result; use nix::sys::{statvfs::statvfs, utsname::UtsName}; - use std::{ env, fs::File, io::{self, Read}, }; -use crate::colors::{CYAN, GREEN, RED, RESET, YELLOW}; - pub fn get_username_and_hostname(utsname: &UtsName) -> String { let username = env::var("USER").unwrap_or("unknown_user".to_string()); let hostname = utsname @@ -16,14 +14,18 @@ pub fn get_username_and_hostname(utsname: &UtsName) -> String { .to_str() .unwrap_or("unknown_host") .to_string(); - - format!("{YELLOW}{username}{RED}@{GREEN}{hostname}") + format!( + "{yellow}{username}{red}@{green}{hostname}{reset}", + yellow = COLORS.yellow, + red = COLORS.red, + green = COLORS.green, + reset = COLORS.reset, + ) } pub fn get_shell() -> String { let shell_path = env::var("SHELL").unwrap_or("unknown_shell".to_string()); let shell_name = shell_path.rsplit('/').next().unwrap_or("unknown_shell"); - shell_name.to_string() } @@ -32,16 +34,15 @@ pub fn get_root_disk_usage() -> Result { let block_size = vfs.block_size() as u64; let total_blocks = vfs.blocks(); let available_blocks = vfs.blocks_available(); - let total_size = block_size * total_blocks; let used_size = total_size - (block_size * available_blocks); - let total_size = total_size as f64 / (1024.0 * 1024.0 * 1024.0); let used_size = used_size as f64 / (1024.0 * 1024.0 * 1024.0); - let usage = (used_size as f64 / total_size as f64) * 100.0; - + let usage = (used_size / total_size) * 100.0; Ok(format!( - "{used_size:.2} GiB / {total_size:.2} GiB ({CYAN}{usage:.0}%{RESET})" + "{used_size:.2} GiB / {total_size:.2} GiB ({cyan}{usage:.0}%{reset})", + cyan = COLORS.cyan, + reset = COLORS.reset, )) } @@ -50,35 +51,31 @@ pub fn get_memory_usage() -> Result { fn parse_memory_info() -> Result<(f64, f64), io::Error> { let mut total_memory_kb = 0.0; let mut available_memory_kb = 0.0; - let mut meminfo = String::with_capacity(2048); File::open("/proc/meminfo")?.read_to_string(&mut meminfo)?; - for line in meminfo.lines() { let mut split = line.split_whitespace(); match split.next().unwrap_or_default() { "MemTotal:" => total_memory_kb = split.next().unwrap_or("0").parse().unwrap_or(0.0), "MemAvailable:" => { available_memory_kb = split.next().unwrap_or("0").parse().unwrap_or(0.0); - // MemTotal comes before MemAvailable, stop parsing break; } _ => (), } } - let total_memory_gb = total_memory_kb / 1024.0 / 1024.0; let available_memory_gb = available_memory_kb / 1024.0 / 1024.0; let used_memory_gb = total_memory_gb - available_memory_gb; - Ok((used_memory_gb, total_memory_gb)) } let (used_memory, total_memory) = parse_memory_info()?; let percentage_used = (used_memory / total_memory * 100.0).round() as u64; - Ok(format!( - "{used_memory:.2} GiB / {total_memory:.2} GiB ({CYAN}{percentage_used}%{RESET})" + "{used_memory:.2} GiB / {total_memory:.2} GiB ({cyan}{percentage_used}%{reset})", + cyan = COLORS.cyan, + reset = COLORS.reset, )) }