feat: add the area() API for renderable elements (#1667)

This commit is contained in:
三咲雅 · Misaki Masa 2024-09-21 01:47:34 +08:00 committed by GitHub
parent ac196f211e
commit 1a1820cf77
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 54 additions and 15 deletions

View file

@ -4,7 +4,7 @@ function M:peek()
local limit = self.area.h
local paths, sizes = {}, {}
local files, bound, code = self:list_files({ "-p", tostring(self.file.url) }, self.skip, limit)
local files, bound, code = self.list_files({ "-p", tostring(self.file.url) }, self.skip, limit)
if code ~= 0 then
return ya.preview_widgets(self, {
ui.Paragraph(self.area, {
@ -53,7 +53,7 @@ function M:seek(units)
end
end
function M:spawn_7z(args)
function M.spawn_7z(args)
local last_error = nil
local try = function(name)
local stdout = args[1] == "l" and Command.PIPED or Command.NULL
@ -88,8 +88,8 @@ end
--- 1: failed to spawn
--- 2: wrong password
--- 3: partial success
function M:list_files(args, skip, limit)
local child = self:spawn_7z { "l", "-ba", "-slt", table.unpack(args) }
function M.list_files(args, skip, limit)
local child = M.spawn_7z { "l", "-ba", "-slt", table.unpack(args) }
if not child then
return {}, 0, 1
end
@ -98,7 +98,7 @@ function M:list_files(args, skip, limit)
local key, value = "", ""
repeat
local next, event = child:read_line()
if event == 1 and self:is_encrypted(next) then
if event == 1 and M.is_encrypted(next) then
code = 2
break
elseif event == 1 then
@ -145,8 +145,8 @@ end
--- 1: failed to spawn
--- 2: wrong password
--- 3: partial success
function M:list_meta(args)
local child = self:spawn_7z { "l", "-slt", table.unpack(args) }
function M.list_meta(args)
local child = M.spawn_7z { "l", "-slt", table.unpack(args) }
if not child then
return nil, 1
end
@ -157,7 +157,7 @@ function M:list_meta(args)
i = i + 1
local next, event = child:read_line()
if event == 1 and self:is_encrypted(next) then
if event == 1 and M.is_encrypted(next) then
code = 2
break
elseif event == 1 then
@ -178,8 +178,8 @@ function M:list_meta(args)
return typ ~= "" and typ or nil, code
end
function M:is_encrypted(s) return s:find(" Wrong password", 1, true) end
function M.is_encrypted(s) return s:find(" Wrong password", 1, true) end
function M:is_tar(url) return require("archive"):list_meta { "-p", tostring(url) } == "tar" end
function M.is_tar(url) return M.list_meta { "-p", tostring(url) } == "tar" end
return M

View file

@ -48,13 +48,13 @@ function M:try_with(from, pwd, to)
end
local archive = require("archive")
local child, code = archive:spawn_7z { "x", "-aou", "-p" .. pwd, "-o" .. tostring(tmp), tostring(from) }
local child, code = archive.spawn_7z { "x", "-aou", "-p" .. pwd, "-o" .. tostring(tmp), tostring(from) }
if not child then
fail("Spawn `7z` and `7zz` both commands failed, error code %s", code)
end
local output, err = child:wait_with_output()
if output and output.status.code == 2 and archive:is_encrypted(output.stderr) then
if output and output.status.code == 2 and archive.is_encrypted(output.stderr) then
fs.remove("dir_clean", tmp)
return true -- Need to retry
end
@ -77,7 +77,7 @@ function M:tidy(from, to, tmp)
end
local only = #outs == 1
if only and not outs[1].cha.is_dir and require("archive"):is_tar(outs[1].url) then
if only and not outs[1].cha.is_dir and require("archive").is_tar(outs[1].url) then
self:entry { tostring(outs[1].url), tostring(to) }
fs.remove("file", outs[1].url)
fs.remove("dir", tmp)

View file

@ -42,8 +42,13 @@ impl Bar {
impl UserData for Bar {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
crate::impl_area_method!(methods);
crate::impl_style_method!(methods, style);
methods.add_function("direction", |_, (ud, symbol): (AnyUserData, u8)| {
ud.borrow_mut::<Self>()?.direction = Borders::from_bits_truncate(symbol);
Ok(ud)
});
methods.add_function("symbol", |_, (ud, symbol): (AnyUserData, String)| {
ud.borrow_mut::<Self>()?.symbol = symbol;
Ok(ud)

View file

@ -55,8 +55,13 @@ impl Border {
impl UserData for Border {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
crate::impl_area_method!(methods);
crate::impl_style_method!(methods, style);
methods.add_function("position", |_, (ud, position): (AnyUserData, u8)| {
ud.borrow_mut::<Self>()?.position = ratatui::widgets::Borders::from_bits_truncate(position);
Ok(ud)
});
methods.add_function("type", |_, (ud, value): (AnyUserData, u8)| {
ud.borrow_mut::<Self>()?.type_ = match value {
ROUNDED => ratatui::widgets::BorderType::Rounded,

View file

@ -55,7 +55,11 @@ impl Renderable for Clear {
fn clone_render(&self, buf: &mut ratatui::buffer::Buffer) { Box::new(*self).render(buf); }
}
impl UserData for Clear {}
impl UserData for Clear {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
crate::impl_area_method!(methods);
}
}
#[inline]
const fn is_overlapping(a: &Rect, b: &Rect) -> bool {

View file

@ -25,6 +25,7 @@ impl Gauge {
impl UserData for Gauge {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
crate::impl_area_method!(methods);
crate::impl_style_method!(methods, style);
methods.add_function("percent", |_, (ud, percent): (AnyUserData, u8)| {

View file

@ -22,7 +22,11 @@ impl List {
}
}
impl UserData for List {}
impl UserData for List {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
crate::impl_area_method!(methods);
}
}
impl Renderable for List {
fn area(&self) -> ratatui::layout::Rect { self.area }

View file

@ -58,6 +58,7 @@ impl Paragraph {
impl UserData for Paragraph {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
crate::impl_area_method!(methods);
crate::impl_style_method!(methods, style);
crate::impl_style_shorthands!(methods, style);
@ -76,6 +77,9 @@ impl UserData for Paragraph {
};
Ok(ud)
});
methods.add_method("max_width", |_, me, ()| {
Ok(me.text.lines.iter().take(me.area.height as usize).map(|l| l.width()).max())
});
}
}

View file

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