use mlua::{AnyUserData, FromLua, Lua, Table, UserData, UserDataMethods, Value}; use super::{Span, Style}; use crate::{GLOBALS, LUA}; #[derive(Clone)] pub(crate) struct Line(pub(super) ratatui::text::Line<'static>); impl Line { pub(crate) fn install() -> mlua::Result<()> { let ui: Table = GLOBALS.get("ui")?; ui.set( "Line", LUA.create_function(|_, value: Value| { if let Value::Table(tbl) = value { let seq: Vec<_> = tbl.sequence_values().filter_map(|v| v.ok()).collect(); let mut spans = Vec::with_capacity(seq.len()); for value in seq { if let Value::UserData(ud) = value { if let Ok(span) = ud.take::() { spans.push(span.0); } else if let Ok(line) = ud.take::() { spans.extend(line.0.spans.into_iter().collect::>()); } else { return Err(mlua::Error::external("expected a table of Spans or Lines")); } } } return Ok(Self(ratatui::text::Line::from(spans))); } Err(mlua::Error::external("expected a table of Spans or Lines")) })?, ) } } impl<'lua> FromLua<'lua> for Line { fn from_lua(value: Value<'lua>, _: &'lua Lua) -> mlua::Result { match value { Value::UserData(ud) => Ok(ud.borrow::()?.clone()), _ => Err(mlua::Error::FromLuaConversionError { from: value.type_name(), to: "Line", message: Some("expected a Line".to_string()), }), } } } impl UserData for Line { fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { methods.add_function("width", |_, ud: AnyUserData| Ok(ud.borrow_mut::()?.0.width())); methods.add_function("style", |_, (ud, value): (AnyUserData, Value)| { { let mut me = ud.borrow_mut::()?; match value { Value::Nil => me.0.reset_style(), Value::Table(tbl) => me.0.patch_style(Style::from(tbl).0), Value::UserData(ud) => me.0.patch_style(ud.borrow::