refactor: turn RectRef, PaddingRef, PositionRef into Rect, Padding, Position (#1730)

This commit is contained in:
三咲雅 · Misaki Masa 2024-10-04 20:23:36 +08:00 committed by GitHub
parent 8c5d8aa589
commit 3150fb10f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 200 additions and 240 deletions

View file

@ -22,7 +22,7 @@ impl App {
let Ok(evt) = yazi_plugin::bindings::MouseEvent::cast(&LUA, event) else { return }; let Ok(evt) = yazi_plugin::bindings::MouseEvent::cast(&LUA, event) else { return };
let res = Lives::scope(&self.cx, move |_| { let res = Lives::scope(&self.cx, move |_| {
let area = yazi_plugin::elements::Rect::cast(&LUA, size)?; let area = yazi_plugin::elements::Rect::from(size);
let root = LUA.globals().raw_get::<_, Table>("Root")?.call_method::<_, Table>("new", area)?; let root = LUA.globals().raw_get::<_, Table>("Root")?.call_method::<_, Table>("new", area)?;
if matches!(event.kind, MouseEventKind::Down(_) if MANAGER.mouse_events.draggable()) { if matches!(event.kind, MouseEventKind::Down(_) if MANAGER.mouse_events.draggable()) {

View file

@ -1,7 +1,7 @@
use mlua::{Table, TableExt}; use mlua::{Table, TableExt};
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget}; use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
use tracing::error; use tracing::error;
use yazi_plugin::{LUA, bindings::Cast, elements::render_widgets}; use yazi_plugin::{LUA, elements::render_widgets};
use super::{completion, confirm, input, select, tasks, which}; use super::{completion, confirm, input, select, tasks, which};
use crate::{Ctx, components, help}; use crate::{Ctx, components, help};
@ -17,7 +17,7 @@ impl<'a> Root<'a> {
impl<'a> Widget for Root<'a> { impl<'a> Widget for Root<'a> {
fn render(self, area: Rect, buf: &mut Buffer) { fn render(self, area: Rect, buf: &mut Buffer) {
let mut f = || { let mut f = || {
let area = yazi_plugin::elements::Rect::cast(&LUA, area)?; let area = yazi_plugin::elements::Rect::from(area);
let root = LUA.globals().raw_get::<_, Table>("Root")?.call_method::<_, Table>("new", area)?; let root = LUA.globals().raw_get::<_, Table>("Root")?.call_method::<_, Table>("new", area)?;
render_widgets(root.call_method("render", ())?, buf); render_widgets(root.call_method("render", ())?, buf);

View file

@ -1,11 +1,11 @@
use mlua::{AnyUserData, Lua, Table, UserData}; use mlua::{AnyUserData, Lua, Table, UserData};
use ratatui::widgets::Borders; use ratatui::widgets::Borders;
use super::{RectRef, Renderable}; use super::{Rect, Renderable};
#[derive(Clone)] #[derive(Clone)]
pub struct Bar { pub struct Bar {
area: ratatui::layout::Rect, area: Rect,
direction: ratatui::widgets::Borders, direction: ratatui::widgets::Borders,
symbol: String, symbol: String,
@ -14,13 +14,13 @@ pub struct Bar {
impl Bar { impl Bar {
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> { pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
let new = lua.create_function(|_, (_, area, direction): (Table, RectRef, u8)| { let new = lua.create_function(|_, (_, area, direction): (Table, Rect, u8)| {
Ok(Self { Ok(Self {
area: *area, area,
direction: Borders::from_bits_truncate(direction), direction: Borders::from_bits_truncate(direction),
symbol: Default::default(), symbol: Default::default(),
style: Default::default(), style: Default::default(),
}) })
})?; })?;
@ -57,7 +57,7 @@ impl UserData for Bar {
} }
impl Renderable for Bar { impl Renderable for Bar {
fn area(&self) -> ratatui::layout::Rect { self.area } fn area(&self) -> ratatui::layout::Rect { *self.area }
fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) { fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) {
if self.area.area() == 0 { if self.area.area() == 0 {

View file

@ -1,7 +1,7 @@
use mlua::{AnyUserData, Lua, Table, UserData}; use mlua::{AnyUserData, Lua, Table, UserData};
use ratatui::widgets::{Borders, Widget}; use ratatui::widgets::{Borders, Widget};
use super::{RectRef, Renderable}; use super::{Rect, Renderable};
// Type // Type
const PLAIN: u8 = 0; const PLAIN: u8 = 0;
@ -13,7 +13,7 @@ const QUADRANT_OUTSIDE: u8 = 5;
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct Border { pub struct Border {
area: ratatui::layout::Rect, area: Rect,
position: ratatui::widgets::Borders, position: ratatui::widgets::Borders,
type_: ratatui::widgets::BorderType, type_: ratatui::widgets::BorderType,
@ -22,9 +22,9 @@ pub struct Border {
impl Border { impl Border {
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> { pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
let new = lua.create_function(|_, (_, area, position): (Table, RectRef, u8)| { let new = lua.create_function(|_, (_, area, position): (Table, Rect, u8)| {
Ok(Border { Ok(Border {
area: *area, area,
position: ratatui::widgets::Borders::from_bits_truncate(position), position: ratatui::widgets::Borders::from_bits_truncate(position),
..Default::default() ..Default::default()
}) })
@ -77,14 +77,14 @@ impl UserData for Border {
} }
impl Renderable for Border { impl Renderable for Border {
fn area(&self) -> ratatui::layout::Rect { self.area } fn area(&self) -> ratatui::layout::Rect { *self.area }
fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) { fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) {
ratatui::widgets::Block::default() ratatui::widgets::Block::default()
.borders(self.position) .borders(self.position)
.border_type(self.type_) .border_type(self.type_)
.border_style(self.style) .border_style(self.style)
.render(self.area, buf); .render(*self.area, buf);
} }
fn clone_render(&self, buf: &mut ratatui::buffer::Buffer) { Box::new(self.clone()).render(buf); } fn clone_render(&self, buf: &mut ratatui::buffer::Buffer) { Box::new(self.clone()).render(buf); }

View file

@ -1,21 +1,20 @@
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use mlua::{Lua, Table, UserData}; use mlua::{Lua, Table, UserData};
use ratatui::layout::Rect;
use yazi_adapter::ADAPTOR; use yazi_adapter::ADAPTOR;
use super::{RectRef, Renderable}; use super::{Rect, Renderable};
pub static COLLISION: AtomicBool = AtomicBool::new(false); pub static COLLISION: AtomicBool = AtomicBool::new(false);
#[derive(Clone, Copy, Default)] #[derive(Clone, Copy, Default)]
pub struct Clear { pub struct Clear {
pub area: ratatui::layout::Rect, pub area: Rect,
} }
impl Clear { impl Clear {
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> { pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
let new = lua.create_function(|_, (_, area): (Table, RectRef)| Ok(Clear { area: *area }))?; let new = lua.create_function(|_, (_, area): (Table, Rect)| Ok(Clear { area }))?;
let clear = lua.create_table()?; let clear = lua.create_table()?;
clear.set_metatable(Some(lua.create_table_from([("__call", new)])?)); clear.set_metatable(Some(lua.create_table_from([("__call", new)])?));
@ -25,13 +24,13 @@ impl Clear {
} }
impl ratatui::widgets::Widget for Clear { impl ratatui::widgets::Widget for Clear {
fn render(self, area: Rect, buf: &mut ratatui::prelude::Buffer) fn render(self, area: ratatui::layout::Rect, buf: &mut ratatui::prelude::Buffer)
where where
Self: Sized, Self: Sized,
{ {
ratatui::widgets::Clear.render(area, buf); ratatui::widgets::Clear.render(area, buf);
let Some(r) = ADAPTOR.shown_load().and_then(|r| overlap(&area, &r)) else { let Some(r) = ADAPTOR.shown_load().and_then(|r| overlap(area, r)) else {
return; return;
}; };
@ -46,10 +45,10 @@ impl ratatui::widgets::Widget for Clear {
} }
impl Renderable for Clear { impl Renderable for Clear {
fn area(&self) -> ratatui::layout::Rect { self.area } fn area(&self) -> ratatui::layout::Rect { *self.area }
fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) { fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) {
<Self as ratatui::widgets::Widget>::render(Default::default(), self.area, buf); <Self as ratatui::widgets::Widget>::render(Default::default(), *self.area, buf);
} }
fn clone_render(&self, buf: &mut ratatui::buffer::Buffer) { Box::new(*self).render(buf); } fn clone_render(&self, buf: &mut ratatui::buffer::Buffer) { Box::new(*self).render(buf); }
@ -62,11 +61,11 @@ impl UserData for Clear {
} }
#[inline] #[inline]
const fn is_overlapping(a: &Rect, b: &Rect) -> bool { const fn is_overlapping(a: ratatui::layout::Rect, b: ratatui::layout::Rect) -> bool {
a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y
} }
fn overlap(a: &Rect, b: &Rect) -> Option<Rect> { fn overlap(a: ratatui::layout::Rect, b: ratatui::layout::Rect) -> Option<ratatui::layout::Rect> {
if !is_overlapping(a, b) { if !is_overlapping(a, b) {
return None; return None;
} }
@ -75,5 +74,5 @@ fn overlap(a: &Rect, b: &Rect) -> Option<Rect> {
let y = a.y.max(b.y); let y = a.y.max(b.y);
let width = (a.x + a.width).min(b.x + b.width) - x; let width = (a.x + a.width).min(b.x + b.width) - x;
let height = (a.y + a.height).min(b.y + b.height) - y; let height = (a.y + a.height).min(b.y + b.height) - y;
Some(Rect { x, y, width, height }) Some(ratatui::layout::Rect { x, y, width, height })
} }

View file

@ -5,35 +5,36 @@ pub struct Constraint(pub(super) ratatui::layout::Constraint);
impl Constraint { impl Constraint {
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> { pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
let constraint = lua.create_table()?; let constraint = lua.create_table_from([
(
constraint.raw_set( "Min",
"Min", lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Min(n))))?,
lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Min(n))))?, ),
)?; (
constraint.raw_set( "Max",
"Max", lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Max(n))))?,
lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Max(n))))?, ),
)?; (
constraint.raw_set( "Length",
"Length", lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Length(n))))?,
lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Length(n))))?, ),
)?; (
constraint.raw_set( "Percentage",
"Percentage", lua.create_function(|_, n: u16| {
lua Ok(Constraint(ratatui::layout::Constraint::Percentage(n)))
.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Percentage(n))))?, })?,
)?; ),
constraint.raw_set( (
"Ratio", "Ratio",
lua.create_function(|_, (a, b): (u32, u32)| { lua.create_function(|_, (a, b): (u32, u32)| {
Ok(Constraint(ratatui::layout::Constraint::Ratio(a, b))) Ok(Constraint(ratatui::layout::Constraint::Ratio(a, b)))
})?, })?,
)?; ),
constraint.raw_set( (
"Fill", "Fill",
lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Fill(n))))?, lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Fill(n))))?,
)?; ),
])?;
ui.raw_set("Constraint", constraint) ui.raw_set("Constraint", constraint)
} }

View file

@ -6,10 +6,6 @@ use crate::cast_to_renderable;
pub fn pour(lua: &Lua) -> mlua::Result<()> { pub fn pour(lua: &Lua) -> mlua::Result<()> {
let ui = lua.create_table()?; let ui = lua.create_table()?;
// Register
super::Padding::register(lua)?;
super::Rect::register(lua)?;
// Install // Install
super::Bar::install(lua, &ui)?; super::Bar::install(lua, &ui)?;
super::Border::install(lua, &ui)?; super::Border::install(lua, &ui)?;

View file

@ -1,12 +1,12 @@
use mlua::{AnyUserData, ExternalError, Lua, Table, UserData, UserDataMethods, Value}; use mlua::{AnyUserData, ExternalError, Lua, Table, UserData, UserDataMethods, Value};
use ratatui::widgets::Widget; use ratatui::widgets::Widget;
use super::{RectRef, Renderable, Span}; use super::{Rect, Renderable, Span};
use crate::elements::Style; use crate::elements::Style;
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct Gauge { pub struct Gauge {
area: ratatui::layout::Rect, area: Rect,
ratio: f64, ratio: f64,
label: Option<ratatui::text::Span<'static>>, label: Option<ratatui::text::Span<'static>>,
@ -18,7 +18,7 @@ impl Gauge {
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> { pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
ui.raw_set( ui.raw_set(
"Gauge", "Gauge",
lua.create_function(|_, area: RectRef| Ok(Gauge { area: *area, ..Default::default() }))?, lua.create_function(|_, area: Rect| Ok(Gauge { area, ..Default::default() }))?,
) )
} }
} }
@ -59,7 +59,7 @@ impl UserData for Gauge {
} }
impl Renderable for Gauge { impl Renderable for Gauge {
fn area(&self) -> ratatui::layout::Rect { self.area } fn area(&self) -> ratatui::layout::Rect { *self.area }
fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) { fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) {
let mut gauge = ratatui::widgets::Gauge::default() let mut gauge = ratatui::widgets::Gauge::default()
@ -71,7 +71,7 @@ impl Renderable for Gauge {
gauge = gauge.label(s) gauge = gauge.label(s)
} }
gauge.render(self.area, buf); gauge.render(*self.area, buf);
} }
fn clone_render(&self, buf: &mut ratatui::buffer::Buffer) { Box::new(self.clone()).render(buf) } fn clone_render(&self, buf: &mut ratatui::buffer::Buffer) { Box::new(self.clone()).render(buf) }

View file

@ -1,7 +1,6 @@
use mlua::{AnyUserData, Lua, Table, UserData, UserDataMethods}; use mlua::{AnyUserData, Lua, Table, UserData, UserDataMethods};
use super::{Constraint, Rect, RectRef}; use super::{Constraint, Rect};
use crate::bindings::Cast;
const HORIZONTAL: bool = true; const HORIZONTAL: bool = true;
const VERTICAL: bool = false; const VERTICAL: bool = false;
@ -61,7 +60,7 @@ impl UserData for Layout {
ud.borrow_mut::<Self>()?.constraints = value.into_iter().map(|c| c.0).collect(); ud.borrow_mut::<Self>()?.constraints = value.into_iter().map(|c| c.0).collect();
Ok(ud) Ok(ud)
}); });
methods.add_method("split", |lua, me, value: RectRef| { methods.add_method("split", |lua, me, value: Rect| {
let mut layout = ratatui::layout::Layout::new( let mut layout = ratatui::layout::Layout::new(
if me.direction == VERTICAL { if me.direction == VERTICAL {
ratatui::layout::Direction::Vertical ratatui::layout::Direction::Vertical
@ -76,11 +75,7 @@ impl UserData for Layout {
layout = layout.vertical_margin(margin.vertical); layout = layout.vertical_margin(margin.vertical);
} }
let mut chunks = Vec::with_capacity(me.constraints.len()); lua.create_sequence_from(layout.split(*value).iter().map(|chunk| Rect::from(*chunk)))
for chunk in &*layout.split(*value) {
chunks.push(Rect::cast(lua, *chunk)?);
}
Ok(chunks)
}); });
} }
} }

View file

@ -1,12 +1,12 @@
use mlua::{ExternalError, FromLua, Lua, Table, UserData, Value}; use mlua::{ExternalError, FromLua, Lua, Table, UserData, Value};
use ratatui::widgets::Widget; use ratatui::widgets::Widget;
use super::{Line, RectRef, Renderable, Span}; use super::{Line, Rect, Renderable, Span};
// --- List // --- List
#[derive(Clone)] #[derive(Clone)]
pub struct List { pub struct List {
area: ratatui::layout::Rect, area: Rect,
inner: ratatui::widgets::List<'static>, inner: ratatui::widgets::List<'static>,
} }
@ -15,8 +15,8 @@ impl List {
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> { pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
ui.raw_set( ui.raw_set(
"List", "List",
lua.create_function(|_, (area, items): (RectRef, Vec<ListItem>)| { lua.create_function(|_, (area, items): (Rect, Vec<ListItem>)| {
Ok(Self { area: *area, inner: ratatui::widgets::List::new(items) }) Ok(Self { area, inner: ratatui::widgets::List::new(items) })
})?, })?,
) )
} }
@ -29,10 +29,10 @@ impl UserData for List {
} }
impl Renderable for List { impl Renderable for List {
fn area(&self) -> ratatui::layout::Rect { self.area } fn area(&self) -> ratatui::layout::Rect { *self.area }
fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) { fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) {
self.inner.render(self.area, buf); self.inner.render(*self.area, buf);
} }
fn clone_render(&self, buf: &mut ratatui::buffer::Buffer) { Box::new(self.clone()).render(buf) } fn clone_render(&self, buf: &mut ratatui::buffer::Buffer) { Box::new(self.clone()).render(buf) }

View file

@ -1,58 +1,43 @@
use mlua::{AnyUserData, Lua, Table, UserDataFields, UserDataRef}; use std::ops::Deref;
use crate::bindings::Cast; use mlua::{FromLua, Lua, Table, UserData};
pub type PaddingRef<'lua> = UserDataRef<'lua, ratatui::widgets::Padding>; #[derive(Clone, Copy, FromLua)]
pub struct Padding(ratatui::widgets::Padding);
pub struct Padding; impl Deref for Padding {
type Target = ratatui::widgets::Padding;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl Padding { impl Padding {
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> { pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
let new = lua.create_function(|lua, args: (Table, u16, u16, u16, u16)| { let new = lua.create_function(|_, args: (Table, u16, u16, u16, u16)| {
Self::cast(lua, ratatui::widgets::Padding::new(args.1, args.2, args.3, args.4)) Ok(Self(ratatui::widgets::Padding::new(args.1, args.2, args.3, args.4)))
})?; })?;
let padding = lua.create_table_from([ let padding = lua.create_table_from([
( (
"left", "left",
lua.create_function(|lua, left: u16| { lua.create_function(|_, left: u16| Ok(Self(ratatui::widgets::Padding::left(left))))?,
Self::cast(lua, ratatui::widgets::Padding::left(left))
})?,
), ),
( (
"right", "right",
lua.create_function(|lua, right: u16| { lua.create_function(|_, right: u16| Ok(Self(ratatui::widgets::Padding::right(right))))?,
Self::cast(lua, ratatui::widgets::Padding::right(right))
})?,
),
(
"top",
lua
.create_function(|lua, top: u16| Self::cast(lua, ratatui::widgets::Padding::top(top)))?,
), ),
("top", lua.create_function(|_, top: u16| Ok(Self(ratatui::widgets::Padding::top(top))))?),
( (
"bottom", "bottom",
lua.create_function(|lua, bottom: u16| { lua
Self::cast(lua, ratatui::widgets::Padding::bottom(bottom)) .create_function(|_, bottom: u16| Ok(Self(ratatui::widgets::Padding::bottom(bottom))))?,
})?,
),
(
"x",
lua.create_function(|lua, x: u16| {
Self::cast(lua, ratatui::widgets::Padding::new(x, x, 0, 0))
})?,
),
(
"y",
lua.create_function(|lua, y: u16| {
Self::cast(lua, ratatui::widgets::Padding::new(0, 0, y, y))
})?,
), ),
("x", lua.create_function(|_, x: u16| Ok(Self(ratatui::widgets::Padding::new(x, x, 0, 0))))?),
("y", lua.create_function(|_, y: u16| Ok(Self(ratatui::widgets::Padding::new(0, 0, y, y))))?),
( (
"xy", "xy",
lua.create_function(|lua, xy: u16| { lua
Self::cast(lua, ratatui::widgets::Padding::new(xy, xy, xy, xy)) .create_function(|_, xy: u16| Ok(Self(ratatui::widgets::Padding::new(xy, xy, xy, xy))))?,
})?,
), ),
])?; ])?;
@ -60,20 +45,13 @@ impl Padding {
ui.raw_set("Padding", padding) ui.raw_set("Padding", padding)
} }
pub fn register(lua: &Lua) -> mlua::Result<()> {
// TODO: remove this
lua.register_userdata_type::<ratatui::widgets::Padding>(|reg| {
reg.add_field_method_get("left", |_, me| Ok(me.left));
reg.add_field_method_get("right", |_, me| Ok(me.right));
reg.add_field_method_get("top", |_, me| Ok(me.top));
reg.add_field_method_get("bottom", |_, me| Ok(me.bottom));
})
}
} }
impl Cast<ratatui::widgets::Padding> for Padding { impl UserData for Padding {
fn cast(lua: &Lua, data: ratatui::widgets::Padding) -> mlua::Result<AnyUserData> { fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
lua.create_any_userdata(data) fields.add_field_method_get("left", |_, me| Ok(me.left));
fields.add_field_method_get("right", |_, me| Ok(me.right));
fields.add_field_method_get("top", |_, me| Ok(me.top));
fields.add_field_method_get("bottom", |_, me| Ok(me.bottom));
} }
} }

View file

@ -2,7 +2,7 @@ use ansi_to_tui::IntoText;
use mlua::{AnyUserData, ExternalError, ExternalResult, IntoLua, Lua, Table, UserData}; use mlua::{AnyUserData, ExternalError, ExternalResult, IntoLua, Lua, Table, UserData};
use ratatui::widgets::Widget; use ratatui::widgets::Widget;
use super::{Line, RectRef, Renderable}; use super::{Line, Rect, Renderable};
// Alignment // Alignment
const LEFT: u8 = 0; const LEFT: u8 = 0;
@ -14,9 +14,9 @@ pub const WRAP_NO: u8 = 0;
pub const WRAP: u8 = 1; pub const WRAP: u8 = 1;
pub const WRAP_TRIM: u8 = 2; pub const WRAP_TRIM: u8 = 2;
#[derive(Clone, Debug, Default)] #[derive(Clone, Default)]
pub struct Paragraph { pub struct Paragraph {
pub area: ratatui::layout::Rect, pub area: Rect,
pub text: ratatui::text::Text<'static>, pub text: ratatui::text::Text<'static>,
pub style: ratatui::style::Style, pub style: ratatui::style::Style,
@ -26,16 +26,12 @@ pub struct Paragraph {
impl Paragraph { impl Paragraph {
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> { pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
let new = lua.create_function(|_, (_, area, lines): (Table, RectRef, Vec<Line>)| { let new = lua.create_function(|_, (_, area, lines): (Table, Rect, Vec<Line>)| {
Ok(Paragraph { Ok(Paragraph { area, text: lines.into_iter().map(|s| s.0).collect(), ..Default::default() })
area: *area,
text: lines.into_iter().map(|s| s.0).collect(),
..Default::default()
})
})?; })?;
let parse = lua.create_function(|_, (area, code): (RectRef, mlua::String)| { let parse = lua.create_function(|_, (area, code): (Rect, mlua::String)| {
Ok(Paragraph { area: *area, text: code.into_text().into_lua_err()?, ..Default::default() }) Ok(Paragraph { area, text: code.into_text().into_lua_err()?, ..Default::default() })
})?; })?;
let paragraph = lua.create_table_from([ let paragraph = lua.create_table_from([
@ -84,7 +80,7 @@ impl UserData for Paragraph {
} }
impl Renderable for Paragraph { impl Renderable for Paragraph {
fn area(&self) -> ratatui::layout::Rect { self.area } fn area(&self) -> ratatui::layout::Rect { *self.area }
fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) { fn render(self: Box<Self>, buf: &mut ratatui::buffer::Buffer) {
let mut p = ratatui::widgets::Paragraph::new(self.text).style(self.style); let mut p = ratatui::widgets::Paragraph::new(self.text).style(self.style);
@ -93,7 +89,7 @@ impl Renderable for Paragraph {
p = p.wrap(ratatui::widgets::Wrap { trim: self.wrap == WRAP_TRIM }); p = p.wrap(ratatui::widgets::Wrap { trim: self.wrap == WRAP_TRIM });
} }
p.alignment(self.alignment).render(self.area, buf); p.alignment(self.alignment).render(*self.area, buf);
} }
fn clone_render(&self, buf: &mut ratatui::buffer::Buffer) { Box::new(self.clone()).render(buf) } fn clone_render(&self, buf: &mut ratatui::buffer::Buffer) { Box::new(self.clone()).render(buf) }

View file

@ -1,39 +1,37 @@
use mlua::{AnyUserData, Lua, Table, UserDataFields, UserDataRef}; use std::ops::Deref;
use crate::bindings::Cast; use mlua::{FromLua, Lua, Table, UserData, UserDataFields};
pub type PositionRef<'lua> = UserDataRef<'lua, ratatui::layout::Position>; #[derive(Clone, Copy, FromLua)]
pub struct Position(ratatui::layout::Position);
pub struct Position; impl Deref for Position {
type Target = ratatui::layout::Position;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl From<ratatui::layout::Rect> for Position {
fn from(rect: ratatui::layout::Rect) -> Self { Self(rect.as_position()) }
}
impl Position { impl Position {
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> { pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
let new = lua.create_function(|lua, (_, args): (Table, Table)| { let new = lua.create_function(|_, (_, args): (Table, Table)| {
Position::cast(lua, ratatui::layout::Position { Ok(Self(ratatui::layout::Position { x: args.raw_get("x")?, y: args.raw_get("y")? }))
x: args.raw_get("x")?,
y: args.raw_get("y")?,
})
})?; })?;
let position = let position = lua.create_table_from([("default", Self(Default::default()))])?;
lua.create_table_from([("default", Position::cast(lua, Default::default())?)])?;
position.set_metatable(Some(lua.create_table_from([("__call", new)])?)); position.set_metatable(Some(lua.create_table_from([("__call", new)])?));
ui.raw_set("Position", position) ui.raw_set("Position", position)
} }
pub fn register(lua: &Lua) -> mlua::Result<()> {
// TODO: remove this
lua.register_userdata_type::<ratatui::layout::Position>(|reg| {
reg.add_field_method_get("x", |_, me| Ok(me.x));
reg.add_field_method_get("y", |_, me| Ok(me.y));
})
}
} }
impl Cast<ratatui::layout::Position> for Position { impl UserData for Position {
fn cast(lua: &Lua, data: ratatui::layout::Position) -> mlua::Result<AnyUserData> { fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
lua.create_any_userdata(data) fields.add_field_method_get("x", |_, me| Ok(me.x));
fields.add_field_method_get("y", |_, me| Ok(me.y));
} }
} }

View file

@ -1,72 +1,71 @@
use mlua::{AnyUserData, Lua, Table, UserDataFields, UserDataMethods, UserDataRef}; use std::ops::Deref;
use super::{PaddingRef, Position, PositionRef}; use mlua::{FromLua, Lua, Table, UserData};
use crate::bindings::Cast;
pub type RectRef<'lua> = UserDataRef<'lua, ratatui::layout::Rect>; use super::{Padding, Position};
pub struct Rect; #[derive(Clone, Copy, Default, FromLua)]
pub struct Rect(ratatui::layout::Rect);
impl Deref for Rect {
type Target = ratatui::layout::Rect;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl From<ratatui::layout::Rect> for Rect {
fn from(rect: ratatui::layout::Rect) -> Self { Self(rect) }
}
impl From<ratatui::layout::Size> for Rect {
fn from(size: ratatui::layout::Size) -> Self {
Self(ratatui::layout::Rect { x: 0, y: 0, width: size.width, height: size.height })
}
}
impl Rect { impl Rect {
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> { pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
let new = lua.create_function(|lua, (_, args): (Table, Table)| { let new = lua.create_function(|_, (_, args): (Table, Table)| {
Rect::cast(lua, ratatui::layout::Rect { Ok(Self(ratatui::layout::Rect {
x: args.raw_get("x")?, x: args.raw_get("x")?,
y: args.raw_get("y")?, y: args.raw_get("y")?,
width: args.raw_get("w")?, width: args.raw_get("w")?,
height: args.raw_get("h")?, height: args.raw_get("h")?,
}) }))
})?; })?;
let rect = let rect = lua.create_table_from([("default", Self(ratatui::layout::Rect::default()))])?;
lua.create_table_from([("default", Rect::cast(lua, ratatui::layout::Rect::default())?)])?;
rect.set_metatable(Some(lua.create_table_from([("__call", new)])?)); rect.set_metatable(Some(lua.create_table_from([("__call", new)])?));
ui.raw_set("Rect", rect) ui.raw_set("Rect", rect)
} }
pub fn register(lua: &Lua) -> mlua::Result<()> {
// TODO: remove this
lua.register_userdata_type::<ratatui::layout::Rect>(|reg| {
reg.add_field_method_get("x", |_, me| Ok(me.x));
reg.add_field_method_get("y", |_, me| Ok(me.y));
reg.add_field_method_get("w", |_, me| Ok(me.width));
reg.add_field_method_get("h", |_, me| Ok(me.height));
reg.add_field_method_get("left", |_, me| Ok(me.left()));
reg.add_field_method_get("right", |_, me| Ok(me.right()));
reg.add_field_method_get("top", |_, me| Ok(me.top()));
reg.add_field_method_get("bottom", |_, me| Ok(me.bottom()));
reg.add_method("padding", |lua, me, padding: PaddingRef| {
let mut r = *me;
r.x = r.x.saturating_add(padding.left);
r.y = r.y.saturating_add(padding.top);
r.width = r.width.saturating_sub(padding.left + padding.right);
r.height = r.height.saturating_sub(padding.top + padding.bottom);
Rect::cast(lua, r)
});
reg.add_method("position", |lua, me, ()| Position::cast(lua, me.as_position()));
reg.add_method("contains", |_, me, position: PositionRef| Ok(me.contains(*position)));
})
}
} }
impl Cast<ratatui::layout::Rect> for Rect { impl UserData for Rect {
fn cast(lua: &Lua, data: ratatui::layout::Rect) -> mlua::Result<AnyUserData> { fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
lua.create_any_userdata(data) fields.add_field_method_get("x", |_, me| Ok(me.x));
} fields.add_field_method_get("y", |_, me| Ok(me.y));
} fields.add_field_method_get("w", |_, me| Ok(me.width));
fields.add_field_method_get("h", |_, me| Ok(me.height));
impl Cast<ratatui::layout::Size> for Rect { fields.add_field_method_get("left", |_, me| Ok(me.left()));
fn cast(lua: &Lua, data: ratatui::layout::Size) -> mlua::Result<AnyUserData> { fields.add_field_method_get("right", |_, me| Ok(me.right()));
lua.create_any_userdata(ratatui::layout::Rect { fields.add_field_method_get("top", |_, me| Ok(me.top()));
x: 0, fields.add_field_method_get("bottom", |_, me| Ok(me.bottom()));
y: 0, }
width: data.width,
height: data.height, fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
}) methods.add_method("padding", |_, me, padding: Padding| {
let mut r = **me;
r.x = r.x.saturating_add(padding.left);
r.y = r.y.saturating_add(padding.top);
r.width = r.width.saturating_sub(padding.left + padding.right);
r.height = r.height.saturating_sub(padding.top + padding.bottom);
Ok(Self(r))
});
methods.add_method("position", |_, me, ()| Ok(Position::from(**me)));
methods.add_method("contains", |_, me, position: Position| Ok(me.contains(*position)));
} }
} }

View file

@ -93,7 +93,7 @@ impl Highlighter {
} }
Ok(if plain { Ok(if plain {
Text::from(replace_to_printable(&after.join(""), PREVIEW.tab_size)) Text::from(replace_to_printable(&after, PREVIEW.tab_size))
} else { } else {
Self::highlight_with(before, after, syntax.unwrap()).await? Self::highlight_with(before, after, syntax.unwrap()).await?
}) })

View file

@ -23,7 +23,7 @@ pub async fn fetch(name: &str, files: Vec<yazi_shared::fs::File>) -> mlua::Resul
} }
plugin.raw_set("skip", 0)?; plugin.raw_set("skip", 0)?;
plugin.raw_set("area", Rect::cast(&lua, LAYOUT.load().preview)?)?; plugin.raw_set("area", Rect::from(LAYOUT.load().preview))?;
plugin.raw_set("files", files)?; plugin.raw_set("files", files)?;
Handle::current().block_on(plugin.call_async_method("fetch", ())) Handle::current().block_on(plugin.call_async_method("fetch", ()))

View file

@ -23,7 +23,6 @@ pub fn slim_lua(name: &str) -> mlua::Result<Lua> {
let ui = lua.create_table()?; let ui = lua.create_table()?;
elements::Line::install(&lua, &ui)?; elements::Line::install(&lua, &ui)?;
elements::Paragraph::install(&lua, &ui)?; elements::Paragraph::install(&lua, &ui)?;
elements::Rect::register(&lua)?;
elements::Rect::install(&lua, &ui)?; elements::Rect::install(&lua, &ui)?;
elements::Span::install(&lua, &ui)?; elements::Span::install(&lua, &ui)?;

View file

@ -40,7 +40,7 @@ pub fn peek(
plugin.raw_set("file", File::cast(&lua, file)?)?; plugin.raw_set("file", File::cast(&lua, file)?)?;
plugin.raw_set("_mime", mime)?; plugin.raw_set("_mime", mime)?;
plugin.raw_set("skip", skip)?; plugin.raw_set("skip", skip)?;
plugin.raw_set("area", Rect::cast(&lua, LAYOUT.load().preview)?)?; plugin.raw_set("area", Rect::from(LAYOUT.load().preview))?;
plugin.raw_set("window", Window::default())?; plugin.raw_set("window", Window::default())?;
if ct2.is_cancelled() { Ok(()) } else { plugin.call_async_method("peek", ()).await } if ct2.is_cancelled() { Ok(()) } else { plugin.call_async_method("peek", ()).await }
@ -68,7 +68,7 @@ pub fn peek_sync(cmd: &Cmd, file: yazi_shared::fs::File, mime: Cow<'static, str>
plugin.raw_set("file", File::cast(&LUA, file)?)?; plugin.raw_set("file", File::cast(&LUA, file)?)?;
plugin.raw_set("_mime", mime)?; plugin.raw_set("_mime", mime)?;
plugin.raw_set("skip", skip)?; plugin.raw_set("skip", skip)?;
plugin.raw_set("area", Rect::cast(&LUA, LAYOUT.load().preview)?)?; plugin.raw_set("area", Rect::from(LAYOUT.load().preview))?;
plugin.raw_set("window", Window::default())?; plugin.raw_set("window", Window::default())?;
plugin.call_method("peek", ()) plugin.call_method("peek", ())
}); });

View file

@ -18,7 +18,7 @@ pub async fn preload(name: &str, file: yazi_shared::fs::File) -> mlua::Result<u8
}; };
plugin.raw_set("skip", 0)?; plugin.raw_set("skip", 0)?;
plugin.raw_set("area", Rect::cast(&lua, LAYOUT.load().preview)?)?; plugin.raw_set("area", Rect::from(LAYOUT.load().preview))?;
plugin.raw_set("file", File::cast(&lua, file)?)?; plugin.raw_set("file", File::cast(&lua, file)?)?;
Handle::current().block_on(plugin.call_async_method("preload", ())) Handle::current().block_on(plugin.call_async_method("preload", ()))

View file

@ -7,7 +7,7 @@ use crate::{LUA, Opt, OptCallback, bindings::Cast, elements::Rect, file::File};
pub fn seek_sync(cmd: &Cmd, file: yazi_shared::fs::File, units: i16) { pub fn seek_sync(cmd: &Cmd, file: yazi_shared::fs::File, units: i16) {
let cb: OptCallback = Box::new(move |_, plugin| { let cb: OptCallback = Box::new(move |_, plugin| {
plugin.raw_set("file", File::cast(&LUA, file)?)?; plugin.raw_set("file", File::cast(&LUA, file)?)?;
plugin.raw_set("area", Rect::cast(&LUA, LAYOUT.load().preview)?)?; plugin.raw_set("area", Rect::from(LAYOUT.load().preview))?;
plugin.call_method("seek", units) plugin.call_method("seek", units)
}); });

View file

@ -29,14 +29,15 @@ macro_rules! impl_style_method {
#[macro_export] #[macro_export]
macro_rules! impl_area_method { macro_rules! impl_area_method {
($methods:ident) => { ($methods:ident) => {
use $crate::{bindings::Cast, elements::{Rect, RectRef}}; use mlua::IntoLua;
use $crate::elements::Rect;
$methods.add_function("area", |lua, (ud, area): (mlua::AnyUserData, Option<RectRef>)| { $methods.add_function("area", |lua, (ud, area): (mlua::AnyUserData, Option<Rect>)| {
if let Some(r) = area { if let Some(r) = area {
ud.borrow_mut::<Self>()?.area = *r; ud.borrow_mut::<Self>()?.area = r;
Ok(ud) ud.into_lua(lua)
} else { } else {
Rect::cast(lua, ud.borrow::<Self>()?.area) ud.borrow::<Self>()?.area.into_lua(lua)
} }
}); });
}; };

View file

@ -7,7 +7,6 @@ use yazi_dds::Sendable;
use yazi_shared::{Layer, emit, event::{Cmd, Data}, render}; use yazi_shared::{Layer, emit, event::{Cmd, Data}, render};
use super::Utils; use super::Utils;
use crate::elements::RectRef;
impl Utils { impl Utils {
fn parse_args(t: Table) -> mlua::Result<HashMap<String, Data>> { fn parse_args(t: Table) -> mlua::Result<HashMap<String, Data>> {
@ -45,13 +44,13 @@ impl Utils {
match id { match id {
"current" => { "current" => {
LAYOUT.store(Arc::new(yazi_config::Layout { LAYOUT.store(Arc::new(yazi_config::Layout {
current: *c.raw_get::<_, RectRef>("_area")?, current: *c.raw_get::<_, crate::elements::Rect>("_area")?,
..*LAYOUT.load_full() ..*LAYOUT.load_full()
})); }));
} }
"preview" => { "preview" => {
LAYOUT.store(Arc::new(yazi_config::Layout { LAYOUT.store(Arc::new(yazi_config::Layout {
preview: *c.raw_get::<_, RectRef>("_area")?, preview: *c.raw_get::<_, crate::elements::Rect>("_area")?,
..*LAYOUT.load_full() ..*LAYOUT.load_full()
})); }));
} }

View file

@ -1,18 +1,18 @@
use mlua::{IntoLuaMulti, Lua, Table, Value}; use mlua::{IntoLua, Lua, Table, Value};
use yazi_adapter::{ADAPTOR, Image}; use yazi_adapter::{ADAPTOR, Image};
use super::Utils; use super::Utils;
use crate::{bindings::Cast, elements::{Rect, RectRef}, url::UrlRef}; use crate::{elements::Rect, url::UrlRef};
impl Utils { impl Utils {
pub(super) fn image(lua: &Lua, ya: &Table) -> mlua::Result<()> { pub(super) fn image(lua: &Lua, ya: &Table) -> mlua::Result<()> {
ya.raw_set( ya.raw_set(
"image_show", "image_show",
lua.create_async_function(|lua, (url, rect): (UrlRef, RectRef)| async move { lua.create_async_function(|lua, (url, rect): (UrlRef, Rect)| async move {
if let Ok(area) = ADAPTOR.image_show(&url, *rect).await { if let Ok(area) = ADAPTOR.image_show(&url, *rect).await {
Rect::cast(lua, area)?.into_lua_multi(lua) Rect::from(area).into_lua(lua)
} else { } else {
Value::Nil.into_lua_multi(lua) Value::Nil.into_lua(lua)
} }
})?, })?,
)?; )?;

View file

@ -3,7 +3,7 @@ use yazi_config::{PREVIEW, preview::PreviewWrap};
use yazi_shared::{Layer, PeekError, emit, event::Cmd}; use yazi_shared::{Layer, PeekError, emit, event::Cmd};
use super::Utils; use super::Utils;
use crate::{bindings::Window, cast_to_renderable, elements::{Paragraph, RectRef, Renderable, WRAP, WRAP_NO}, external::Highlighter, file::FileRef}; use crate::{bindings::Window, cast_to_renderable, elements::{Paragraph, Rect, Renderable, WRAP, WRAP_NO}, external::Highlighter, file::FileRef};
pub struct PreviewLock { pub struct PreviewLock {
pub url: yazi_shared::fs::Url, pub url: yazi_shared::fs::Url,
@ -37,7 +37,7 @@ impl Utils {
ya.raw_set( ya.raw_set(
"preview_code", "preview_code",
lua.create_async_function(|lua, t: Table| async move { lua.create_async_function(|lua, t: Table| async move {
let area: RectRef = t.raw_get("area")?; let area: Rect = t.raw_get("area")?;
let mut lock = PreviewLock::try_from(t)?; let mut lock = PreviewLock::try_from(t)?;
let text = match Highlighter::new(&lock.url).highlight(lock.skip, *area).await { let text = match Highlighter::new(&lock.url).highlight(lock.skip, *area).await {
@ -49,7 +49,7 @@ impl Utils {
}; };
lock.data = vec![Box::new(Paragraph { lock.data = vec![Box::new(Paragraph {
area: *area, area,
text, text,
wrap: if PREVIEW.wrap == PreviewWrap::Yes { WRAP } else { WRAP_NO }, wrap: if PREVIEW.wrap == PreviewWrap::Yes { WRAP } else { WRAP_NO },
..Default::default() ..Default::default()

View file

@ -28,11 +28,11 @@ pub fn strip_trailing_newline(mut s: String) -> String {
s s
} }
pub fn replace_to_printable(s: &str, tab_size: u8) -> String { pub fn replace_to_printable(s: &[String], tab_size: u8) -> String {
let mut buf = Vec::new(); let mut buf = Vec::new();
buf.try_reserve_exact(s.len() | 15).unwrap_or_else(|_| panic!()); buf.try_reserve_exact(s.iter().map(|s| s.len()).sum::<usize>() | 15).unwrap_or_else(|_| panic!());
for &b in s.as_bytes() { for &b in s.iter().flat_map(|s| s.as_bytes()) {
match b { match b {
b'\n' => buf.push(b'\n'), b'\n' => buf.push(b'\n'),
b'\t' => { b'\t' => {

View file

@ -14,14 +14,13 @@ impl Transliterator for &[u8] {
} }
let (ascii, rest) = self.split_at(ascii_len); let (ascii, rest) = self.split_at(ascii_len);
let ascii = unsafe { str::from_utf8_unchecked(ascii) };
// Reserve a bit more space to avoid reallocations on longer transliterations // Reserve a bit more space to avoid reallocations on longer transliterations
// but instead of `+ 16` uses `| 15` to stay in the smallest allocation bucket // but instead of `+ 16` uses `| 15` to stay in the smallest allocation bucket
// for short strings // for short strings
let mut out = String::new(); let mut out = String::new();
out.try_reserve_exact(self.len() | 15).unwrap_or_else(|_| panic!()); out.try_reserve_exact(self.len() | 15).unwrap_or_else(|_| panic!());
out.push_str(ascii); out.push_str(unsafe { str::from_utf8_unchecked(ascii) });
for c in String::from_utf8_lossy(rest).chars() { for c in String::from_utf8_lossy(rest).chars() {
if let Some(s) = super::lookup(c) { if let Some(s) = super::lookup(c) {