From fd7da43393e59e1f1f85db93a2891c867de187ee Mon Sep 17 00:00:00 2001 From: neoarz Date: Wed, 7 Jan 2026 22:35:41 -0500 Subject: [PATCH] chore: clippy & fmt --- src/helpers/battery.rs | 44 +++++------ src/helpers/cursor.rs | 82 +++++++++++---------- src/helpers/display.rs | 14 +++- src/helpers/gpu.rs | 4 +- src/helpers/host.rs | 159 +++++++++++++++++++++------------------- src/helpers/ip.rs | 37 ++++------ src/helpers/locale.rs | 17 ++--- src/helpers/memory.rs | 4 +- src/helpers/shell.rs | 9 +-- src/helpers/storage.rs | 7 +- src/helpers/swap.rs | 18 +++-- src/helpers/terminal.rs | 11 ++- src/helpers/wm.rs | 39 +++++----- src/helpers/wm_theme.rs | 42 +++++------ src/main.rs | 25 ++++--- src/output/image.rs | 94 ++++++++++++++---------- 16 files changed, 322 insertions(+), 284 deletions(-) diff --git a/src/helpers/battery.rs b/src/helpers/battery.rs index fea880a..2e5bfa8 100644 --- a/src/helpers/battery.rs +++ b/src/helpers/battery.rs @@ -45,19 +45,19 @@ pub fn get_battery_info() -> (String, String) { let value = value_part.trim_matches(';').trim(); is_charging = value == "Yes"; } - } else if line.contains("\"AvgTimeToEmpty\"") { - if let Some(equals_pos) = line.find('=') { - let value_part = &line[equals_pos + 1..].trim(); - let value = value_part.trim_matches(';').trim(); - if let Ok(time) = value.parse::() { - avg_time_to_empty = Some(time); - } + } else if line.contains("\"AvgTimeToEmpty\"") + && let Some(equals_pos) = line.find('=') + { + let value_part = &line[equals_pos + 1..].trim(); + let value = value_part.trim_matches(';').trim(); + if let Ok(time) = value.parse::() { + avg_time_to_empty = Some(time); } } } let percentage = if let Some(capacity) = current_capacity { - if capacity >= 0 && capacity <= 100 { + if (0..=100).contains(&capacity) { capacity as u32 } else { return (format!("({})", device_name), "".to_string()); @@ -76,20 +76,21 @@ pub fn get_battery_info() -> (String, String) { let mut result = crate::output::colors::battery_percent(percentage); - if !external_connected && !is_charging { - if let Some(time_mins) = avg_time_to_empty { - if time_mins > 0 && time_mins < 0xFFFF { - let hours = time_mins / 60; - let mins = time_mins % 60; + if !external_connected + && !is_charging + && let Some(time_mins) = avg_time_to_empty + && time_mins > 0 + && time_mins < 0xFFFF + { + let hours = time_mins / 60; + let mins = time_mins % 60; - if hours > 0 && mins > 0 { - result.push_str(&format!(" ({} hours, {} mins remaining)", hours, mins)); - } else if hours > 0 { - result.push_str(&format!(" ({} hours remaining)", hours)); - } else if mins > 0 { - result.push_str(&format!(" ({} mins remaining)", mins)); - } - } + if hours > 0 && mins > 0 { + result.push_str(&format!(" ({} hours, {} mins remaining)", hours, mins)); + } else if hours > 0 { + result.push_str(&format!(" ({} hours remaining)", hours)); + } else if mins > 0 { + result.push_str(&format!(" ({} mins remaining)", mins)); } } @@ -97,4 +98,3 @@ pub fn get_battery_info() -> (String, String) { (format!("({})", device_name), result) } - diff --git a/src/helpers/cursor.rs b/src/helpers/cursor.rs index 6c70b38..4fad074 100644 --- a/src/helpers/cursor.rs +++ b/src/helpers/cursor.rs @@ -12,45 +12,53 @@ pub fn get_cursor_info() -> String { let mut outline = "White".to_string(); let mut size = "32".to_string(); - if let Ok(value) = Value::from_file(path) { - if let Some(dict) = value.as_dictionary() { - if let Some(f_dict) = dict.get("cursorFill").and_then(|v| v.as_dictionary()) { - let r = (f_dict.get("red").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; - let g = (f_dict.get("green").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; - let b = (f_dict.get("blue").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; - let a = (f_dict.get("alpha").and_then(|v| v.as_real()).unwrap_or(1.0) * 255.0 + 0.5) as u32; - let color_hex = (r << 24) | (g << 16) | (b << 8) | a; - fill = match color_hex { - 0x000000FF => "Black".to_string(), - 0xFFFFFFFF => "White".to_string(), - 0xFF2600FF => "Red".to_string(), - 0x0433FFFF => "Blue".to_string(), - 0x00F900FF => "Green".to_string(), - 0xFFFB00FF => "Yellow".to_string(), - _ => format!("#{:08X}", color_hex), - }; - } + if let Ok(value) = Value::from_file(path) + && let Some(dict) = value.as_dictionary() + { + if let Some(f_dict) = dict.get("cursorFill").and_then(|v| v.as_dictionary()) { + let r = + (f_dict.get("red").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; + let g = + (f_dict.get("green").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; + let b = + (f_dict.get("blue").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; + let a = + (f_dict.get("alpha").and_then(|v| v.as_real()).unwrap_or(1.0) * 255.0 + 0.5) as u32; + let color_hex = (r << 24) | (g << 16) | (b << 8) | a; + fill = match color_hex { + 0x000000FF => "Black".to_string(), + 0xFFFFFFFF => "White".to_string(), + 0xFF2600FF => "Red".to_string(), + 0x0433FFFF => "Blue".to_string(), + 0x00F900FF => "Green".to_string(), + 0xFFFB00FF => "Yellow".to_string(), + _ => format!("#{:08X}", color_hex), + }; + } - if let Some(o_dict) = dict.get("cursorOutline").and_then(|v| v.as_dictionary()) { - let r = (o_dict.get("red").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; - let g = (o_dict.get("green").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; - let b = (o_dict.get("blue").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; - let a = (o_dict.get("alpha").and_then(|v| v.as_real()).unwrap_or(1.0) * 255.0 + 0.5) as u32; - let color_hex = (r << 24) | (g << 16) | (b << 8) | a; - outline = match color_hex { - 0x000000FF => "Black".to_string(), - 0xFFFFFFFF => "White".to_string(), - 0xFF2600FF => "Red".to_string(), - 0x0433FFFF => "Blue".to_string(), - 0x00F900FF => "Green".to_string(), - 0xFFFB00FF => "Yellow".to_string(), - _ => format!("#{:08X}", color_hex), - }; - } + if let Some(o_dict) = dict.get("cursorOutline").and_then(|v| v.as_dictionary()) { + let r = + (o_dict.get("red").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; + let g = + (o_dict.get("green").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; + let b = + (o_dict.get("blue").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; + let a = + (o_dict.get("alpha").and_then(|v| v.as_real()).unwrap_or(1.0) * 255.0 + 0.5) as u32; + let color_hex = (r << 24) | (g << 16) | (b << 8) | a; + outline = match color_hex { + 0x000000FF => "Black".to_string(), + 0xFFFFFFFF => "White".to_string(), + 0xFF2600FF => "Red".to_string(), + 0x0433FFFF => "Blue".to_string(), + 0x00F900FF => "Green".to_string(), + 0xFFFB00FF => "Yellow".to_string(), + _ => format!("#{:08X}", color_hex), + }; + } - if let Some(s_val) = dict.get("mouseDriverCursorSize").and_then(|v| v.as_real()) { - size = format!("{:.0}", s_val * 32.0); - } + if let Some(s_val) = dict.get("mouseDriverCursorSize").and_then(|v| v.as_real()) { + size = format!("{:.0}", s_val * 32.0); } } diff --git a/src/helpers/display.rs b/src/helpers/display.rs index f795831..b77b1f2 100644 --- a/src/helpers/display.rs +++ b/src/helpers/display.rs @@ -18,10 +18,20 @@ pub fn get_display_info() -> String { }; if display_count > 1 { - let name = if main.name.is_empty() { "Color LCD" } else { &main.name }; + let name = if main.name.is_empty() { + "Color LCD" + } else { + &main.name + }; format!( "({}) {}x{} @ {}x in {}\", {} Hz {}", - name, p_width, p_height, main.scale_factor as u32, inches, main.frequency as u32, tag + name, + p_width, + p_height, + main.scale_factor as u32, + inches, + main.frequency as u32, + tag ) } else { format!( diff --git a/src/helpers/gpu.rs b/src/helpers/gpu.rs index 3eaa770..a7734f5 100644 --- a/src/helpers/gpu.rs +++ b/src/helpers/gpu.rs @@ -20,9 +20,7 @@ pub fn get_gpu_info() -> String { .nth(1) .unwrap_or("") .trim() - .replace('"', "") - .replace('<', "") - .replace('>', ""); + .replace(['"', '<', '>'], ""); } if line.contains("\"gpu-core-count\"") { cores = line.split('=').nth(1).unwrap_or("").trim().to_string(); diff --git a/src/helpers/host.rs b/src/helpers/host.rs index 7650873..f55956d 100644 --- a/src/helpers/host.rs +++ b/src/helpers/host.rs @@ -11,13 +11,16 @@ pub fn get_host_info() -> String { } fn model_to_name(model: &str) -> Option { - let version = if model.starts_with("Mac") && !model.starts_with("MacBook") && !model.starts_with("Macmini") && !model.starts_with("MacPro") { + let version = if model.starts_with("Mac") + && !model.starts_with("MacBook") + && !model.starts_with("Macmini") + && !model.starts_with("MacPro") + { Some(model.strip_prefix("Mac")?) } else { None }; - // Database stolen from https://github.com/fastfetch-cli/fastfetch/blob/dev/src/detection/host/host_mac.c // Macbook Pro: https://support.apple.com/en-us/HT201300 // Macbook Air: https://support.apple.com/en-us/HT201862 @@ -26,80 +29,86 @@ fn model_to_name(model: &str) -> Option { // Mac Pro: https://support.apple.com/en-us/HT202888 // Mac Studio: https://support.apple.com/en-us/HT213073 if let Some(v) = version { - return Some(match v { - // MacBook Air - "16,13" => "MacBook Air (15-inch, M4, 2025)", - "16,12" => "MacBook Air (13-inch, M4, 2025)", - "15,13" => "MacBook Air (15-inch, M3, 2024)", - "15,12" => "MacBook Air (13-inch, M3, 2024)", - "14,15" => "MacBook Air (15-inch, M2, 2023)", - "14,2" => "MacBook Air (M2, 2022)", - // MacBook Pro - "16,8" => "MacBook Pro (16-inch, M4 Max, 2024)", - "16,7" => "MacBook Pro (16-inch, M4 Pro, 2024)", - "16,6" => "MacBook Pro (14-inch, M4 Max, 2024)", - "16,5" => "MacBook Pro (14-inch, M4 Pro, 2024)", - "16,1" => "MacBook Pro (14-inch, M4, 2024)", - "15,11" => "MacBook Pro (16-inch, M3 Max, 2023)", - "15,9" => "MacBook Pro (16-inch, M3 Pro, 2023)", - "15,10" => "MacBook Pro (14-inch, M3 Max, 2023)", - "15,8" => "MacBook Pro (14-inch, M3 Pro, 2023)", - "15,6" | "15,7" => "MacBook Pro (16-inch, M2 Max, 2023)", - "15,3" => "MacBook Pro (14-inch, M2 Max, 2023)", - "14,10" | "14,6" => "MacBook Pro (16-inch, M2 Pro/Max, 2023)", - "14,9" | "14,5" => "MacBook Pro (14-inch, M2 Pro/Max, 2023)", - "14,7" => "MacBook Pro (13-inch, M2, 2022)", - // Mac Studio - "14,14" => "Mac Studio (M2 Ultra, 2023)", - "14,13" => "Mac Studio (M2 Max, 2023)", - "13,2" => "Mac Studio (M1 Ultra, 2022)", - "13,1" => "Mac Studio (M1 Max, 2022)", - // Mac mini - "16,10" => "Mac mini (M4, 2024)", - "16,3" => "Mac mini (M4 Pro, 2024)", - "14,12" => "Mac mini (M2 Pro, 2023)", - "14,3" => "Mac mini (M2, 2023)", - // Mac Pro - "14,8" => "Mac Pro (M2 Ultra, 2023)", - // iMac - "16,2" => "iMac (24-inch, M4, 2024)", - "15,4" | "15,5" => "iMac (24-inch, M3, 2023)", - _ => return None, - }.to_string()); + return Some( + match v { + // MacBook Air + "16,13" => "MacBook Air (15-inch, M4, 2025)", + "16,12" => "MacBook Air (13-inch, M4, 2025)", + "15,13" => "MacBook Air (15-inch, M3, 2024)", + "15,12" => "MacBook Air (13-inch, M3, 2024)", + "14,15" => "MacBook Air (15-inch, M2, 2023)", + "14,2" => "MacBook Air (M2, 2022)", + // MacBook Pro + "16,8" => "MacBook Pro (16-inch, M4 Max, 2024)", + "16,7" => "MacBook Pro (16-inch, M4 Pro, 2024)", + "16,6" => "MacBook Pro (14-inch, M4 Max, 2024)", + "16,5" => "MacBook Pro (14-inch, M4 Pro, 2024)", + "16,1" => "MacBook Pro (14-inch, M4, 2024)", + "15,11" => "MacBook Pro (16-inch, M3 Max, 2023)", + "15,9" => "MacBook Pro (16-inch, M3 Pro, 2023)", + "15,10" => "MacBook Pro (14-inch, M3 Max, 2023)", + "15,8" => "MacBook Pro (14-inch, M3 Pro, 2023)", + "15,6" | "15,7" => "MacBook Pro (16-inch, M2 Max, 2023)", + "15,3" => "MacBook Pro (14-inch, M2 Max, 2023)", + "14,10" | "14,6" => "MacBook Pro (16-inch, M2 Pro/Max, 2023)", + "14,9" | "14,5" => "MacBook Pro (14-inch, M2 Pro/Max, 2023)", + "14,7" => "MacBook Pro (13-inch, M2, 2022)", + // Mac Studio + "14,14" => "Mac Studio (M2 Ultra, 2023)", + "14,13" => "Mac Studio (M2 Max, 2023)", + "13,2" => "Mac Studio (M1 Ultra, 2022)", + "13,1" => "Mac Studio (M1 Max, 2022)", + // Mac mini + "16,10" => "Mac mini (M4, 2024)", + "16,3" => "Mac mini (M4 Pro, 2024)", + "14,12" => "Mac mini (M2 Pro, 2023)", + "14,3" => "Mac mini (M2, 2023)", + // Mac Pro + "14,8" => "Mac Pro (M2 Ultra, 2023)", + // iMac + "16,2" => "iMac (24-inch, M4, 2024)", + "15,4" | "15,5" => "iMac (24-inch, M3, 2023)", + _ => return None, + } + .to_string(), + ); } // Older Macs with specific prefixes - Some(match model { - // MacBook Air (Intel/M1) - "MacBookAir10,1" => "MacBook Air (M1, 2020)", - "MacBookAir9,1" => "MacBook Air (Retina, 13-inch, 2020)", - "MacBookAir8,2" => "MacBook Air (Retina, 13-inch, 2019)", - "MacBookAir8,1" => "MacBook Air (Retina, 13-inch, 2018)", - // MacBook Pro (Intel/M1) - "MacBookPro18,4" => "MacBook Pro (14-inch, M1 Max, 2021)", - "MacBookPro18,3" => "MacBook Pro (14-inch, M1 Pro, 2021)", - "MacBookPro18,2" => "MacBook Pro (16-inch, M1 Max, 2021)", - "MacBookPro18,1" => "MacBook Pro (16-inch, M1 Pro, 2021)", - "MacBookPro17,1" => "MacBook Pro (13-inch, M1, 2020)", - "MacBookPro16,4" => "MacBook Pro (16-inch, 2019)", - "MacBookPro16,3" => "MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)", - "MacBookPro16,2" => "MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)", - "MacBookPro16,1" => "MacBook Pro (16-inch, 2019)", - "MacBookPro15,4" => "MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)", - "MacBookPro15,3" => "MacBook Pro (15-inch, 2019)", - "MacBookPro15,2" => "MacBook Pro (13-inch, 2018/2019, Four Thunderbolt 3 ports)", - "MacBookPro15,1" => "MacBook Pro (15-inch, 2018/2019)", - // Mac mini - "Macmini9,1" => "Mac mini (M1, 2020)", - "Macmini8,1" => "Mac mini (2018)", - // iMac - "iMac21,2" | "iMac21,1" => "iMac (24-inch, M1, 2021)", - "iMac20,2" | "iMac20,1" => "iMac (Retina 5K, 27-inch, 2020)", - "iMac19,2" => "iMac (Retina 4K, 21.5-inch, 2019)", - "iMac19,1" => "iMac (Retina 5K, 27-inch, 2019)", - // Mac Pro - "MacPro7,1" => "Mac Pro (2019)", - "MacPro6,1" => "Mac Pro (Late 2013)", - _ => return None, - }.to_string()) + Some( + match model { + // MacBook Air (Intel/M1) + "MacBookAir10,1" => "MacBook Air (M1, 2020)", + "MacBookAir9,1" => "MacBook Air (Retina, 13-inch, 2020)", + "MacBookAir8,2" => "MacBook Air (Retina, 13-inch, 2019)", + "MacBookAir8,1" => "MacBook Air (Retina, 13-inch, 2018)", + // MacBook Pro (Intel/M1) + "MacBookPro18,4" => "MacBook Pro (14-inch, M1 Max, 2021)", + "MacBookPro18,3" => "MacBook Pro (14-inch, M1 Pro, 2021)", + "MacBookPro18,2" => "MacBook Pro (16-inch, M1 Max, 2021)", + "MacBookPro18,1" => "MacBook Pro (16-inch, M1 Pro, 2021)", + "MacBookPro17,1" => "MacBook Pro (13-inch, M1, 2020)", + "MacBookPro16,4" => "MacBook Pro (16-inch, 2019)", + "MacBookPro16,3" => "MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)", + "MacBookPro16,2" => "MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)", + "MacBookPro16,1" => "MacBook Pro (16-inch, 2019)", + "MacBookPro15,4" => "MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)", + "MacBookPro15,3" => "MacBook Pro (15-inch, 2019)", + "MacBookPro15,2" => "MacBook Pro (13-inch, 2018/2019, Four Thunderbolt 3 ports)", + "MacBookPro15,1" => "MacBook Pro (15-inch, 2018/2019)", + // Mac mini + "Macmini9,1" => "Mac mini (M1, 2020)", + "Macmini8,1" => "Mac mini (2018)", + // iMac + "iMac21,2" | "iMac21,1" => "iMac (24-inch, M1, 2021)", + "iMac20,2" | "iMac20,1" => "iMac (Retina 5K, 27-inch, 2020)", + "iMac19,2" => "iMac (Retina 4K, 21.5-inch, 2019)", + "iMac19,1" => "iMac (Retina 5K, 27-inch, 2019)", + // Mac Pro + "MacPro7,1" => "Mac Pro (2019)", + "MacPro6,1" => "Mac Pro (Late 2013)", + _ => return None, + } + .to_string(), + ) } diff --git a/src/helpers/ip.rs b/src/helpers/ip.rs index deadd32..5810e31 100644 --- a/src/helpers/ip.rs +++ b/src/helpers/ip.rs @@ -3,25 +3,21 @@ use std::process::Command; pub fn get_ip_info() -> String { let mut interface = "en0".to_string(); - let route_output = Command::new("route") - .args(["get", "default"]) - .output(); + let route_output = Command::new("route").args(["get", "default"]).output(); if let Ok(output) = route_output { let stdout = String::from_utf8_lossy(&output.stdout); for line in stdout.lines() { - if line.trim().starts_with("interface:") { - if let Some(iface) = line.split_whitespace().nth(1) { - interface = iface.to_string(); - break; - } + if line.trim().starts_with("interface:") + && let Some(iface) = line.split_whitespace().nth(1) + { + interface = iface.to_string(); + break; } } } - let ifconfig_output = Command::new("ifconfig") - .arg(&interface) - .output(); + let ifconfig_output = Command::new("ifconfig").arg(&interface).output(); if let Ok(output) = ifconfig_output { let stdout = String::from_utf8_lossy(&output.stdout); @@ -32,15 +28,15 @@ pub fn get_ip_info() -> String { let ip = parts[1]; let mut ip_with_cidr = ip.to_string(); - if let Some(netmask_idx) = parts.iter().position(|&x| x == "netmask") { - if netmask_idx + 1 < parts.len() { - let netmask_hex = parts[netmask_idx + 1]; - if netmask_hex.starts_with("0x") { - if let Ok(num) = u32::from_str_radix(&netmask_hex[2..], 16) { - let cidr = num.count_ones(); - ip_with_cidr = format!("{}/{}", ip, cidr); - } - } + if let Some(netmask_idx) = parts.iter().position(|&x| x == "netmask") + && netmask_idx + 1 < parts.len() + { + let netmask_hex = parts[netmask_idx + 1]; + if netmask_hex.starts_with("0x") + && let Ok(num) = u32::from_str_radix(&netmask_hex[2..], 16) + { + let cidr = num.count_ones(); + ip_with_cidr = format!("{}/{}", ip, cidr); } } @@ -52,4 +48,3 @@ pub fn get_ip_info() -> String { "".to_string() } - diff --git a/src/helpers/locale.rs b/src/helpers/locale.rs index 6d53e02..ac297d8 100644 --- a/src/helpers/locale.rs +++ b/src/helpers/locale.rs @@ -1,18 +1,17 @@ use std::env; pub fn get_locale_info() -> String { - if let Ok(locale) = env::var("LC_ALL") { - if !locale.is_empty() { - return locale; - } + if let Ok(locale) = env::var("LC_ALL") + && !locale.is_empty() + { + return locale; } - if let Ok(locale) = env::var("LANG") { - if !locale.is_empty() { - return locale; - } + if let Ok(locale) = env::var("LANG") + && !locale.is_empty() + { + return locale; } "".to_string() } - diff --git a/src/helpers/memory.rs b/src/helpers/memory.rs index a4bce4c..aee3931 100644 --- a/src/helpers/memory.rs +++ b/src/helpers/memory.rs @@ -74,6 +74,8 @@ pub fn get_memory_info() -> String { format!( "{:.2} GiB / {:.2} GiB ({})", - used_gib, total_gib, crate::output::colors::percent(percentage) + used_gib, + total_gib, + crate::output::colors::percent(percentage) ) } diff --git a/src/helpers/shell.rs b/src/helpers/shell.rs index bfe72bf..4d76aa8 100644 --- a/src/helpers/shell.rs +++ b/src/helpers/shell.rs @@ -3,8 +3,9 @@ use std::process::Command; pub fn get_shell_info() -> String { let shell_path = env::var("SHELL").unwrap_or_else(|_| "unknown".to_string()); - let shell_name = shell_path.split('/').last().unwrap_or("unknown"); - let version = Command::new(&shell_path) + let shell_name = shell_path.split('/').next_back().unwrap_or("unknown"); + + Command::new(&shell_path) .arg("--version") .output() .map(|output| { @@ -16,7 +17,5 @@ pub fn get_shell_info() -> String { .collect::>() .join(" ") }) - .unwrap_or_else(|_| shell_name.to_string()); - - version + .unwrap_or_else(|_| shell_name.to_string()) } diff --git a/src/helpers/storage.rs b/src/helpers/storage.rs index 423cf41..9ea4158 100644 --- a/src/helpers/storage.rs +++ b/src/helpers/storage.rs @@ -1,6 +1,6 @@ // https://github.com/fastfetch-cli/fastfetch/blob/dev/src/detection/disk/disk.c -use libc::{c_int, c_char}; +use libc::{c_char, c_int}; use std::ffi::CStr; #[repr(C)] @@ -79,7 +79,9 @@ pub fn get_storage_info() -> String { let mut result = format!( "{:.2} GiB / {:.2} GiB ({})", - used_gib, total_gib, crate::output::colors::percent(percentage) + used_gib, + total_gib, + crate::output::colors::percent(percentage) ); if !filesystem.is_empty() { @@ -97,4 +99,3 @@ pub fn get_storage_info() -> String { "".to_string() } - diff --git a/src/helpers/swap.rs b/src/helpers/swap.rs index 7ebd8af..35a651d 100644 --- a/src/helpers/swap.rs +++ b/src/helpers/swap.rs @@ -12,13 +12,13 @@ pub fn get_swap_info() -> String { let mut used_mb = 0.0; for part in stdout.split_whitespace() { - if let Some(val) = part.strip_suffix('M') { - if let Ok(num) = val.parse::() { - if stdout.contains(&format!("total = {}", part)) { - total_mb = num; - } else if stdout.contains(&format!("used = {}", part)) { - used_mb = num; - } + if let Some(val) = part.strip_suffix('M') + && let Ok(num) = val.parse::() + { + if stdout.contains(&format!("total = {}", part)) { + total_mb = num; + } else if stdout.contains(&format!("used = {}", part)) { + used_mb = num; } } } @@ -33,7 +33,9 @@ pub fn get_swap_info() -> String { return format!( "{:.2} GiB / {:.2} GiB ({})", - used_gib, total_gib, crate::output::colors::percent(percentage) + used_gib, + total_gib, + crate::output::colors::percent(percentage) ); } diff --git a/src/helpers/terminal.rs b/src/helpers/terminal.rs index 1594414..3cd76a1 100644 --- a/src/helpers/terminal.rs +++ b/src/helpers/terminal.rs @@ -26,12 +26,11 @@ pub fn get_terminal_info() -> String { let my_pid = sysinfo::get_current_pid().unwrap_or(sysinfo::Pid::from(0)); - if let Some(process) = sys.process(my_pid) { - if let Some(parent_pid) = process.parent() { - if let Some(parent_proc) = sys.process(parent_pid) { - return parent_proc.name().to_string_lossy().replace(".app", ""); - } - } + if let Some(process) = sys.process(my_pid) + && let Some(parent_pid) = process.parent() + && let Some(parent_proc) = sys.process(parent_pid) + { + return parent_proc.name().to_string_lossy().replace(".app", ""); } "unknown".to_string() diff --git a/src/helpers/wm.rs b/src/helpers/wm.rs index bdc7651..0fec2be 100644 --- a/src/helpers/wm.rs +++ b/src/helpers/wm.rs @@ -15,30 +15,25 @@ pub fn get_window_manager_info() -> DisplayServerResult { if cfg!(target_os = "macos") { let plist_path = "/System/Library/CoreServices/WindowManager.app/Contents/version.plist"; - if Path::new(plist_path).exists() { - if let Ok(value) = Value::from_file(plist_path) { - if let Some(dict) = value.as_dictionary() { - if let Some(raw_version) = dict.get("SourceVersion").and_then(|v| v.as_string()) - { - // Apple format: AAAABBBCCDDDDDD (Major, Minor, Patch, Build) - if raw_version.len() >= 8 && raw_version.chars().all(|c| c.is_numeric()) { - let major = - raw_version[..raw_version.len() - 12].trim_start_matches('0'); - let minor = raw_version[raw_version.len() - 12..raw_version.len() - 9] - .trim_start_matches('0'); - let patch = raw_version[raw_version.len() - 9..raw_version.len() - 7] - .trim_start_matches('0'); + if Path::new(plist_path).exists() + && let Ok(value) = Value::from_file(plist_path) + && let Some(dict) = value.as_dictionary() + && let Some(raw_version) = dict.get("SourceVersion").and_then(|v| v.as_string()) + { + // Apple format: AAAABBBCCDDDDDD (Major, Minor, Patch, Build) + if raw_version.len() >= 8 && raw_version.chars().all(|c| c.is_numeric()) { + let major = raw_version[..raw_version.len() - 12].trim_start_matches('0'); + let minor = raw_version[raw_version.len() - 12..raw_version.len() - 9] + .trim_start_matches('0'); + let patch = raw_version[raw_version.len() - 9..raw_version.len() - 7] + .trim_start_matches('0'); - let m = if minor.is_empty() { "0" } else { minor }; - let p = if patch.is_empty() { "0" } else { patch }; + let m = if minor.is_empty() { "0" } else { minor }; + let p = if patch.is_empty() { "0" } else { patch }; - result.wm_pretty_name = - format!("Quartz Compositor {}.{}.{}", major, m, p); - } else { - result.wm_pretty_name = format!("Quartz Compositor {}", raw_version); - } - } - } + result.wm_pretty_name = format!("Quartz Compositor {}.{}.{}", major, m, p); + } else { + result.wm_pretty_name = format!("Quartz Compositor {}", raw_version); } } } diff --git a/src/helpers/wm_theme.rs b/src/helpers/wm_theme.rs index c0c9ab2..80c8ab3 100644 --- a/src/helpers/wm_theme.rs +++ b/src/helpers/wm_theme.rs @@ -11,28 +11,28 @@ pub fn get_wm_theme_info() -> String { let mut accent_name = "Multicolor".to_string(); let mut appearance = "Light".to_string(); - if let Ok(value) = Value::from_file(path) { - if let Some(dict) = value.as_dictionary() { - if let Some(accent_val) = dict - .get("AppleAccentColor") - .and_then(|v| v.as_signed_integer()) - { - accent_name = match accent_val { - -1 => "Graphite".to_string(), - 0 => "Red".to_string(), - 1 => "Orange".to_string(), - 2 => "Yellow".to_string(), - 3 => "Green".to_string(), - 4 => "Blue".to_string(), - 5 => "Purple".to_string(), - 6 => "Pink".to_string(), - _ => "Multicolor".to_string(), - }; - } + if let Ok(value) = Value::from_file(path) + && let Some(dict) = value.as_dictionary() + { + if let Some(accent_val) = dict + .get("AppleAccentColor") + .and_then(|v| v.as_signed_integer()) + { + accent_name = match accent_val { + -1 => "Graphite".to_string(), + 0 => "Red".to_string(), + 1 => "Orange".to_string(), + 2 => "Yellow".to_string(), + 3 => "Green".to_string(), + 4 => "Blue".to_string(), + 5 => "Purple".to_string(), + 6 => "Pink".to_string(), + _ => "Multicolor".to_string(), + }; + } - if let Some(style) = dict.get("AppleInterfaceStyle").and_then(|v| v.as_string()) { - appearance = style.to_string(); // Usually "Dark" - } + if let Some(style) = dict.get("AppleInterfaceStyle").and_then(|v| v.as_string()) { + appearance = style.to_string(); // Usually "Dark" } } diff --git a/src/main.rs b/src/main.rs index 7e2f6bc..4c0a014 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ // neoarz // neo64fetch - "jarvis, rewrite this project in rust" -use std::env; use sysinfo::System; mod helpers; @@ -41,7 +40,6 @@ struct Stats { architecture: String, // appended to os } - fn get_system_stats() -> Stats { let mut sys = System::new_all(); sys.refresh_all(); @@ -82,7 +80,6 @@ fn get_system_stats() -> Stats { } } - fn print_stats(stats: &Stats, offset: usize) { let mut lines = Vec::new(); @@ -90,10 +87,15 @@ fn print_stats(stats: &Stats, offset: usize) { lines.push(colors::title(&stats.username, &stats.hostname)); // separator - lines.push(colors::separator(stats.username.len() + stats.hostname.len() + 1)); + lines.push(colors::separator( + stats.username.len() + stats.hostname.len() + 1, + )); // info - lines.push(colors::info("OS", &format!("{} {}", stats.os, stats.architecture))); + lines.push(colors::info( + "OS", + &format!("{} {}", stats.os, stats.architecture), + )); lines.push(colors::info("Host", &stats.host)); lines.push(colors::info("Kernel", &stats.kernel)); lines.push(colors::info("Uptime", &stats.uptime)); @@ -113,7 +115,10 @@ fn print_stats(stats: &Stats, offset: usize) { lines.push(colors::info("Swap", &stats.swap)); lines.push(colors::info("Disk (/)", &stats.storage)); // lines.push(colors::info("Local IP", &stats.ip)); - lines.push(colors::info(&format!("Battery {}", stats.battery.0), &stats.battery.1)); + lines.push(colors::info( + &format!("Battery {}", stats.battery.0), + &stats.battery.1, + )); // lines.push(colors::info("Locale", &stats.locale)); // color blocks @@ -127,12 +132,10 @@ fn print_stats(stats: &Stats, offset: usize) { } } - - fn main() { - let stats = get_system_stats(); + let stats = get_system_stats(); let (offset, img_rows) = image::print_image_and_setup("assets/logo.png", 700); - // ^^^ size of the image change it here + // ^^^ size of the image change it here print_stats(&stats, offset); image::finish_printing(offset, 24, img_rows); -} \ No newline at end of file +} diff --git a/src/output/image.rs b/src/output/image.rs index d099e81..5d67ccf 100644 --- a/src/output/image.rs +++ b/src/output/image.rs @@ -1,14 +1,14 @@ // Kitty Graphics Protocol implementation for terminal image display -// -// Inspired ~~stolen~~ by swiftfetch's implementation: +// +// Inspired ~~stolen~~ by swiftfetch's implementation: // https://github.com/Ly-sec/swiftfetch/blob/main/src/display.rs -// +// // Images are base64-encoded and chunked copying what swiftfetch does // Compatible terminals: Any terminals which use Kitty protocol, like Ghostty, Kitty, Wezterm -use base64::{engine::general_purpose::STANDARD as BASE64, Engine}; +use base64::{Engine, engine::general_purpose::STANDARD as BASE64}; use image::{GenericImageView, ImageFormat}; -use libc::{ioctl, winsize, STDOUT_FILENO, TIOCGWINSZ}; +use libc::{STDOUT_FILENO, TIOCGWINSZ, ioctl, winsize}; use std::env; use std::io::{Cursor, Write}; use std::mem; @@ -27,11 +27,11 @@ const DEFAULT_GAP_COLUMNS: usize = 2; // See: https://github.com/Ly-sec/swiftfetch/blob/main/src/display.rs#L557 const CHUNK_SIZE: usize = 4096; -// Detects Kitty Graphics Protocol support via environment variables. -// +// Detects Kitty Graphics Protocol support via environment variables. +// // See: https://github.com/Ly-sec/swiftfetch/blob/main/src/display.rs#L422-L460 -// -// Returns false for unsupported terminals +// +// Returns false for unsupported terminals // Right now it just doenst print anything pub fn terminal_supports_kitty() -> bool { if matches!( @@ -41,8 +41,12 @@ pub fn terminal_supports_kitty() -> bool { return true; } - if env::var("KITTY_WINDOW_ID").is_ok() { return true; } - if env::var("WEZTERM_PANE").is_ok() { return true; } + if env::var("KITTY_WINDOW_ID").is_ok() { + return true; + } + if env::var("WEZTERM_PANE").is_ok() { + return true; + } if let Ok(term_program) = env::var("TERM_PROGRAM") { let t = term_program.to_lowercase(); @@ -51,22 +55,26 @@ pub fn terminal_supports_kitty() -> bool { } } - if let Ok(term) = env::var("TERM") { - if term.to_lowercase().contains("kitty") { return true; } + if let Ok(term) = env::var("TERM") + && term.to_lowercase().contains("kitty") + { + return true; } false } // Queries terminal for character cell dimensions using ioctl(TIOCGWINSZ). -// +// // See: https://github.com/Ly-sec/swiftfetch/blob/main/src/display.rs#L462-L477 fn terminal_cell_metrics() -> (f32, f32) { unsafe { let mut ws: winsize = mem::zeroed(); - if ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut ws) == 0 - && ws.ws_col > 0 && ws.ws_row > 0 - && ws.ws_xpixel > 0 && ws.ws_ypixel > 0 + if ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut ws) == 0 + && ws.ws_col > 0 + && ws.ws_row > 0 + && ws.ws_xpixel > 0 + && ws.ws_ypixel > 0 { return ( ws.ws_xpixel as f32 / ws.ws_col as f32, @@ -80,13 +88,13 @@ fn terminal_cell_metrics() -> (f32, f32) { // Loads, resizes, and displays an image via Kitty Graphics Protocol. // Loading Logic: // See: https://github.com/Ly-sec/swiftfetch/blob/main/src/display.rs#L479-L527 -// +// // Resize logic: // See: https://github.com/Ly-sec/swiftfetch/blob/main/src/display.rs#L530-L545 -// +// // Transmission logic: // See: https://github.com/Ly-sec/swiftfetch/blob/main/src/display.rs#L547-L578 -// +// // Returns (column_offset, total_rows) for side-by-side text printing. // Returns (0, 0) on failure; unsupported terminal or image load error (skill issue) pub fn print_image_and_setup(path: &str, target_height: u32) -> (usize, usize) { @@ -109,7 +117,10 @@ pub fn print_image_and_setup(path: &str, target_height: u32) -> (usize, usize) { // Kitty protocol requires PNG format, even for JPEG/WebP sources // See: https://github.com/Ly-sec/swiftfetch/blob/main/src/display.rs#L495-L501 let mut png_bytes = Vec::new(); - if image.write_to(&mut Cursor::new(&mut png_bytes), ImageFormat::Png).is_err() { + if image + .write_to(&mut Cursor::new(&mut png_bytes), ImageFormat::Png) + .is_err() + { return (0, 0); } @@ -124,7 +135,10 @@ pub fn print_image_and_setup(path: &str, target_height: u32) -> (usize, usize) { let more = if end < encoded.len() { 1 } else { 0 }; if first { - output.push_str(&format!("\x1b_Ga=T,f=100,s={},v={},m={};", width, height, more)); + output.push_str(&format!( + "\x1b_Ga=T,f=100,s={},v={},m={};", + width, height, more + )); first = false; } else { output.push_str(&format!("\x1b_Gm={};", more)); @@ -150,38 +164,42 @@ pub fn print_image_and_setup(path: &str, target_height: u32) -> (usize, usize) { // use cursor positioning to place image // swiftfetch uses a different approach with save/restore but lowk didnt work for me // https://github.com/Ly-sec/swiftfetch/blob/main/src/display.rs#L225-L253 - print!("\x1b[{}A", total_rows); - + print!("\x1b[{}A", total_rows); + if padding_top > 0 { - print!("\x1b[{}B", padding_top); + print!("\x1b[{}B", padding_top); } - - print!("\x1b[s"); - print!("{}", output); + + print!("\x1b[s"); + print!("{}", output); std::io::stdout().flush().ok(); // just a silly caption lolol let image_width_cols = cols - DEFAULT_GAP_COLUMNS; - + let text = "a creeper made this"; let text_len = 16; - let pad = if image_width_cols > text_len { (image_width_cols - text_len) / 2 } else { 0 }; + let pad = if image_width_cols > text_len { + (image_width_cols - text_len) / 2 + } else { + 0 + }; print!("\x1b[{}B", rows); - print!("\r\x1b[{}C{}", pad, text); + print!("\r\x1b[{}C{}", pad, text); + + print!("\x1b[u"); - print!("\x1b[u"); - if padding_top > 0 { - print!("\x1b[{}A", padding_top); + print!("\x1b[{}A", padding_top); } std::io::stdout().flush().ok(); (cols, total_rows + caption_rows) } -// Prints text at a horizontal offset for side-by-side layout with image. -// -// swiftfetch uses space padding instead of cursor movement: +// Prints text at a horizontal offset for side-by-side layout with image. +// +// swiftfetch uses space padding instead of cursor movement: // See: https://github.com/Ly-sec/swiftfetch/blob/main/src/display.rs#L236-L245 pub fn print_with_offset(offset: usize, text: &str) { if offset > 0 { @@ -192,7 +210,7 @@ pub fn print_with_offset(offset: usize, text: &str) { } // Fills remaining vertical space if text is shorter than image height. -// +// // Called after all info lines are printed to make sure the image is not cut off. // See: https://github.com/Ly-sec/swiftfetch/blob/main/src/display.rs#L338-L348 pub fn finish_printing(offset: usize, lines_printed: usize, image_rows: usize) {