// Gather and display system information // Copyright (C) 2021 Lucien Cartier-Tilet // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . use crate::sysinfo::{Machine, Memory}; use crate::args::Args; fn get_uptime(mut uptime: u64, seconds: bool) -> String { let mut uptime_str = String::new(); let minute_length = 60_u64; let hour_length = minute_length * 60; let day_length = hour_length * 24; let days = uptime / day_length; uptime %= day_length; if days > 0 { uptime_str.push_str(format!("{} days ", days).as_str()); } let hours = uptime / hour_length; uptime %= hour_length; if days > 0 || hours > 0 { uptime_str.push_str(format!("{} hours ", hours).as_str()); } let minutes = uptime / minute_length; uptime_str.push_str(format!("{} minutes", minutes).as_str()); if seconds { uptime %= minute_length; uptime_str.push_str(format!(" {} seconds", uptime).as_str()); } uptime_str } fn get_name_max_width(disks: &[Memory]) -> usize { disks .iter() .max_by(|x, y| x.name.len().cmp(&y.name.len())) .unwrap() .name .len() } fn print_ramp( memory: &Memory, left_margin: usize, total_width: usize, ) -> String { use ansi_term::{Color, Style}; use humansize::{FileSize, file_size_opts as foptions}; let humansize_option = foptions::FileSizeOpts { decimal_places: 1, decimal_zeroes: 1, space: false, ..foptions::CONVENTIONAL }; let ramp_length = total_width - left_margin - 28; let full = (ramp_length as f32 * memory.percentage()) as usize; let empty = ramp_length - full; let percentage = memory.percentage() * 100_f32; let warning = percentage >= 75_f32; let critical = percentage >= 90_f32; let fg = if critical { Color::Red } else if warning { Color::Yellow } else { Color::Green }; let mut ramp = String::from("["); for _ in 0..full { ramp.push_str(Style::new().fg(fg).paint("=").to_string().as_str()); } for _ in 0..empty { ramp.push('='); } ramp.push_str( format!( "] {:>6} / {:>6} ", memory .used() .file_size(&humansize_option) .unwrap() .replace("B", ""), memory .size .file_size(&humansize_option) .unwrap() .replace("B", "") ) .as_str(), ); let percentage_str = Style::new().fg(fg).paint(format!("{:3.0}%", percentage)).to_string(); ramp.push_str(format!("({}%)", percentage_str).as_str()); ramp } pub fn print_cli(machine: Machine, args: Args) { let width = args.width; let mut separator = String::from(""); for _ in 0..width { separator.push('='); } let left_max_width = "Hostname".len().max(get_name_max_width(&machine.disks)); let uptime = get_uptime(machine.uptime, args.seconds); let right_width = machine.kernel.len().max(uptime.len()) + 3; println!("{}", separator); println!("{0:.<1$}: {2}{3:>4$}.: {5}", "OS", left_max_width, machine.os, "Kernel", width as usize - (left_max_width + 2 + machine.os.len()) - right_width, machine.kernel ); println!("{0:.<1$}: {2}{3:>4$}.: {5}", "Hostname", left_max_width, machine.hostname, "Uptime", width as usize - (left_max_width + 2 + machine.hostname.len()) - right_width, uptime ); println!("{0:.<1$}: {2}", "Mem", left_max_width, print_ramp(&machine.ram, left_max_width, width) ); println!("{0:.<1$}: {2}", "Swap", left_max_width, print_ramp(&machine.swap, left_max_width, width) ); for disk in machine.disks { println!("{0:.<1$}: {2}", disk.name, left_max_width, print_ramp(&disk, left_max_width, width) ); } println!("{}", separator); }