commit b6817731e46cf374b42642fc1c9c8fe9ea35d05b
parent 3904958712cb67c079a2e1ea8166fe52d31872a0
Author: Sylvia Ivory <git@sivory.net>
Date: Fri, 20 Jun 2025 21:46:53 -0700
Pretty table printing
Diffstat:
| M | src/editor.rs | | | 85 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ |
1 file changed, 79 insertions(+), 6 deletions(-)
diff --git a/src/editor.rs b/src/editor.rs
@@ -1,10 +1,13 @@
+use std::collections::HashSet;
+
+use comfy_table::{presets::UTF8_FULL, Table};
use mlua::prelude::*;
use reedline::{DefaultPrompt, DefaultPromptSegment, Reedline, Signal};
use crate::highlight::LuaHighlighter;
pub enum TableFormat {
- Ascii,
+ Pretty,
Lua,
Address,
}
@@ -36,8 +39,8 @@ impl Editor {
editor,
lua,
- table_format: TableFormat::Address,
- print_nested_tables: false,
+ table_format: TableFormat::Pretty,
+ print_nested_tables: true,
})
}
@@ -61,11 +64,81 @@ impl Editor {
}
}
+ fn addr_tbl(tbl: &LuaTable) -> String {
+ format!("table@{:?}", tbl.to_pointer())
+ }
+
+ fn convert_string(string: &LuaString) -> String {
+ let bytes = string
+ .as_bytes()
+ .iter()
+ .flat_map(|b| std::ascii::escape_default(*b))
+ .collect::<Vec<_>>();
+
+ String::from_utf8_lossy(&bytes).to_string()
+ }
+
+ fn lua_to_string(value: &LuaValue) -> LuaResult<String> {
+ match value {
+ LuaValue::String(string) => Ok(Self::convert_string(string)),
+ LuaValue::Table(tbl) => Ok(Self::addr_tbl(tbl)),
+ value => value.to_string()
+ }
+ }
+
+ fn pretty_table(&self, tbl: &LuaTable, visited: &mut HashSet<String>) -> LuaResult<String> {
+ let addr = Self::addr_tbl(tbl);
+
+ if visited.contains(&addr) {
+ return Ok(format!("{addr} (self-reference)"))
+ } else {
+ visited.insert(addr.clone());
+ }
+
+ let mut table = Table::new();
+ table.load_preset(UTF8_FULL);
+
+ for (key, value) in tbl.pairs::<LuaValue, LuaValue>().flatten() {
+ let value_str = if let LuaValue::Table(sub) = value {
+ if self.print_nested_tables {
+ self.pretty_table(&sub, visited)?
+ } else {
+ addr.clone()
+ }
+ } else {
+ Self::lua_to_string(&value)?
+ };
+
+ table.add_row(vec![Self::lua_to_string(&key)?, value_str]);
+ }
+
+ if table.is_empty() {
+ Ok(String::from("{}"))
+ } else {
+ Ok(table.to_string())
+ }
+ }
+
+ fn handle_table(&self, tbl: &LuaTable) -> LuaResult<()> {
+ match self.table_format {
+ TableFormat::Address => println!("table@{:?}", tbl.to_pointer()),
+ TableFormat::Lua => todo!(),
+ TableFormat::Pretty => {
+ let mut visited = HashSet::new();
+ println!("{}", self.pretty_table(tbl, &mut visited)?)
+ }
+ }
+
+ Ok(())
+ }
+
fn eval(&mut self, line: &str) -> LuaResult<()> {
- let res: LuaValue = self.lua.load(line).eval()?;
+ let value: LuaValue = self.lua.load(line).eval()?;
- // TODO; pretty print tables
- println!("{}", res.to_string()?);
+ match value {
+ LuaValue::Table(tbl) => self.handle_table(&tbl)?,
+ value => println!("{}", Self::lua_to_string(&value)?),
+ }
Ok(())
}