diff --git a/yazi-plugin/preset/components/entity.lua b/yazi-plugin/preset/components/entity.lua index b4285c28..62d783db 100644 --- a/yazi-plugin/preset/components/entity.lua +++ b/yazi-plugin/preset/components/entity.lua @@ -79,8 +79,8 @@ end function Entity:redraw() local lines = {} for _, c in ipairs(self._children) do - local line = ui.Line((type(c[1]) == "string" and self[c[1]] or c[1])(self)) - c.width, lines[#lines + 1] = line:width(), line + local line = (type(c[1]) == "string" and self[c[1]] or c[1])(self) + c.width, lines[#lines + 1] = ui.width(line), line end return ui.Line(lines):style(self:style()) end @@ -101,12 +101,11 @@ function Entity:ellipsis(max) for _, child in ipairs(self._children) do adv = adv + child.width if adv >= max then - return not f.cha.is_dir and f.url.ext and "…." .. f.url.ext or "…" + return not f.cha.is_dir and f.url.ext and "…." .. f.url.ext or nil elseif child.id == 4 then break end end - return "…" end -- Children diff --git a/yazi-plugin/preset/plugins/archive.lua b/yazi-plugin/preset/plugins/archive.lua index a32ca5e9..cd18c972 100644 --- a/yazi-plugin/preset/plugins/archive.lua +++ b/yazi-plugin/preset/plugins/archive.lua @@ -2,7 +2,6 @@ local M = {} function M:peek(job) local limit = job.area.h - local paths, sizes = {}, {} local files, bound, code = self.list_files({ "-p", tostring(job.file.url) }, job.skip, limit) if code ~= 0 then @@ -13,31 +12,40 @@ function M:peek(job) ) end + local left, right = {}, {} for _, f in ipairs(files) do local icon = File({ url = Url(f.path), cha = Cha { kind = f.attr:sub(1, 1) == "D" and 1 or 0 }, }):icon() - if icon then - paths[#paths + 1] = ui.Line { ui.Span(" " .. icon.text .. " "):style(icon.style), f.path } + if f.size > 0 then + right[#right + 1] = string.format(" %s ", ya.readable_size(f.size)) else - paths[#paths + 1] = f.path + right[#right + 1] = " " end - if f.size > 0 then - sizes[#sizes + 1] = string.format(" %s ", ya.readable_size(f.size)) + if icon then + left[#left + 1] = ui.Span(" " .. icon.text .. " "):style(icon.style) else - sizes[#sizes + 1] = "" + left[#left + 1] = " " end + + left[#left] = ui.Line { + left[#left], + ya.truncate(f.path, { + rtl = true, + max = math.max(0, job.area.w - ui.width(left[#left]) - ui.width(right[#right])), + }), + } end if job.skip > 0 and bound < job.skip + limit then ya.emit("peek", { math.max(0, bound - limit), only_if = job.file.url, upper_bound = true }) else ya.preview_widget(job, { - ui.Text(paths):area(job.area), - ui.Text(sizes):area(job.area):align(ui.Text.RIGHT), + ui.Text(left):area(job.area), + ui.Text(right):area(job.area):align(ui.Text.RIGHT), }) end end diff --git a/yazi-plugin/src/elements/bar.rs b/yazi-plugin/src/elements/bar.rs index 98c927a5..8b30dc7a 100644 --- a/yazi-plugin/src/elements/bar.rs +++ b/yazi-plugin/src/elements/bar.rs @@ -1,4 +1,4 @@ -use mlua::{AnyUserData, Lua, MetaMethod, Table, UserData}; +use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, Table, UserData, Value}; use ratatui::widgets::Borders; use super::Area; @@ -13,7 +13,7 @@ pub struct Bar { } impl Bar { - pub fn compose(lua: &Lua) -> mlua::Result { + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, direction): (Table, u8)| { Ok(Self { direction: Borders::from_bits_truncate(direction), ..Default::default() }) })?; @@ -29,7 +29,7 @@ impl Bar { ])?; bar.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(bar) + bar.into_lua(lua) } pub(super) fn render( diff --git a/yazi-plugin/src/elements/border.rs b/yazi-plugin/src/elements/border.rs index 1a114911..aa2e1f75 100644 --- a/yazi-plugin/src/elements/border.rs +++ b/yazi-plugin/src/elements/border.rs @@ -1,4 +1,4 @@ -use mlua::{AnyUserData, Lua, MetaMethod, Table, UserData, Value}; +use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, Table, UserData, Value}; use ratatui::widgets::{Borders, Widget}; use super::Area; @@ -24,7 +24,7 @@ pub struct Border { } impl Border { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, position): (Table, u8)| { Ok(Border { position: ratatui::widgets::Borders::from_bits_truncate(position), @@ -50,7 +50,7 @@ impl Border { ])?; border.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(border) + border.into_lua(lua) } pub(super) fn render( diff --git a/yazi-plugin/src/elements/clear.rs b/yazi-plugin/src/elements/clear.rs index 6a3feba1..1de82560 100644 --- a/yazi-plugin/src/elements/clear.rs +++ b/yazi-plugin/src/elements/clear.rs @@ -1,6 +1,6 @@ use std::sync::atomic::{AtomicBool, Ordering}; -use mlua::{Lua, MetaMethod, Table, UserData}; +use mlua::{IntoLua, Lua, MetaMethod, Table, UserData, Value}; use yazi_adapter::ADAPTOR; use super::Area; @@ -13,13 +13,13 @@ pub struct Clear { } impl Clear { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, area): (Table, Area)| Ok(Clear { area }))?; let clear = lua.create_table()?; clear.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(clear) + clear.into_lua(lua) } pub(super) fn render( diff --git a/yazi-plugin/src/elements/constraint.rs b/yazi-plugin/src/elements/constraint.rs index 6526dd5b..c2ecad07 100644 --- a/yazi-plugin/src/elements/constraint.rs +++ b/yazi-plugin/src/elements/constraint.rs @@ -1,20 +1,22 @@ -use mlua::{FromLua, Lua, Table, UserData}; +use mlua::{FromLua, IntoLua, Lua, UserData, Value}; #[derive(Clone, Copy, Default, FromLua)] pub struct Constraint(pub(super) ratatui::layout::Constraint); impl Constraint { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { use ratatui::layout::Constraint as C; - lua.create_table_from([ - ("Min", lua.create_function(|_, n: u16| Ok(Self(C::Min(n))))?), - ("Max", lua.create_function(|_, n: u16| Ok(Self(C::Max(n))))?), - ("Length", lua.create_function(|_, n: u16| Ok(Self(C::Length(n))))?), - ("Percentage", lua.create_function(|_, n: u16| Ok(Self(C::Percentage(n))))?), - ("Ratio", lua.create_function(|_, (a, b): (u32, u32)| Ok(Self(C::Ratio(a, b))))?), - ("Fill", lua.create_function(|_, n: u16| Ok(Self(C::Fill(n))))?), - ]) + lua + .create_table_from([ + ("Min", lua.create_function(|_, n: u16| Ok(Self(C::Min(n))))?), + ("Max", lua.create_function(|_, n: u16| Ok(Self(C::Max(n))))?), + ("Length", lua.create_function(|_, n: u16| Ok(Self(C::Length(n))))?), + ("Percentage", lua.create_function(|_, n: u16| Ok(Self(C::Percentage(n))))?), + ("Ratio", lua.create_function(|_, (a, b): (u32, u32)| Ok(Self(C::Ratio(a, b))))?), + ("Fill", lua.create_function(|_, n: u16| Ok(Self(C::Fill(n))))?), + ])? + .into_lua(lua) } } diff --git a/yazi-plugin/src/elements/elements.rs b/yazi-plugin/src/elements/elements.rs index 59714e12..9b3d0a55 100644 --- a/yazi-plugin/src/elements/elements.rs +++ b/yazi-plugin/src/elements/elements.rs @@ -23,6 +23,8 @@ pub fn compose(lua: &Lua) -> mlua::Result { b"Style" => super::Style::compose(lua)?, b"Table" => super::Table::compose(lua)?, b"Text" => super::Text::compose(lua)?, + + b"width" => super::Utils::width(lua)?, _ => return Ok(Value::Nil), } .into_lua(lua) diff --git a/yazi-plugin/src/elements/gauge.rs b/yazi-plugin/src/elements/gauge.rs index f9235921..3cfe8f25 100644 --- a/yazi-plugin/src/elements/gauge.rs +++ b/yazi-plugin/src/elements/gauge.rs @@ -1,4 +1,4 @@ -use mlua::{AnyUserData, ExternalError, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; +use mlua::{AnyUserData, ExternalError, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; use ratatui::widgets::Widget; use super::{Area, Span}; @@ -15,13 +15,13 @@ pub struct Gauge { } impl Gauge { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, _: Table| Ok(Gauge::default()))?; let gauge = lua.create_table()?; gauge.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(gauge) + gauge.into_lua(lua) } pub(super) fn render( diff --git a/yazi-plugin/src/elements/layout.rs b/yazi-plugin/src/elements/layout.rs index cc75ca8a..1e0ac00e 100644 --- a/yazi-plugin/src/elements/layout.rs +++ b/yazi-plugin/src/elements/layout.rs @@ -1,4 +1,4 @@ -use mlua::{AnyUserData, Lua, MetaMethod, Table, UserData, UserDataMethods}; +use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; use super::{Constraint, Rect}; @@ -13,13 +13,13 @@ pub struct Layout { } impl Layout { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, _: Table| Ok(Self::default()))?; let layout = lua.create_table_from([("HORIZONTAL", HORIZONTAL), ("VERTICAL", VERTICAL)])?; layout.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(layout) + layout.into_lua(lua) } } diff --git a/yazi-plugin/src/elements/line.rs b/yazi-plugin/src/elements/line.rs index d8083691..e5806bdb 100644 --- a/yazi-plugin/src/elements/line.rs +++ b/yazi-plugin/src/elements/line.rs @@ -21,7 +21,7 @@ pub struct Line { } impl Line { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, value): (Table, Value)| Line::try_from(value))?; let parse = lua.create_function(|_, code: mlua::String| { @@ -47,7 +47,7 @@ impl Line { ])?; line.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(line) + line.into_lua(lua) } pub(super) fn render( @@ -148,26 +148,70 @@ impl UserData for Line { } }; - let (mut width, mut last) = (0, None); - 'outer: for (x, span) in me.inner.iter_mut().enumerate() { - for (y, c) in span.content.char_indices() { - width += c.width().unwrap_or(0); - match last { - None if width > max - ellipsis.0 => last = Some((false, x, y)), - Some((false, x, y)) if width > max => { - last = Some((true, x, y)); - break 'outer; - } - _ => {} + fn traverse( + max: usize, + threshold: usize, + it: impl Iterator, + ) -> (Option<(usize, usize, usize)>, bool) { + let (mut adv, mut cut) = (0, None); + for (x, y, c) in it { + adv += c.width().unwrap_or(0); + if adv <= threshold { + cut = Some((x, y, adv)); + } else if adv > max { + break; } } + (cut, adv > max) } - if let Some((true, x, y)) = last { - let spans = &mut me.inner.spans; + let rtl = t.raw_get("rtl")?; + let (cut, remain) = if rtl { + traverse( + max, + max - ellipsis.0, + me.inner + .iter() + .enumerate() + .rev() + .flat_map(|(x, s)| s.content.char_indices().rev().map(move |(y, c)| (x, y, c))), + ) + } else { + traverse( + max, + max - ellipsis.0, + me.inner + .iter() + .enumerate() + .flat_map(|(x, s)| s.content.char_indices().map(move |(y, c)| (x, y, c))), + ) + }; + + let Some((x, y, width)) = cut else { + me.inner.spans.clear(); + me.inner.spans.push(ellipsis.1); + return Ok(ud); + }; + if !remain { + return Ok(ud); + } + + let spans = &mut me.inner.spans; + let len = match (rtl, width == max) { + (a, b) if a == b => spans[x].content[y..].chars().next().map_or(0, |c| c.len_utf8()), + _ => 0, + }; + + if rtl { match &mut spans[x].content { - Cow::Borrowed(s) => spans[x].content = Cow::Borrowed(&s[..y]), - Cow::Owned(s) => s.truncate(y), + Cow::Borrowed(s) => spans[x].content = Cow::Borrowed(&s[y + len..]), + Cow::Owned(s) => _ = s.drain(..y + len), + } + spans.splice(..x, [ellipsis.1]); + } else { + match &mut spans[x].content { + Cow::Borrowed(s) => spans[x].content = Cow::Borrowed(&s[..y + len]), + Cow::Owned(s) => s.truncate(y + len), } spans.truncate(x + 1); spans.push(ellipsis.1); @@ -177,3 +221,80 @@ impl UserData for Line { }); } } + +#[cfg(test)] +mod tests { + use mlua::{UserDataRef, chunk}; + + use super::*; + + fn truncate(s: &str, max: usize, rtl: bool) -> String { + let lua = Lua::new(); + let comp = Line::compose(&lua).unwrap(); + let line: UserDataRef = lua + .load(chunk! { + return $comp($s):truncate { max = $max, rtl = $rtl } + }) + .call(()) + .unwrap(); + + line.inner.spans.iter().map(|s| s.content.as_ref()).collect() + } + + #[test] + fn test_truncate() { + assert_eq!(truncate("你好,world", 0, false), ""); + assert_eq!(truncate("你好,world", 1, false), "…"); + assert_eq!(truncate("你好,world", 2, false), "…"); + + assert_eq!(truncate("你好,世界", 3, false), "你…"); + assert_eq!(truncate("你好,世界", 4, false), "你…"); + assert_eq!(truncate("你好,世界", 5, false), "你好…"); + + assert_eq!(truncate("Hello, world", 5, false), "Hell…"); + assert_eq!(truncate("Ni好,世界", 3, false), "Ni…"); + } + + #[test] + fn test_truncate_rtl() { + assert_eq!(truncate("world,你好", 0, true), ""); + assert_eq!(truncate("world,你好", 1, true), "…"); + assert_eq!(truncate("world,你好", 2, true), "…"); + + assert_eq!(truncate("你好,世界", 3, true), "…界"); + assert_eq!(truncate("你好,世界", 4, true), "…界"); + assert_eq!(truncate("你好,世界", 5, true), "…世界"); + + assert_eq!(truncate("Hello, world", 5, true), "…orld"); + assert_eq!(truncate("你好,Shi界", 3, true), "…界"); + } + + #[test] + fn test_truncate_oboe() { + assert_eq!(truncate("Hello, world", 11, false), "Hello, wor…"); + assert_eq!(truncate("你好,世界", 9, false), "你好,世…"); + assert_eq!(truncate("你好,世Jie", 9, false), "你好,世…"); + + assert_eq!(truncate("Hello, world", 11, true), "…llo, world"); + assert_eq!(truncate("你好,世界", 9, true), "…好,世界"); + assert_eq!(truncate("Ni好,世界", 9, true), "…好,世界"); + } + + #[test] + fn test_truncate_exact() { + assert_eq!(truncate("Hello, world", 12, false), "Hello, world"); + assert_eq!(truncate("你好,世界", 10, false), "你好,世界"); + + assert_eq!(truncate("Hello, world", 12, true), "Hello, world"); + assert_eq!(truncate("你好,世界", 10, true), "你好,世界"); + } + + #[test] + fn test_truncate_overflow() { + assert_eq!(truncate("Hello, world", 13, false), "Hello, world"); + assert_eq!(truncate("你好,世界", 11, false), "你好,世界"); + + assert_eq!(truncate("Hello, world", 13, true), "Hello, world"); + assert_eq!(truncate("你好,世界", 11, true), "你好,世界"); + } +} diff --git a/yazi-plugin/src/elements/list.rs b/yazi-plugin/src/elements/list.rs index 7607a282..5fa9612d 100644 --- a/yazi-plugin/src/elements/list.rs +++ b/yazi-plugin/src/elements/list.rs @@ -1,4 +1,4 @@ -use mlua::{ExternalError, Lua, MetaMethod, Table, UserData, Value}; +use mlua::{ExternalError, IntoLua, Lua, MetaMethod, Table, UserData, Value}; use ratatui::widgets::Widget; use super::{Area, Text}; @@ -14,7 +14,7 @@ pub struct List { } impl List { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, seq): (Table, Table)| { let mut items = Vec::with_capacity(seq.raw_len()); for v in seq.sequence_values::() { @@ -27,7 +27,7 @@ impl List { let list = lua.create_table()?; list.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(list) + list.into_lua(lua) } pub(super) fn render( diff --git a/yazi-plugin/src/elements/mod.rs b/yazi-plugin/src/elements/mod.rs index 27caddee..5987df66 100644 --- a/yazi-plugin/src/elements/mod.rs +++ b/yazi-plugin/src/elements/mod.rs @@ -1,3 +1,3 @@ #![allow(clippy::module_inception)] -yazi_macro::mod_flat!(area bar border cell clear constraint elements gauge layout line list pad pos rect renderable row span style table text); +yazi_macro::mod_flat!(area bar border cell clear constraint elements gauge layout line list pad pos rect renderable row span style table text utils); diff --git a/yazi-plugin/src/elements/pad.rs b/yazi-plugin/src/elements/pad.rs index 36ee5044..3053797b 100644 --- a/yazi-plugin/src/elements/pad.rs +++ b/yazi-plugin/src/elements/pad.rs @@ -1,6 +1,6 @@ use std::ops::{Add, AddAssign, Deref}; -use mlua::{FromLua, Lua, MetaMethod, Table, UserData}; +use mlua::{FromLua, IntoLua, Lua, MetaMethod, Table, UserData, Value}; #[derive(Clone, Copy, Default, FromLua)] pub struct Pad(ratatui::widgets::Padding); @@ -16,7 +16,7 @@ impl From for Pad { } impl Pad { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, top, right, bottom, left): (Table, u16, u16, u16, u16)| { Ok(Self(ratatui::widgets::Padding::new(left, right, top, bottom))) @@ -47,7 +47,7 @@ impl Pad { ])?; pad.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(pad) + pad.into_lua(lua) } } diff --git a/yazi-plugin/src/elements/pos.rs b/yazi-plugin/src/elements/pos.rs index dc07cb51..e8b3fce0 100644 --- a/yazi-plugin/src/elements/pos.rs +++ b/yazi-plugin/src/elements/pos.rs @@ -1,6 +1,6 @@ use std::{ops::Deref, str::FromStr}; -use mlua::{AnyUserData, ExternalResult, Lua, MetaMethod, Table, UserData}; +use mlua::{AnyUserData, ExternalResult, IntoLua, Lua, MetaMethod, Table, UserData, Value}; use super::Pad; @@ -46,13 +46,13 @@ impl TryFrom for Pos { } impl Pos { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, t): (Table, Table)| Self::try_from(t))?; let position = lua.create_table()?; position.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(position) + position.into_lua(lua) } pub fn new_input(t: mlua::Table) -> mlua::Result { diff --git a/yazi-plugin/src/elements/rect.rs b/yazi-plugin/src/elements/rect.rs index c678cb3d..e5b52d4e 100644 --- a/yazi-plugin/src/elements/rect.rs +++ b/yazi-plugin/src/elements/rect.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use mlua::{FromLua, Lua, MetaMethod, Table, UserData}; +use mlua::{FromLua, IntoLua, Lua, MetaMethod, Table, UserData, Value}; use super::Pad; @@ -24,7 +24,7 @@ impl From for Rect { } impl Rect { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, args): (Table, Table)| { Ok(Self(ratatui::layout::Rect { x: args.raw_get("x").unwrap_or_default(), @@ -37,7 +37,7 @@ impl Rect { let rect = lua.create_table_from([("default", Self(ratatui::layout::Rect::default()))])?; rect.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(rect) + rect.into_lua(lua) } pub(super) fn pad(self, pad: Pad) -> Self { diff --git a/yazi-plugin/src/elements/row.rs b/yazi-plugin/src/elements/row.rs index 5ac080e9..378c143d 100644 --- a/yazi-plugin/src/elements/row.rs +++ b/yazi-plugin/src/elements/row.rs @@ -1,4 +1,4 @@ -use mlua::{AnyUserData, ExternalError, Lua, MetaMethod, Table, UserData, Value}; +use mlua::{AnyUserData, ExternalError, IntoLua, Lua, MetaMethod, Table, UserData, Value}; use super::Cell; @@ -14,7 +14,7 @@ pub struct Row { } impl Row { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, cells): (Table, Vec)| { Ok(Self { cells, ..Default::default() }) })?; @@ -22,7 +22,7 @@ impl Row { let row = lua.create_table()?; row.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(row) + row.into_lua(lua) } } diff --git a/yazi-plugin/src/elements/span.rs b/yazi-plugin/src/elements/span.rs index 98e2d756..e7a1ef74 100644 --- a/yazi-plugin/src/elements/span.rs +++ b/yazi-plugin/src/elements/span.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use mlua::{AnyUserData, ExternalError, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; +use mlua::{AnyUserData, ExternalError, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; use unicode_width::UnicodeWidthChar; const EXPECTED: &str = "expected a string or Span"; @@ -8,13 +8,13 @@ const EXPECTED: &str = "expected a string or Span"; pub struct Span(pub(super) ratatui::text::Span<'static>); impl Span { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, value): (Table, Value)| Span::try_from(value))?; let span = lua.create_table()?; span.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(span) + span.into_lua(lua) } pub(super) fn truncate(&mut self, max: usize) -> usize { diff --git a/yazi-plugin/src/elements/style.rs b/yazi-plugin/src/elements/style.rs index 11411d23..d42590a4 100644 --- a/yazi-plugin/src/elements/style.rs +++ b/yazi-plugin/src/elements/style.rs @@ -1,19 +1,19 @@ use std::str::FromStr; -use mlua::{AnyUserData, ExternalError, ExternalResult, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; +use mlua::{AnyUserData, ExternalError, ExternalResult, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; use yazi_shared::theme::Color; #[derive(Clone, Copy, Default)] pub struct Style(pub(super) ratatui::style::Style); impl Style { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, value): (Table, Value)| Self::try_from(value))?; let style = lua.create_table()?; style.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(style) + style.into_lua(lua) } } diff --git a/yazi-plugin/src/elements/table.rs b/yazi-plugin/src/elements/table.rs index 24f72851..cd591b15 100644 --- a/yazi-plugin/src/elements/table.rs +++ b/yazi-plugin/src/elements/table.rs @@ -1,4 +1,4 @@ -use mlua::{AnyUserData, ExternalError, Lua, MetaMethod, UserData, Value}; +use mlua::{AnyUserData, ExternalError, IntoLua, Lua, MetaMethod, UserData, Value}; use ratatui::widgets::StatefulWidget; use super::{Area, Row}; @@ -32,7 +32,7 @@ pub struct Table { } impl Table { - pub fn compose(lua: &Lua) -> mlua::Result { + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, seq): (mlua::Table, mlua::Table)| { let mut rows = Vec::with_capacity(seq.raw_len()); for v in seq.sequence_values::() { @@ -45,7 +45,7 @@ impl Table { let table = lua.create_table()?; table.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(table) + table.into_lua(lua) } pub fn selected_cell(&self) -> Option<&ratatui::text::Text> { diff --git a/yazi-plugin/src/elements/text.rs b/yazi-plugin/src/elements/text.rs index 1b764478..4bff0438 100644 --- a/yazi-plugin/src/elements/text.rs +++ b/yazi-plugin/src/elements/text.rs @@ -29,7 +29,7 @@ pub struct Text { } impl Text { - pub fn compose(lua: &Lua) -> mlua::Result
{ + pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, value): (Table, Value)| Text::try_from(value))?; let parse = lua.create_function(|_, code: mlua::String| { @@ -49,7 +49,7 @@ impl Text { ])?; text.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?)); - Ok(text) + text.into_lua(lua) } pub(super) fn render( diff --git a/yazi-plugin/src/elements/utils.rs b/yazi-plugin/src/elements/utils.rs new file mode 100644 index 00000000..27dc5beb --- /dev/null +++ b/yazi-plugin/src/elements/utils.rs @@ -0,0 +1,35 @@ +use mlua::{ExternalError, IntoLua, Lua, Value}; +use unicode_width::UnicodeWidthStr; + +use super::{Line, Span}; + +pub(super) struct Utils; + +impl Utils { + pub(super) fn width(lua: &Lua) -> mlua::Result { + let f = lua.create_function(|_, v: Value| match v { + Value::String(s) => { + let (mut acc, b) = (0, s.as_bytes()); + for c in b.utf8_chunks() { + acc += c.valid().width(); + if !c.invalid().is_empty() { + acc += 1; + } + } + Ok(acc) + } + Value::UserData(ud) => { + if let Ok(line) = ud.borrow::() { + Ok(line.inner.width()) + } else if let Ok(span) = ud.borrow::() { + Ok(span.0.width()) + } else { + Err("expected a string, Line, or Span".into_lua_err())? + } + } + _ => Err("expected a string, Line, or Span".into_lua_err())?, + })?; + + f.into_lua(lua) + } +} diff --git a/yazi-plugin/src/utils/text.rs b/yazi-plugin/src/utils/text.rs index 8edd26e2..e50a46ca 100644 --- a/yazi-plugin/src/utils/text.rs +++ b/yazi-plugin/src/utils/text.rs @@ -96,17 +96,20 @@ impl Utils { #[cfg(test)] mod tests { - use mlua::Value; + use mlua::chunk; use super::*; fn truncate(s: &str, max: usize, rtl: bool) -> String { let lua = Lua::new(); - let t = lua - .create_table_from([("max", Value::Integer(max as i64)), ("rtl", Value::Boolean(rtl))]) - .unwrap(); + let f = Utils::truncate(&lua).unwrap(); - Utils::truncate(&lua).unwrap().call((s, t)).unwrap() + lua + .load(chunk! { + return $f($s, { max = $max, rtl = $rtl }) + }) + .call(()) + .unwrap() } #[test]