diff --git a/Cargo.lock b/Cargo.lock index b0b866e..ece7c54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1033,6 +1033,7 @@ dependencies = [ "rustyline", "serde", "serde_json", + "stanza", "toml", "tree-sitter", "wasm-bindgen-futures", @@ -3118,6 +3119,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "stanza" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d230b987a5b524a015ded47fed54c5177598a71c90508acee1c5d0b4c955f74" + [[package]] name = "static_assertions" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 931594f..3af4df3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ reedline = { version = "0.28.0", features = ["clipboard", "sqlite"] } crossterm = "0.27.0" nu-ansi-term = "0.49.0" humantime = "2.1.0" +stanza = "0.5.1" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] env_logger = "0.10" diff --git a/src/value/list.rs b/src/value/list.rs index 975bc0b..55d48cf 100644 --- a/src/value/list.rs +++ b/src/value/list.rs @@ -4,6 +4,12 @@ use std::{ sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}, }; +use stanza::{ + renderer::{console::Console, Renderer}, + style::Styles, + table::{Cell, Content, Row, Table}, +}; + use crate::Value; #[derive(Debug, Clone)] @@ -35,6 +41,36 @@ impl List { pub fn items_mut(&self) -> RwLockWriteGuard<'_, Vec> { self.0.write().unwrap() } + + pub fn as_text_table(&self) -> Table { + let cells: Vec = self + .items() + .iter() + .map(|value| { + if let Value::List(list) = value { + Cell::new(Styles::default(), Content::Nested(list.as_text_table())) + } else if let Value::Map(map) = value { + Cell::new(Styles::default(), Content::Nested(map.as_text_table())) + } else { + Cell::new(Styles::default(), Content::Label(value.to_string())) + } + }) + .collect(); + + let row = if cells.is_empty() { + Row::new( + Styles::default(), + vec![Cell::new( + Styles::default(), + Content::Label("empty list".to_string()), + )], + ) + } else { + Row::new(Styles::default(), cells) + }; + + Table::default().with_row(row) + } } impl Eq for List {} @@ -65,18 +101,8 @@ impl PartialOrd for List { impl Display for List { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let items = self.items(); + let renderer = Console::default(); - write!(f, "[")?; - - for (index, value) in items.iter().enumerate() { - write!(f, "{value}")?; - - if index != items.len() - 1 { - write!(f, ", ")?; - } - } - - write!(f, "]") + f.write_str(&renderer.render(&self.as_text_table())) } } diff --git a/src/value/map.rs b/src/value/map.rs index 73d7357..a98597c 100644 --- a/src/value/map.rs +++ b/src/value/map.rs @@ -3,6 +3,11 @@ use serde::{ ser::SerializeMap, Deserialize, Serialize, }; +use stanza::{ + renderer::{console::Console, Renderer}, + style::{HAlign, Styles}, + table::{Row, Table}, +}; use std::{ cmp::Ordering, collections::BTreeMap, @@ -94,6 +99,37 @@ impl Map { Ok(previous) } + + pub fn as_text_table(&self) -> Table { + let variables = self.variables.read().unwrap().clone().into_iter(); + let mut table = Table::with_styles(Styles::default().with(HAlign::Centred)); + + for (key, (value, r#type)) in variables { + if let Value::Map(map) = value { + table.push_row(Row::new( + Styles::default(), + vec![key.into(), map.as_text_table().into(), "".into()], + )); + } else if let Value::List(list) = value { + table.push_row(Row::new( + Styles::default(), + vec![ + key.into(), + list.as_text_table().into(), + r#type.to_string().into(), + ], + )); + } else { + table.push_row([key, value.to_string(), r#type.to_string()]); + }; + } + + if table.is_empty() { + table.push_row(vec!["", "empty map", ""]) + } + + table + } } impl Default for Map { @@ -130,14 +166,9 @@ impl PartialOrd for Map { impl Display for Map { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - writeln!(f, "{{")?; + let renderer = Console::default(); - let variables = self.variables.read().unwrap().clone().into_iter(); - - for (key, (value, value_type)) in variables { - writeln!(f, " {key} <{value_type}> = {value}")?; - } - write!(f, "}}") + f.write_str(&renderer.render(&self.as_text_table())) } }