manen

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

commit 06138d63030e17c2347ebea0958c5c4b650491e8
parent 5ed134beca06dea8437e6b44280a91bfbd96cc74
Author: Sylvia Ivory <git@sivory.net>
Date:   Sun, 22 Jun 2025 20:08:30 -0700

Colorize more types

Diffstat:
Msrc/editor.rs | 6++----
Msrc/format.rs | 42++++++++++++++++++------------------------
Msrc/inspect.rs | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 95 insertions(+), 28 deletions(-)

diff --git a/src/editor.rs b/src/editor.rs @@ -5,9 +5,7 @@ use reedline::{ }; use crate::{ - format::{TableFormat, lua_to_string}, - highlight::LuaHighlighter, - validator::LuaValidator, + format::TableFormat, highlight::LuaHighlighter, inspect::rewrite_types, validator::LuaValidator, }; pub struct Editor { @@ -118,7 +116,7 @@ impl Editor { let stringify = match value { LuaValue::Table(tbl) => self.table_format.format(&self.lua, &tbl, true)?, - value => lua_to_string(&value)?, + value => rewrite_types(&value, true), }; // TODO; colorize diff --git a/src/format.rs b/src/format.rs @@ -5,7 +5,7 @@ use mlua::prelude::*; use nu_ansi_term::Color; use reedline::Highlighter; -use crate::{highlight::LuaHighlighter, inspect::cleanup_string}; +use crate::{highlight::LuaHighlighter, inspect::rewrite_types}; const INSPECT_CODE: &str = include_str!("inspect.lua"); @@ -15,18 +15,6 @@ pub enum TableFormat { Address, } -fn addr_tbl(tbl: &LuaTable) -> String { - format!("table@{:?}", tbl.to_pointer()) -} - -pub fn lua_to_string(value: &LuaValue) -> LuaResult<String> { - match value { - LuaValue::String(string) => Ok(cleanup_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; @@ -48,38 +36,38 @@ fn is_array(tbl: &LuaTable) -> LuaResult<(bool, bool)> { Ok((is_arr, has_table)) } -fn print_array(tbl: &LuaTable) -> LuaResult<String> { +fn print_array(tbl: &LuaTable) -> 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)?); + buff.push(print_array(&inner)); } else { - buff.push(lua_to_string(&value)?); + buff.push(rewrite_types(&value, true)); } } - Ok(format!("{{ {} }}", buff.join(", "))) + format!("{{ {} }}", buff.join(", ")) } fn comfy_table( tbl: &LuaTable, recursive: bool, - visited: &mut HashMap<String, usize>, + visited: &mut HashMap<usize, usize>, ) -> LuaResult<String> { - let addr = addr_tbl(tbl); + let addr = tbl.to_pointer() as usize; if let Some(id) = visited.get(&addr) { return Ok(format!("<table {id}>")); } let id = visited.len(); - visited.insert(addr.clone(), id); + visited.insert(addr, id); let (is_array, has_table) = is_array(tbl)?; if is_array && !has_table { - return print_array(tbl); + return Ok(print_array(tbl)); } let mut table = Table::new(); @@ -89,12 +77,18 @@ fn comfy_table( 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)?) + ( + rewrite_types(&key, false), + comfy_table(&sub, recursive, visited)?, + ) } else { - (lua_to_string(&key)?, addr.clone()) + ( + rewrite_types(&key, false), + rewrite_types(&LuaValue::Table(sub), false), + ) } } else { - (lua_to_string(&key)?, lua_to_string(&value)?) + (rewrite_types(&key, false), rewrite_types(&value, false)) }; table.add_row(vec![key_str, value_str]); diff --git a/src/inspect.rs b/src/inspect.rs @@ -1,6 +1,7 @@ use aho_corasick::AhoCorasick; use lazy_static::lazy_static; use mlua::prelude::*; +use nu_ansi_term::{AnsiString, AnsiStrings, Color}; lazy_static! { static ref AC_REPLACEMENTS: (AhoCorasick, Vec<String>) = { @@ -34,6 +35,11 @@ lazy_static! { (AhoCorasick::new(escapes).unwrap(), replacements) }; static ref ESCAPER: &'static AhoCorasick = &AC_REPLACEMENTS.0; + static ref REPLACEMENT_COLOR: Vec<String> = AC_REPLACEMENTS + .1 + .iter() + .map(|s| Color::Cyan.paint(s).to_string()) + .collect(); } fn escape_control(s: &str) -> String { @@ -42,6 +48,12 @@ fn escape_control(s: &str) -> String { .replace("\\\\x", "\\x") } +fn escape_control_color(s: &str) -> String { + ESCAPER + .replace_all(s, &REPLACEMENT_COLOR) + .replace("\\\\x", &Color::Cyan.paint("\\x").to_string()) +} + fn remove_invalid(mut bytes: &[u8]) -> String { let mut buffer = String::new(); @@ -78,3 +90,66 @@ fn remove_invalid(mut bytes: &[u8]) -> String { pub fn cleanup_string(lua_str: &LuaString) -> String { escape_control(&remove_invalid(&lua_str.as_bytes())) } + +fn format_string(lua_str: &LuaString, colorize: bool) -> String { + let mut s = remove_invalid(&lua_str.as_bytes()); + + if colorize { + s = escape_control_color(&s); + } else { + s = escape_control(&s); + } + + let pair = (s.contains("'"), s.contains('"')); + + match pair { + (true, true) => format!("\"{}\"", s.replace("\"", "\\\"")), + (false, true) => format!("'{s}'"), + (true, false) | (false, false) => format!("\"{s}\""), + } +} + +fn addr_color(val: &LuaValue) -> Option<(String, Color)> { + match val { + LuaValue::LightUserData(l) => Some((format!("{:?}", l.0), Color::Cyan)), + LuaValue::Table(t) => Some((format!("{:?}", t.to_pointer()), Color::LightBlue)), + LuaValue::Function(f) => Some((format!("{:?}", f.to_pointer()), Color::Purple)), + LuaValue::Thread(t) => Some((format!("{:?}", t.to_pointer()), Color::LightGray)), + LuaValue::UserData(u) => Some((format!("{:?}", u.to_pointer()), Color::Cyan)), + _ => None, + } +} + +fn handle_strings<'a>(colorize: bool, strings: AnsiStrings<'a>) -> String { + if colorize { + strings.to_string() + } else { + nu_ansi_term::unstyle(&strings) + } +} + +pub fn rewrite_types(val: &LuaValue, colorize: bool) -> String { + match addr_color(val) { + Some((addr, color)) => { + let strings: &[AnsiString<'static>] = &[ + color.paint(val.type_name()), + Color::Default.paint("@"), + Color::LightYellow.paint(addr), + ]; + + handle_strings(colorize, AnsiStrings(strings)) + } + None => { + let strings = &[match val { + LuaValue::Nil => Color::LightRed.paint("nil"), + LuaValue::Boolean(b) => Color::LightYellow.paint(b.to_string()), + LuaValue::Integer(i) => Color::LightYellow.paint(i.to_string()), + LuaValue::Number(n) => Color::LightYellow.paint(n.to_string()), + LuaValue::String(s) => Color::Green.paint(format_string(s, colorize)), + val => Color::LightGray.paint(val.to_string().unwrap_or_default()), + }]; + + handle_strings(colorize, AnsiStrings(strings)) + } + } +}