diff --git a/Cargo.lock b/Cargo.lock
index e297979..7da07bd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,15 @@
# It is not intended for manual editing.
version = 3
+[[package]]
+name = "ansi_term"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi",
+]
+
[[package]]
name = "atty"
version = "0.2.14"
@@ -140,6 +149,12 @@ dependencies = [
"libc",
]
+[[package]]
+name = "humansize"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026"
+
[[package]]
name = "indexmap"
version = "1.7.0"
@@ -217,6 +232,15 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "output_vt100"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
+dependencies = [
+ "winapi",
+]
+
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@@ -254,7 +278,10 @@ dependencies = [
name = "pumo-system-info"
version = "0.1.0"
dependencies = [
+ "ansi_term",
"clap",
+ "humansize",
+ "output_vt100",
"serde",
"serde_json",
"sysinfo",
@@ -308,18 +335,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
-version = "1.0.130"
+version = "1.0.131"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
+checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.130"
+version = "1.0.131"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
+checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2"
dependencies = [
"proc-macro2",
"quote",
diff --git a/Cargo.toml b/Cargo.toml
index 482d7e2..b63184f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,7 +10,10 @@ publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-sysinfo = "0.21"
+sysinfo = "0.21.2"
clap = { version = "3.0.0-rc.0", default-features = false, features = ["std", "derive", "color"] }
-serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"
+serde = { version = "1.0.131", features = ["derive"] }
+serde_json = "1.0.72"
+output_vt100 = "0.1.2"
+ansi_term = "0.12.1"
+humansize = "1.1.1"
diff --git a/src/args.rs b/src/args.rs
index 0b3483b..174e5a5 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -24,7 +24,7 @@ conditions; see the GPL-3.0 license or newer
#[derive(Parser, Debug)]
#[clap(name="Pumo System Info",about,version,author,after_long_help=AFTER_HELP)]
pub struct Args {
- #[clap(short, long)]
+ #[clap(short, long, help="JSON output")]
pub json: bool,
#[clap(short, long, default_value_t = 75)]
@@ -33,6 +33,9 @@ pub struct Args {
#[clap(short, long, default_value_t = 90)]
pub critical_level: u8,
- #[clap(short = 'W', long, default_value_t = 72)]
- pub width: u8,
+ #[clap(short = 'W', long, default_value_t = 72, help="Width of the console output")]
+ pub width: usize,
+
+ #[clap(short, long, help="Display seconds in uptime")]
+ pub seconds: bool,
}
diff --git a/src/cli.rs b/src/cli.rs
index 4d6fef2..4939cc3 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -14,8 +14,159 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-mod sysinfo;
-pub fn print_cli() {
+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);
}
diff --git a/src/main.rs b/src/main.rs
index 089d100..d861ba9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -16,14 +16,18 @@
mod sysinfo;
mod args;
+mod cli;
use clap::Parser;
fn main() {
+ output_vt100::init();
+
let args = args::Args::parse();
let machine = sysinfo::Machine::new();
if args.json {
println!("{}", serde_json::to_string(&machine).unwrap());
} else {
+ cli::print_cli(machine, args);
}
}
diff --git a/src/sysinfo.rs b/src/sysinfo.rs
index ca1250f..d4ef344 100644
--- a/src/sysinfo.rs
+++ b/src/sysinfo.rs
@@ -18,27 +18,35 @@ use serde::Serialize;
use sysinfo::{System, SystemExt, DiskExt};
#[derive(Debug, Serialize)]
-struct Memory {
- name: String,
- size: u64,
- available: u64
+pub struct Memory {
+ pub name: String,
+ pub size: u64,
+ pub available: u64
}
impl Memory {
pub fn new(name: String, size: u64, available: u64) -> Self {
Self { name, size, available }
}
+
+ pub fn used(&self) -> u64 {
+ self.size - self.available
+ }
+
+ pub fn percentage(&self) -> f32 {
+ self.used() as f32 / self.size as f32
+ }
}
#[derive(Debug, Serialize)]
pub struct Machine {
- os: String,
- kernel: String,
- hostname: String,
- uptime: u64,
- ram: Memory,
- swap: Memory,
- disks: Vec,
+ pub os: String,
+ pub kernel: String,
+ pub hostname: String,
+ pub uptime: u64,
+ pub ram: Memory,
+ pub swap: Memory,
+ pub disks: Vec,
}
impl Machine {
@@ -50,14 +58,14 @@ impl Machine {
.iter()
.map(|x| {
Memory::new(
- x.name().to_str().unwrap().to_string(),
+ x.mount_point().to_str().unwrap().to_string(),
x.total_space(),
x.available_space(),
)
})
.collect::>();
- let ram = Memory::new("RAM".into(), sys.available_memory(), sys.available_memory());
- let swap = Memory::new("Swap".into(), sys.total_swap(), sys.free_swap());
+ let ram = Memory::new("RAM".into(), sys.total_memory() * 1000, sys.available_memory() * 1000);
+ let swap = Memory::new("Swap".into(), sys.total_swap() * 1000, sys.free_swap() * 1000);
Self {
os: sys.name().unwrap(),
kernel: sys.kernel_version().unwrap(),