chore: clippy & fmt

This commit is contained in:
neoarz
2026-01-07 22:35:41 -05:00
parent ef666c53e5
commit fd7da43393
16 changed files with 322 additions and 284 deletions

View File

@@ -45,19 +45,19 @@ pub fn get_battery_info() -> (String, String) {
let value = value_part.trim_matches(';').trim(); let value = value_part.trim_matches(';').trim();
is_charging = value == "Yes"; is_charging = value == "Yes";
} }
} else if line.contains("\"AvgTimeToEmpty\"") { } else if line.contains("\"AvgTimeToEmpty\"")
if let Some(equals_pos) = line.find('=') { && let Some(equals_pos) = line.find('=')
let value_part = &line[equals_pos + 1..].trim(); {
let value = value_part.trim_matches(';').trim(); let value_part = &line[equals_pos + 1..].trim();
if let Ok(time) = value.parse::<i32>() { let value = value_part.trim_matches(';').trim();
avg_time_to_empty = Some(time); if let Ok(time) = value.parse::<i32>() {
} avg_time_to_empty = Some(time);
} }
} }
} }
let percentage = if let Some(capacity) = current_capacity { let percentage = if let Some(capacity) = current_capacity {
if capacity >= 0 && capacity <= 100 { if (0..=100).contains(&capacity) {
capacity as u32 capacity as u32
} else { } else {
return (format!("({})", device_name), "<unknown>".to_string()); return (format!("({})", device_name), "<unknown>".to_string());
@@ -76,20 +76,21 @@ pub fn get_battery_info() -> (String, String) {
let mut result = crate::output::colors::battery_percent(percentage); let mut result = crate::output::colors::battery_percent(percentage);
if !external_connected && !is_charging { if !external_connected
if let Some(time_mins) = avg_time_to_empty { && !is_charging
if time_mins > 0 && time_mins < 0xFFFF { && let Some(time_mins) = avg_time_to_empty
let hours = time_mins / 60; && time_mins > 0
let mins = time_mins % 60; && time_mins < 0xFFFF
{
let hours = time_mins / 60;
let mins = time_mins % 60;
if hours > 0 && mins > 0 { if hours > 0 && mins > 0 {
result.push_str(&format!(" ({} hours, {} mins remaining)", hours, mins)); result.push_str(&format!(" ({} hours, {} mins remaining)", hours, mins));
} else if hours > 0 { } else if hours > 0 {
result.push_str(&format!(" ({} hours remaining)", hours)); result.push_str(&format!(" ({} hours remaining)", hours));
} else if mins > 0 { } else if mins > 0 {
result.push_str(&format!(" ({} mins remaining)", mins)); result.push_str(&format!(" ({} mins remaining)", mins));
}
}
} }
} }
@@ -97,4 +98,3 @@ pub fn get_battery_info() -> (String, String) {
(format!("({})", device_name), result) (format!("({})", device_name), result)
} }

View File

@@ -12,45 +12,53 @@ pub fn get_cursor_info() -> String {
let mut outline = "White".to_string(); let mut outline = "White".to_string();
let mut size = "32".to_string(); let mut size = "32".to_string();
if let Ok(value) = Value::from_file(path) { if let Ok(value) = Value::from_file(path)
if let Some(dict) = value.as_dictionary() { && 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; if let Some(f_dict) = dict.get("cursorFill").and_then(|v| v.as_dictionary()) {
let g = (f_dict.get("green").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; let r =
let b = (f_dict.get("blue").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; (f_dict.get("red").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 g =
let color_hex = (r << 24) | (g << 16) | (b << 8) | a; (f_dict.get("green").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32;
fill = match color_hex { let b =
0x000000FF => "Black".to_string(), (f_dict.get("blue").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32;
0xFFFFFFFF => "White".to_string(), let a =
0xFF2600FF => "Red".to_string(), (f_dict.get("alpha").and_then(|v| v.as_real()).unwrap_or(1.0) * 255.0 + 0.5) as u32;
0x0433FFFF => "Blue".to_string(), let color_hex = (r << 24) | (g << 16) | (b << 8) | a;
0x00F900FF => "Green".to_string(), fill = match color_hex {
0xFFFB00FF => "Yellow".to_string(), 0x000000FF => "Black".to_string(),
_ => format!("#{:08X}", color_hex), 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()) { 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 r =
let g = (o_dict.get("green").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32; (o_dict.get("red").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 g =
let a = (o_dict.get("alpha").and_then(|v| v.as_real()).unwrap_or(1.0) * 255.0 + 0.5) as u32; (o_dict.get("green").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32;
let color_hex = (r << 24) | (g << 16) | (b << 8) | a; let b =
outline = match color_hex { (o_dict.get("blue").and_then(|v| v.as_real()).unwrap_or(0.0) * 255.0 + 0.5) as u32;
0x000000FF => "Black".to_string(), let a =
0xFFFFFFFF => "White".to_string(), (o_dict.get("alpha").and_then(|v| v.as_real()).unwrap_or(1.0) * 255.0 + 0.5) as u32;
0xFF2600FF => "Red".to_string(), let color_hex = (r << 24) | (g << 16) | (b << 8) | a;
0x0433FFFF => "Blue".to_string(), outline = match color_hex {
0x00F900FF => "Green".to_string(), 0x000000FF => "Black".to_string(),
0xFFFB00FF => "Yellow".to_string(), 0xFFFFFFFF => "White".to_string(),
_ => format!("#{:08X}", color_hex), 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()) { if let Some(s_val) = dict.get("mouseDriverCursorSize").and_then(|v| v.as_real()) {
size = format!("{:.0}", s_val * 32.0); size = format!("{:.0}", s_val * 32.0);
}
} }
} }

View File

@@ -18,10 +18,20 @@ pub fn get_display_info() -> String {
}; };
if display_count > 1 { 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!( format!(
"({}) {}x{} @ {}x in {}\", {} Hz {}", "({}) {}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 { } else {
format!( format!(

View File

@@ -20,9 +20,7 @@ pub fn get_gpu_info() -> String {
.nth(1) .nth(1)
.unwrap_or("") .unwrap_or("")
.trim() .trim()
.replace('"', "") .replace(['"', '<', '>'], "");
.replace('<', "")
.replace('>', "");
} }
if line.contains("\"gpu-core-count\"") { if line.contains("\"gpu-core-count\"") {
cores = line.split('=').nth(1).unwrap_or("").trim().to_string(); cores = line.split('=').nth(1).unwrap_or("").trim().to_string();

View File

@@ -11,13 +11,16 @@ pub fn get_host_info() -> String {
} }
fn model_to_name(model: &str) -> Option<String> { fn model_to_name(model: &str) -> Option<String> {
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")?) Some(model.strip_prefix("Mac")?)
} else { } else {
None None
}; };
// Database stolen from https://github.com/fastfetch-cli/fastfetch/blob/dev/src/detection/host/host_mac.c // 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 Pro: https://support.apple.com/en-us/HT201300
// Macbook Air: https://support.apple.com/en-us/HT201862 // Macbook Air: https://support.apple.com/en-us/HT201862
@@ -26,80 +29,86 @@ fn model_to_name(model: &str) -> Option<String> {
// Mac Pro: https://support.apple.com/en-us/HT202888 // Mac Pro: https://support.apple.com/en-us/HT202888
// Mac Studio: https://support.apple.com/en-us/HT213073 // Mac Studio: https://support.apple.com/en-us/HT213073
if let Some(v) = version { if let Some(v) = version {
return Some(match v { return Some(
// MacBook Air match v {
"16,13" => "MacBook Air (15-inch, M4, 2025)", // MacBook Air
"16,12" => "MacBook Air (13-inch, M4, 2025)", "16,13" => "MacBook Air (15-inch, M4, 2025)",
"15,13" => "MacBook Air (15-inch, M3, 2024)", "16,12" => "MacBook Air (13-inch, M4, 2025)",
"15,12" => "MacBook Air (13-inch, M3, 2024)", "15,13" => "MacBook Air (15-inch, M3, 2024)",
"14,15" => "MacBook Air (15-inch, M2, 2023)", "15,12" => "MacBook Air (13-inch, M3, 2024)",
"14,2" => "MacBook Air (M2, 2022)", "14,15" => "MacBook Air (15-inch, M2, 2023)",
// MacBook Pro "14,2" => "MacBook Air (M2, 2022)",
"16,8" => "MacBook Pro (16-inch, M4 Max, 2024)", // MacBook Pro
"16,7" => "MacBook Pro (16-inch, M4 Pro, 2024)", "16,8" => "MacBook Pro (16-inch, M4 Max, 2024)",
"16,6" => "MacBook Pro (14-inch, M4 Max, 2024)", "16,7" => "MacBook Pro (16-inch, M4 Pro, 2024)",
"16,5" => "MacBook Pro (14-inch, M4 Pro, 2024)", "16,6" => "MacBook Pro (14-inch, M4 Max, 2024)",
"16,1" => "MacBook Pro (14-inch, M4, 2024)", "16,5" => "MacBook Pro (14-inch, M4 Pro, 2024)",
"15,11" => "MacBook Pro (16-inch, M3 Max, 2023)", "16,1" => "MacBook Pro (14-inch, M4, 2024)",
"15,9" => "MacBook Pro (16-inch, M3 Pro, 2023)", "15,11" => "MacBook Pro (16-inch, M3 Max, 2023)",
"15,10" => "MacBook Pro (14-inch, M3 Max, 2023)", "15,9" => "MacBook Pro (16-inch, M3 Pro, 2023)",
"15,8" => "MacBook Pro (14-inch, M3 Pro, 2023)", "15,10" => "MacBook Pro (14-inch, M3 Max, 2023)",
"15,6" | "15,7" => "MacBook Pro (16-inch, M2 Max, 2023)", "15,8" => "MacBook Pro (14-inch, M3 Pro, 2023)",
"15,3" => "MacBook Pro (14-inch, M2 Max, 2023)", "15,6" | "15,7" => "MacBook Pro (16-inch, M2 Max, 2023)",
"14,10" | "14,6" => "MacBook Pro (16-inch, M2 Pro/Max, 2023)", "15,3" => "MacBook Pro (14-inch, M2 Max, 2023)",
"14,9" | "14,5" => "MacBook Pro (14-inch, M2 Pro/Max, 2023)", "14,10" | "14,6" => "MacBook Pro (16-inch, M2 Pro/Max, 2023)",
"14,7" => "MacBook Pro (13-inch, M2, 2022)", "14,9" | "14,5" => "MacBook Pro (14-inch, M2 Pro/Max, 2023)",
// Mac Studio "14,7" => "MacBook Pro (13-inch, M2, 2022)",
"14,14" => "Mac Studio (M2 Ultra, 2023)", // Mac Studio
"14,13" => "Mac Studio (M2 Max, 2023)", "14,14" => "Mac Studio (M2 Ultra, 2023)",
"13,2" => "Mac Studio (M1 Ultra, 2022)", "14,13" => "Mac Studio (M2 Max, 2023)",
"13,1" => "Mac Studio (M1 Max, 2022)", "13,2" => "Mac Studio (M1 Ultra, 2022)",
// Mac mini "13,1" => "Mac Studio (M1 Max, 2022)",
"16,10" => "Mac mini (M4, 2024)", // Mac mini
"16,3" => "Mac mini (M4 Pro, 2024)", "16,10" => "Mac mini (M4, 2024)",
"14,12" => "Mac mini (M2 Pro, 2023)", "16,3" => "Mac mini (M4 Pro, 2024)",
"14,3" => "Mac mini (M2, 2023)", "14,12" => "Mac mini (M2 Pro, 2023)",
// Mac Pro "14,3" => "Mac mini (M2, 2023)",
"14,8" => "Mac Pro (M2 Ultra, 2023)", // Mac Pro
// iMac "14,8" => "Mac Pro (M2 Ultra, 2023)",
"16,2" => "iMac (24-inch, M4, 2024)", // iMac
"15,4" | "15,5" => "iMac (24-inch, M3, 2023)", "16,2" => "iMac (24-inch, M4, 2024)",
_ => return None, "15,4" | "15,5" => "iMac (24-inch, M3, 2023)",
}.to_string()); _ => return None,
}
.to_string(),
);
} }
// Older Macs with specific prefixes // Older Macs with specific prefixes
Some(match model { Some(
// MacBook Air (Intel/M1) match model {
"MacBookAir10,1" => "MacBook Air (M1, 2020)", // MacBook Air (Intel/M1)
"MacBookAir9,1" => "MacBook Air (Retina, 13-inch, 2020)", "MacBookAir10,1" => "MacBook Air (M1, 2020)",
"MacBookAir8,2" => "MacBook Air (Retina, 13-inch, 2019)", "MacBookAir9,1" => "MacBook Air (Retina, 13-inch, 2020)",
"MacBookAir8,1" => "MacBook Air (Retina, 13-inch, 2018)", "MacBookAir8,2" => "MacBook Air (Retina, 13-inch, 2019)",
// MacBook Pro (Intel/M1) "MacBookAir8,1" => "MacBook Air (Retina, 13-inch, 2018)",
"MacBookPro18,4" => "MacBook Pro (14-inch, M1 Max, 2021)", // MacBook Pro (Intel/M1)
"MacBookPro18,3" => "MacBook Pro (14-inch, M1 Pro, 2021)", "MacBookPro18,4" => "MacBook Pro (14-inch, M1 Max, 2021)",
"MacBookPro18,2" => "MacBook Pro (16-inch, M1 Max, 2021)", "MacBookPro18,3" => "MacBook Pro (14-inch, M1 Pro, 2021)",
"MacBookPro18,1" => "MacBook Pro (16-inch, M1 Pro, 2021)", "MacBookPro18,2" => "MacBook Pro (16-inch, M1 Max, 2021)",
"MacBookPro17,1" => "MacBook Pro (13-inch, M1, 2020)", "MacBookPro18,1" => "MacBook Pro (16-inch, M1 Pro, 2021)",
"MacBookPro16,4" => "MacBook Pro (16-inch, 2019)", "MacBookPro17,1" => "MacBook Pro (13-inch, M1, 2020)",
"MacBookPro16,3" => "MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)", "MacBookPro16,4" => "MacBook Pro (16-inch, 2019)",
"MacBookPro16,2" => "MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)", "MacBookPro16,3" => "MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)",
"MacBookPro16,1" => "MacBook Pro (16-inch, 2019)", "MacBookPro16,2" => "MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)",
"MacBookPro15,4" => "MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)", "MacBookPro16,1" => "MacBook Pro (16-inch, 2019)",
"MacBookPro15,3" => "MacBook Pro (15-inch, 2019)", "MacBookPro15,4" => "MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)",
"MacBookPro15,2" => "MacBook Pro (13-inch, 2018/2019, Four Thunderbolt 3 ports)", "MacBookPro15,3" => "MacBook Pro (15-inch, 2019)",
"MacBookPro15,1" => "MacBook Pro (15-inch, 2018/2019)", "MacBookPro15,2" => "MacBook Pro (13-inch, 2018/2019, Four Thunderbolt 3 ports)",
// Mac mini "MacBookPro15,1" => "MacBook Pro (15-inch, 2018/2019)",
"Macmini9,1" => "Mac mini (M1, 2020)", // Mac mini
"Macmini8,1" => "Mac mini (2018)", "Macmini9,1" => "Mac mini (M1, 2020)",
// iMac "Macmini8,1" => "Mac mini (2018)",
"iMac21,2" | "iMac21,1" => "iMac (24-inch, M1, 2021)", // iMac
"iMac20,2" | "iMac20,1" => "iMac (Retina 5K, 27-inch, 2020)", "iMac21,2" | "iMac21,1" => "iMac (24-inch, M1, 2021)",
"iMac19,2" => "iMac (Retina 4K, 21.5-inch, 2019)", "iMac20,2" | "iMac20,1" => "iMac (Retina 5K, 27-inch, 2020)",
"iMac19,1" => "iMac (Retina 5K, 27-inch, 2019)", "iMac19,2" => "iMac (Retina 4K, 21.5-inch, 2019)",
// Mac Pro "iMac19,1" => "iMac (Retina 5K, 27-inch, 2019)",
"MacPro7,1" => "Mac Pro (2019)", // Mac Pro
"MacPro6,1" => "Mac Pro (Late 2013)", "MacPro7,1" => "Mac Pro (2019)",
_ => return None, "MacPro6,1" => "Mac Pro (Late 2013)",
}.to_string()) _ => return None,
}
.to_string(),
)
} }

View File

@@ -3,25 +3,21 @@ use std::process::Command;
pub fn get_ip_info() -> String { pub fn get_ip_info() -> String {
let mut interface = "en0".to_string(); let mut interface = "en0".to_string();
let route_output = Command::new("route") let route_output = Command::new("route").args(["get", "default"]).output();
.args(["get", "default"])
.output();
if let Ok(output) = route_output { if let Ok(output) = route_output {
let stdout = String::from_utf8_lossy(&output.stdout); let stdout = String::from_utf8_lossy(&output.stdout);
for line in stdout.lines() { for line in stdout.lines() {
if line.trim().starts_with("interface:") { if line.trim().starts_with("interface:")
if let Some(iface) = line.split_whitespace().nth(1) { && let Some(iface) = line.split_whitespace().nth(1)
interface = iface.to_string(); {
break; interface = iface.to_string();
} break;
} }
} }
} }
let ifconfig_output = Command::new("ifconfig") let ifconfig_output = Command::new("ifconfig").arg(&interface).output();
.arg(&interface)
.output();
if let Ok(output) = ifconfig_output { if let Ok(output) = ifconfig_output {
let stdout = String::from_utf8_lossy(&output.stdout); let stdout = String::from_utf8_lossy(&output.stdout);
@@ -32,15 +28,15 @@ pub fn get_ip_info() -> String {
let ip = parts[1]; let ip = parts[1];
let mut ip_with_cidr = ip.to_string(); let mut ip_with_cidr = ip.to_string();
if let Some(netmask_idx) = parts.iter().position(|&x| x == "netmask") { if let Some(netmask_idx) = parts.iter().position(|&x| x == "netmask")
if netmask_idx + 1 < parts.len() { && netmask_idx + 1 < parts.len()
let netmask_hex = parts[netmask_idx + 1]; {
if netmask_hex.starts_with("0x") { let netmask_hex = parts[netmask_idx + 1];
if let Ok(num) = u32::from_str_radix(&netmask_hex[2..], 16) { if netmask_hex.starts_with("0x")
let cidr = num.count_ones(); && let Ok(num) = u32::from_str_radix(&netmask_hex[2..], 16)
ip_with_cidr = format!("{}/{}", ip, cidr); {
} let cidr = num.count_ones();
} ip_with_cidr = format!("{}/{}", ip, cidr);
} }
} }
@@ -52,4 +48,3 @@ pub fn get_ip_info() -> String {
"<unknown>".to_string() "<unknown>".to_string()
} }

View File

@@ -1,18 +1,17 @@
use std::env; use std::env;
pub fn get_locale_info() -> String { pub fn get_locale_info() -> String {
if let Ok(locale) = env::var("LC_ALL") { if let Ok(locale) = env::var("LC_ALL")
if !locale.is_empty() { && !locale.is_empty()
return locale; {
} return locale;
} }
if let Ok(locale) = env::var("LANG") { if let Ok(locale) = env::var("LANG")
if !locale.is_empty() { && !locale.is_empty()
return locale; {
} return locale;
} }
"<unknown>".to_string() "<unknown>".to_string()
} }

View File

@@ -74,6 +74,8 @@ pub fn get_memory_info() -> String {
format!( format!(
"{:.2} GiB / {:.2} GiB ({})", "{:.2} GiB / {:.2} GiB ({})",
used_gib, total_gib, crate::output::colors::percent(percentage) used_gib,
total_gib,
crate::output::colors::percent(percentage)
) )
} }

View File

@@ -3,8 +3,9 @@ use std::process::Command;
pub fn get_shell_info() -> String { pub fn get_shell_info() -> String {
let shell_path = env::var("SHELL").unwrap_or_else(|_| "unknown".to_string()); let shell_path = env::var("SHELL").unwrap_or_else(|_| "unknown".to_string());
let shell_name = shell_path.split('/').last().unwrap_or("unknown"); let shell_name = shell_path.split('/').next_back().unwrap_or("unknown");
let version = Command::new(&shell_path)
Command::new(&shell_path)
.arg("--version") .arg("--version")
.output() .output()
.map(|output| { .map(|output| {
@@ -16,7 +17,5 @@ pub fn get_shell_info() -> String {
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(" ") .join(" ")
}) })
.unwrap_or_else(|_| shell_name.to_string()); .unwrap_or_else(|_| shell_name.to_string())
version
} }

View File

@@ -1,6 +1,6 @@
// https://github.com/fastfetch-cli/fastfetch/blob/dev/src/detection/disk/disk.c // 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; use std::ffi::CStr;
#[repr(C)] #[repr(C)]
@@ -79,7 +79,9 @@ pub fn get_storage_info() -> String {
let mut result = format!( let mut result = format!(
"{:.2} GiB / {:.2} GiB ({})", "{:.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() { if !filesystem.is_empty() {
@@ -97,4 +99,3 @@ pub fn get_storage_info() -> String {
"<unknown>".to_string() "<unknown>".to_string()
} }

View File

@@ -12,13 +12,13 @@ pub fn get_swap_info() -> String {
let mut used_mb = 0.0; let mut used_mb = 0.0;
for part in stdout.split_whitespace() { for part in stdout.split_whitespace() {
if let Some(val) = part.strip_suffix('M') { if let Some(val) = part.strip_suffix('M')
if let Ok(num) = val.parse::<f64>() { && let Ok(num) = val.parse::<f64>()
if stdout.contains(&format!("total = {}", part)) { {
total_mb = num; if stdout.contains(&format!("total = {}", part)) {
} else if stdout.contains(&format!("used = {}", part)) { total_mb = num;
used_mb = num; } else if stdout.contains(&format!("used = {}", part)) {
} used_mb = num;
} }
} }
} }
@@ -33,7 +33,9 @@ pub fn get_swap_info() -> String {
return format!( return format!(
"{:.2} GiB / {:.2} GiB ({})", "{:.2} GiB / {:.2} GiB ({})",
used_gib, total_gib, crate::output::colors::percent(percentage) used_gib,
total_gib,
crate::output::colors::percent(percentage)
); );
} }

View File

@@ -26,12 +26,11 @@ pub fn get_terminal_info() -> String {
let my_pid = sysinfo::get_current_pid().unwrap_or(sysinfo::Pid::from(0)); let my_pid = sysinfo::get_current_pid().unwrap_or(sysinfo::Pid::from(0));
if let Some(process) = sys.process(my_pid) { if let Some(process) = sys.process(my_pid)
if let Some(parent_pid) = process.parent() { && let Some(parent_pid) = process.parent()
if let Some(parent_proc) = sys.process(parent_pid) { && let Some(parent_proc) = sys.process(parent_pid)
return parent_proc.name().to_string_lossy().replace(".app", ""); {
} return parent_proc.name().to_string_lossy().replace(".app", "");
}
} }
"unknown".to_string() "unknown".to_string()

View File

@@ -15,30 +15,25 @@ pub fn get_window_manager_info() -> DisplayServerResult {
if cfg!(target_os = "macos") { if cfg!(target_os = "macos") {
let plist_path = "/System/Library/CoreServices/WindowManager.app/Contents/version.plist"; let plist_path = "/System/Library/CoreServices/WindowManager.app/Contents/version.plist";
if Path::new(plist_path).exists() { if Path::new(plist_path).exists()
if let Ok(value) = Value::from_file(plist_path) { && let Ok(value) = Value::from_file(plist_path)
if let Some(dict) = value.as_dictionary() { && let Some(dict) = value.as_dictionary()
if let Some(raw_version) = dict.get("SourceVersion").and_then(|v| v.as_string()) && let Some(raw_version) = dict.get("SourceVersion").and_then(|v| v.as_string())
{ {
// Apple format: AAAABBBCCDDDDDD (Major, Minor, Patch, Build) // Apple format: AAAABBBCCDDDDDD (Major, Minor, Patch, Build)
if raw_version.len() >= 8 && raw_version.chars().all(|c| c.is_numeric()) { if raw_version.len() >= 8 && raw_version.chars().all(|c| c.is_numeric()) {
let major = let major = raw_version[..raw_version.len() - 12].trim_start_matches('0');
raw_version[..raw_version.len() - 12].trim_start_matches('0'); let minor = raw_version[raw_version.len() - 12..raw_version.len() - 9]
let minor = raw_version[raw_version.len() - 12..raw_version.len() - 9] .trim_start_matches('0');
.trim_start_matches('0'); let patch = raw_version[raw_version.len() - 9..raw_version.len() - 7]
let patch = raw_version[raw_version.len() - 9..raw_version.len() - 7] .trim_start_matches('0');
.trim_start_matches('0');
let m = if minor.is_empty() { "0" } else { minor }; let m = if minor.is_empty() { "0" } else { minor };
let p = if patch.is_empty() { "0" } else { patch }; let p = if patch.is_empty() { "0" } else { patch };
result.wm_pretty_name = result.wm_pretty_name = format!("Quartz Compositor {}.{}.{}", major, m, p);
format!("Quartz Compositor {}.{}.{}", major, m, p); } else {
} else { result.wm_pretty_name = format!("Quartz Compositor {}", raw_version);
result.wm_pretty_name = format!("Quartz Compositor {}", raw_version);
}
}
}
} }
} }
} }

View File

@@ -11,28 +11,28 @@ pub fn get_wm_theme_info() -> String {
let mut accent_name = "Multicolor".to_string(); let mut accent_name = "Multicolor".to_string();
let mut appearance = "Light".to_string(); let mut appearance = "Light".to_string();
if let Ok(value) = Value::from_file(path) { if let Ok(value) = Value::from_file(path)
if let Some(dict) = value.as_dictionary() { && let Some(dict) = value.as_dictionary()
if let Some(accent_val) = dict {
.get("AppleAccentColor") if let Some(accent_val) = dict
.and_then(|v| v.as_signed_integer()) .get("AppleAccentColor")
{ .and_then(|v| v.as_signed_integer())
accent_name = match accent_val { {
-1 => "Graphite".to_string(), accent_name = match accent_val {
0 => "Red".to_string(), -1 => "Graphite".to_string(),
1 => "Orange".to_string(), 0 => "Red".to_string(),
2 => "Yellow".to_string(), 1 => "Orange".to_string(),
3 => "Green".to_string(), 2 => "Yellow".to_string(),
4 => "Blue".to_string(), 3 => "Green".to_string(),
5 => "Purple".to_string(), 4 => "Blue".to_string(),
6 => "Pink".to_string(), 5 => "Purple".to_string(),
_ => "Multicolor".to_string(), 6 => "Pink".to_string(),
}; _ => "Multicolor".to_string(),
} };
}
if let Some(style) = dict.get("AppleInterfaceStyle").and_then(|v| v.as_string()) { if let Some(style) = dict.get("AppleInterfaceStyle").and_then(|v| v.as_string()) {
appearance = style.to_string(); // Usually "Dark" appearance = style.to_string(); // Usually "Dark"
}
} }
} }

View File

@@ -1,7 +1,6 @@
// neoarz // neoarz
// neo64fetch - "jarvis, rewrite this project in rust" // neo64fetch - "jarvis, rewrite this project in rust"
use std::env;
use sysinfo::System; use sysinfo::System;
mod helpers; mod helpers;
@@ -41,7 +40,6 @@ struct Stats {
architecture: String, // appended to os architecture: String, // appended to os
} }
fn get_system_stats() -> Stats { fn get_system_stats() -> Stats {
let mut sys = System::new_all(); let mut sys = System::new_all();
sys.refresh_all(); sys.refresh_all();
@@ -82,7 +80,6 @@ fn get_system_stats() -> Stats {
} }
} }
fn print_stats(stats: &Stats, offset: usize) { fn print_stats(stats: &Stats, offset: usize) {
let mut lines = Vec::new(); let mut lines = Vec::new();
@@ -90,10 +87,15 @@ fn print_stats(stats: &Stats, offset: usize) {
lines.push(colors::title(&stats.username, &stats.hostname)); lines.push(colors::title(&stats.username, &stats.hostname));
// separator // separator
lines.push(colors::separator(stats.username.len() + stats.hostname.len() + 1)); lines.push(colors::separator(
stats.username.len() + stats.hostname.len() + 1,
));
// info // 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("Host", &stats.host));
lines.push(colors::info("Kernel", &stats.kernel)); lines.push(colors::info("Kernel", &stats.kernel));
lines.push(colors::info("Uptime", &stats.uptime)); 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("Swap", &stats.swap));
lines.push(colors::info("Disk (/)", &stats.storage)); lines.push(colors::info("Disk (/)", &stats.storage));
// lines.push(colors::info("Local IP", &stats.ip)); // 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)); // lines.push(colors::info("Locale", &stats.locale));
// color blocks // color blocks
@@ -127,8 +132,6 @@ fn print_stats(stats: &Stats, offset: usize) {
} }
} }
fn main() { 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); let (offset, img_rows) = image::print_image_and_setup("assets/logo.png", 700);

View File

@@ -6,9 +6,9 @@
// Images are base64-encoded and chunked copying what swiftfetch does // Images are base64-encoded and chunked copying what swiftfetch does
// Compatible terminals: Any terminals which use Kitty protocol, like Ghostty, Kitty, Wezterm // 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 image::{GenericImageView, ImageFormat};
use libc::{ioctl, winsize, STDOUT_FILENO, TIOCGWINSZ}; use libc::{STDOUT_FILENO, TIOCGWINSZ, ioctl, winsize};
use std::env; use std::env;
use std::io::{Cursor, Write}; use std::io::{Cursor, Write};
use std::mem; use std::mem;
@@ -41,8 +41,12 @@ pub fn terminal_supports_kitty() -> bool {
return true; return true;
} }
if env::var("KITTY_WINDOW_ID").is_ok() { return true; } if env::var("KITTY_WINDOW_ID").is_ok() {
if env::var("WEZTERM_PANE").is_ok() { return true; } return true;
}
if env::var("WEZTERM_PANE").is_ok() {
return true;
}
if let Ok(term_program) = env::var("TERM_PROGRAM") { if let Ok(term_program) = env::var("TERM_PROGRAM") {
let t = term_program.to_lowercase(); let t = term_program.to_lowercase();
@@ -51,8 +55,10 @@ pub fn terminal_supports_kitty() -> bool {
} }
} }
if let Ok(term) = env::var("TERM") { if let Ok(term) = env::var("TERM")
if term.to_lowercase().contains("kitty") { return true; } && term.to_lowercase().contains("kitty")
{
return true;
} }
false false
@@ -65,8 +71,10 @@ fn terminal_cell_metrics() -> (f32, f32) {
unsafe { unsafe {
let mut ws: winsize = mem::zeroed(); let mut ws: winsize = mem::zeroed();
if ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut ws) == 0 if ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut ws) == 0
&& ws.ws_col > 0 && ws.ws_row > 0 && ws.ws_col > 0
&& ws.ws_xpixel > 0 && ws.ws_ypixel > 0 && ws.ws_row > 0
&& ws.ws_xpixel > 0
&& ws.ws_ypixel > 0
{ {
return ( return (
ws.ws_xpixel as f32 / ws.ws_col as f32, ws.ws_xpixel as f32 / ws.ws_col as f32,
@@ -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 // Kitty protocol requires PNG format, even for JPEG/WebP sources
// See: https://github.com/Ly-sec/swiftfetch/blob/main/src/display.rs#L495-L501 // See: https://github.com/Ly-sec/swiftfetch/blob/main/src/display.rs#L495-L501
let mut png_bytes = Vec::new(); 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); 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 }; let more = if end < encoded.len() { 1 } else { 0 };
if first { 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; first = false;
} else { } else {
output.push_str(&format!("\x1b_Gm={};", more)); output.push_str(&format!("\x1b_Gm={};", more));
@@ -165,7 +179,11 @@ pub fn print_image_and_setup(path: &str, target_height: u32) -> (usize, usize) {
let text = "a creeper made this"; let text = "a creeper made this";
let text_len = 16; 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!("\x1b[{}B", rows);
print!("\r\x1b[{}C{}", pad, text); print!("\r\x1b[{}C{}", pad, text);