From a6c102aabfd629d9dbef03104372f9f0f6f9e3ea Mon Sep 17 00:00:00 2001 From: Maxime Van Hees Date: Tue, 15 Jul 2025 10:28:41 +0200 Subject: [PATCH] improved output format + add support for displaying in tables --- Cargo.lock | 124 ++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + example.rhai | 4 +- src/rhai_api.rs | 82 +++++++++++++++++++++++++++----- 4 files changed, 195 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ab85b7d..249fd98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -167,6 +167,27 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "csv" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" +dependencies = [ + "memchr", +] + [[package]] name = "darling" version = "0.20.11" @@ -212,6 +233,27 @@ dependencies = [ "serde", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -229,6 +271,12 @@ version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "encoding_rs" version = "0.8.35" @@ -403,12 +451,19 @@ dependencies = [ "uuid", ] +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + [[package]] name = "hetzner_rhai" version = "0.1.0" dependencies = [ "hcloud", "ping", + "prettytable-rs", "reqwest", "rhai", "tokio", @@ -733,6 +788,17 @@ dependencies = [ "serde", ] +[[package]] +name = "is-terminal" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "itoa" version = "1.0.15" @@ -749,12 +815,28 @@ 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.174" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +[[package]] +name = "libredox" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" +dependencies = [ + "bitflags", + "libc", +] + [[package]] name = "linux-raw-sys" version = "0.9.4" @@ -1016,6 +1098,20 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettytable-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" +dependencies = [ + "csv", + "encode_unicode", + "is-terminal", + "lazy_static", + "term", + "unicode-width", +] + [[package]] name = "proc-macro2" version = "1.0.95" @@ -1079,6 +1175,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror", +] + [[package]] name = "ref-cast" version = "1.0.24" @@ -1539,6 +1646,17 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "thin-vec" version = "0.2.14" @@ -1761,6 +1879,12 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 4bfbafc..0db9a89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,4 @@ rhai = { version = "1.22.2", features = ["sync"] } tokio = { version = "1.46.1", features = ["full"] } ping = "0.6.1" +prettytable-rs = "0.10.0" diff --git a/example.rhai b/example.rhai index 1b47c92..e92432e 100644 --- a/example.rhai +++ b/example.rhai @@ -7,9 +7,7 @@ try { if servers.len() == 0 { print("No servers found."); } else { - for server in servers { - print(`Server: ${server.name} (${server.id}), Status: ${server.status}`); - } + print(servers.show_table()); let first_server = servers[0]; print(`Getting details for server: ${first_server.name}`); diff --git a/src/rhai_api.rs b/src/rhai_api.rs index b43157f..91423f2 100644 --- a/src/rhai_api.rs +++ b/src/rhai_api.rs @@ -2,8 +2,8 @@ use crate::async_handler::Response; use crate::async_handler::Request; use crate::hetzner_api::{HetznerClient, WrappedServer}; use rhai::{Engine, EvalAltResult}; -use rhai::EvalContext; use std::sync::{Arc, Mutex, mpsc::{Sender, Receiver}}; +use prettytable::{Table, Row, Cell}; pub fn register_hetzner_api( engine: &mut Engine, @@ -136,6 +136,28 @@ pub fn register_hetzner_api( .register_iterator::>() .register_fn("len", |list: &mut Vec| list.len() as i64) .register_indexer_get(|list: &mut Vec, index: i64| list[index as usize].clone()) + .register_fn( + "show_table", + |servers: &mut Vec| -> Result> { + let mut table = Table::new(); + table.set_titles(Row::new(vec![Cell::new("Server List").style_spec("c")])); + table.add_row(Row::new(vec![ + Cell::new("ID"), + Cell::new("Name"), + Cell::new("Status"), + Cell::new("Public IPv4"), + ])); + for server in servers { + table.add_row(Row::new(vec![ + Cell::new(&server.0.id.to_string()), + Cell::new(&server.0.name), + Cell::new(&format!("{:?}", server.0.status)), + Cell::new(&server.0.public_net.ipv4.clone().unwrap().ip.to_string()), + ])); + } + Ok(table.to_string()) + }, + ) .register_fn( "ping", move |server: &mut WrappedServer| -> Result> { @@ -168,18 +190,52 @@ pub fn register_hetzner_api( .register_fn( "show_details", |server: &mut WrappedServer| -> Result> { - let mut details = String::new(); - details.push_str(&format!(" ID: {}\n", server.0.id)); - details.push_str(&format!(" Status: {:?}\n", server.0.status)); - details.push_str(&format!(" Created: {}\n", server.0.created)); - details.push_str(&format!(" IPv4: {}\n", server.0.public_net.ipv4.clone().unwrap().ip)); - details.push_str(&format!(" Type: {}\n", server.0.server_type.clone().name)); - details.push_str(&format!(" Included Traffic: {} GB\n", server.0.included_traffic.unwrap_or(0) / 1024 / 1024 / 1024)); - details.push_str(&format!(" Ingoing Traffic: {} MB\n", server.0.ingoing_traffic.unwrap_or(0) / 1024 / 1024)); - details.push_str(&format!(" Outgoing Traffic: {} MB\n", server.0.outgoing_traffic.unwrap_or(0) / 1024 / 1024)); - details.push_str(&format!(" Primary Disk Size: {} GB\n", server.0.primary_disk_size)); - details.push_str(&format!(" Rescue Enabled: {}\n", server.0.rescue_enabled)); - Ok(details) + let mut table = Table::new(); + table.set_titles(Row::new(vec![ + Cell::new(&server.0.name).style_spec("c") + ])); + table.add_row(Row::new(vec![ + Cell::new("ID"), + Cell::new(&server.0.id.to_string()), + ])); + table.add_row(Row::new(vec![ + Cell::new("Status"), + Cell::new(&format!("{:?}", server.0.status)), + ])); + table.add_row(Row::new(vec![ + Cell::new("Created"), + Cell::new(&server.0.created), + ])); + table.add_row(Row::new(vec![ + Cell::new("IPv4"), + Cell::new(&server.0.public_net.ipv4.clone().unwrap().ip.to_string()), + ])); + table.add_row(Row::new(vec![ + Cell::new("Type"), + Cell::new(&server.0.server_type.name), + ])); + table.add_row(Row::new(vec![ + Cell::new("Included Traffic"), + Cell::new(&format!("{} GB", server.0.included_traffic.unwrap_or(0) / 1024 / 1024 / 1024)), + ])); + table.add_row(Row::new(vec![ + Cell::new("Ingoing Traffic"), + Cell::new(&format!("{} MB", server.0.ingoing_traffic.unwrap_or(0) / 1024 / 1024)), + ])); + table.add_row(Row::new(vec![ + Cell::new("Outgoing Traffic"), + Cell::new(&format!("{} MB", server.0.outgoing_traffic.unwrap_or(0) / 1024 / 1024)), + ])); + table.add_row(Row::new(vec![ + Cell::new("Primary Disk Size"), + Cell::new(&server.0.primary_disk_size.to_string()), + ])); + table.add_row(Row::new(vec![ + Cell::new("Rescue Enabled"), + Cell::new(&server.0.rescue_enabled.to_string()), + ])); + + Ok(table.to_string()) }, ); } \ No newline at end of file