manen

Fancy Lua REPL
Log | Files | Refs | README | LICENSE

commit 13e360dd0c0f37714859619c395a47ce556c834d
parent 9aa724953d5ce5de3b70315cfbd22613ad3e3036
Author: Sylvia Ivory <git@sivory.net>
Date:   Fri, 20 Jun 2025 22:28:02 -0700

Cleanup Editor impl

Diffstat:
Msrc/editor.rs | 150+++++--------------------------------------------------------------------------
Asrc/format.rs | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main.rs | 1+
3 files changed, 150 insertions(+), 142 deletions(-)

diff --git a/src/editor.rs b/src/editor.rs @@ -1,18 +1,7 @@ -use std::collections::HashMap; - -use comfy_table::{presets::UTF8_FULL, Table}; use mlua::prelude::*; use reedline::{DefaultPrompt, DefaultPromptSegment, Reedline, Signal}; -use crate::highlight::LuaHighlighter; - -const INSPECT_CODE: &str = include_str!("inspect.lua"); - -pub enum TableFormat { - ComfyTable(bool), - Inspect, - Address, -} +use crate::{format::{lua_to_string, TableFormat}, highlight::LuaHighlighter}; pub struct Editor { prompt: DefaultPrompt, @@ -27,9 +16,6 @@ impl Editor { let lua = Lua::new(); let version: String = lua.globals().get("_VERSION")?; - let inspect: LuaTable = lua.load(INSPECT_CODE).eval()?; - lua.globals().set("_inspect", inspect)?; - let prompt = DefaultPrompt::new( DefaultPromptSegment::Basic(version), DefaultPromptSegment::Empty, @@ -67,136 +53,16 @@ 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 is_array(tbl: &LuaTable) -> LuaResult<(bool, bool)> { - let mut is_array = true; - let mut has_table = false; - - for (key, value) in tbl.pairs::<LuaValue, LuaValue>().flatten() { - if !(key.is_integer() || key.is_number()) { - is_array = false; - } - - if let LuaValue::Table(inner) = value { - let (is_array, has_tbl) = Self::is_array(&inner)?; - - if !is_array || has_tbl { - has_table = true; - } - } - } - - Ok((is_array, has_table)) - } - - fn print_array(tbl: &LuaTable) -> LuaResult<String> { - let mut buff = Vec::new(); - - for (_, value) in tbl.pairs::<LuaValue, LuaValue>().flatten() { - if let LuaValue::Table(inner) = value { - buff.push(Self::print_array(&inner)?); - } else { - buff.push(Self::lua_to_string(&value)?); - } - } - - Ok(format!("{{ {} }}", buff.join(", "))) - } - - fn pretty_table(tbl: &LuaTable, recursive: bool, visited: &mut HashMap<String, usize>) -> LuaResult<String> { - let addr = Self::addr_tbl(tbl); - - if let Some(id) = visited.get(&addr) { - return Ok(format!("<table {id}>")) - } - - let id = visited.len(); - visited.insert(addr.clone(), id); - - let (is_array, has_table) = Self::is_array(tbl)?; - - if is_array && !has_table { - return Self::print_array(tbl) - } - - let mut table = Table::new(); - table.load_preset(UTF8_FULL); - table.set_header(vec![format!("<table {id}>")]); - - for (key, value) in tbl.pairs::<LuaValue, LuaValue>().flatten() { - let (key_str, value_str) = if let LuaValue::Table(sub) = value { - if recursive { - ( - Self::lua_to_string(&key)?, - Self::pretty_table(&sub, recursive, visited)? - ) - } else { - ( - Self::lua_to_string(&key)?, - addr.clone(), - ) - } - } else { - ( - Self::lua_to_string(&key)?, - Self::lua_to_string(&value)?, - ) - }; - - table.add_row(vec![key_str, 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::Inspect => { - let inspect: LuaTable = self.lua.globals().get("_inspect")?; - println!("{}", inspect.call::<String>(tbl)?); - }, - TableFormat::ComfyTable(recursive) => { - let mut visited = HashMap::new(); - println!("{}", Self::pretty_table(tbl, recursive, &mut visited)?) - } - } - - Ok(()) - } - fn eval(&mut self, line: &str) -> LuaResult<()> { let value: LuaValue = self.lua.load(line).eval()?; - match value { - LuaValue::Table(tbl) => self.handle_table(&tbl)?, - value => println!("{}", Self::lua_to_string(&value)?), - } + let stringify = match value { + LuaValue::Table(tbl) => self.table_format.format(&self.lua, &tbl)?, + value => lua_to_string(&value)?, + }; + + // TODO; colorize + println!("{stringify}"); Ok(()) } diff --git a/src/format.rs b/src/format.rs @@ -0,0 +1,141 @@ +use std::collections::HashMap; + +use comfy_table::{presets::UTF8_FULL_CONDENSED, Table}; +use mlua::prelude::*; + +const INSPECT_CODE: &str = include_str!("inspect.lua"); + +pub enum TableFormat { + ComfyTable(bool), + Inspect, + Address, +} + +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() +} + +pub fn lua_to_string(value: &LuaValue) -> LuaResult<String> { + match value { + LuaValue::String(string) => Ok(convert_string(string)), + LuaValue::Table(tbl) => Ok(addr_tbl(tbl)), + value => value.to_string() + } +} + +fn is_array(tbl: &LuaTable) -> LuaResult<(bool, bool)> { + let mut is_arr = true; + let mut has_table = false; + + for (key, value) in tbl.pairs::<LuaValue, LuaValue>().flatten() { + if !(key.is_integer() || key.is_number()) { + is_arr = false; + } + + if let LuaValue::Table(inner) = value { + let (is_arr, has_tbl) = is_array(&inner)?; + + if !is_arr || has_tbl { + has_table = true; + } + } + } + + Ok((is_arr, has_table)) +} + +fn print_array(tbl: &LuaTable) -> LuaResult<String> { + let mut buff = Vec::new(); + + for (_, value) in tbl.pairs::<LuaValue, LuaValue>().flatten() { + if let LuaValue::Table(inner) = value { + buff.push(print_array(&inner)?); + } else { + buff.push(lua_to_string(&value)?); + } + } + + Ok(format!("{{ {} }}", buff.join(", "))) +} + +fn comfy_table(tbl: &LuaTable, recursive: bool, visited: &mut HashMap<String, usize>) -> LuaResult<String> { + let addr = addr_tbl(tbl); + + if let Some(id) = visited.get(&addr) { + return Ok(format!("<table {id}>")) + } + + let id = visited.len(); + visited.insert(addr.clone(), id); + + let (is_array, has_table) = is_array(tbl)?; + + if is_array && !has_table { + return print_array(tbl) + } + + let mut table = Table::new(); + table.load_preset(UTF8_FULL_CONDENSED); + table.set_header(vec![format!("<table {id}>")]); + + for (key, value) in tbl.pairs::<LuaValue, LuaValue>().flatten() { + let (key_str, value_str) = if let LuaValue::Table(sub) = value { + if recursive { + ( + lua_to_string(&key)?, + comfy_table(&sub, recursive, visited)? + ) + } else { + ( + lua_to_string(&key)?, + addr.clone(), + ) + } + } else { + ( + lua_to_string(&key)?, + lua_to_string(&value)?, + ) + }; + + table.add_row(vec![key_str, value_str]); + } + + if table.is_empty() { + Ok(String::from("{}")) + } else { + Ok(table.to_string()) + } +} + +impl TableFormat { + pub fn format(&self, lua: &Lua, tbl: &LuaTable) -> LuaResult<String> { + match self { + TableFormat::Address => Ok(format!("table@{:?}", tbl.to_pointer())), + TableFormat::Inspect => { + if let Some(inspect) = lua.globals().get::<Option<LuaTable>>("_inspect")? { + inspect.call::<String>(tbl) + } else { + let inspect: LuaTable = lua.load(INSPECT_CODE).eval()?; + lua.globals().set("_inspect", inspect)?; + + self.format(lua, tbl) + } + }, + TableFormat::ComfyTable(recursive) => { + let mut visited = HashMap::new(); + comfy_table(tbl, *recursive, &mut visited) + } + } + } +} diff --git a/src/main.rs b/src/main.rs @@ -2,6 +2,7 @@ use editor::Editor; mod editor; mod highlight; +mod format; fn main() -> color_eyre::Result<()> { Editor::new()?.run();