refactor: unify rendering behavior with a new renderer (#4038)

This commit is contained in:
三咲雅 misaki masa 2026-06-11 20:44:22 +08:00 committed by GitHub
parent 07a5deb109
commit 9b920ed2e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 189 additions and 149 deletions

View file

@ -1 +1 @@
{"version":"0.2","language":"en","flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","peekable","ratatui","syntect","pbpaste","pbcopy","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","Konsole","Überzug","pkgs","pdftoppm","poppler","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","ffprobe","vframes","luma","obase","outln","errln","tmtheme","twox","cfgs","fstype","objc","rdev","runloop","exfat","rclone","DECRQSS","DECSCUSR","libvterm","Uninit","lockin","rposition","resvg","foldhash","tilded","futs","chdir","hashbrown","JEMALLOC","RUSTFLAGS","RDONLY","GETPATH","fcntl","casefold","inodes","Splatable","casefied","thiserror","memchr","memmem","russh","deadpool","keepalive","nodelay","publickey","deadpool","initing","treelize","TOCTOU","fellback","watchee","Textlike","sstr","pointee","writef","wakeup","nonblocking","sigwinch","timespec","termios","tcgetattr","tcsetattr","tcgetwinsize","rustix","codepoint","codepoints","Raterm","mimetypes","Mimelist"]}
{"words":["Punct","KEYMAP","splitn","crossterm","YAZI","peekable","ratatui","syntect","pbpaste","pbcopy","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","Konsole","Überzug","pkgs","pdftoppm","poppler","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","ffprobe","vframes","luma","obase","outln","errln","tmtheme","twox","cfgs","fstype","objc","rdev","runloop","exfat","rclone","DECRQSS","DECSCUSR","libvterm","Uninit","lockin","rposition","resvg","foldhash","tilded","futs","chdir","hashbrown","JEMALLOC","RUSTFLAGS","RDONLY","GETPATH","fcntl","casefold","inodes","Splatable","casefied","thiserror","memchr","memmem","russh","deadpool","keepalive","nodelay","publickey","deadpool","initing","treelize","TOCTOU","fellback","watchee","Textlike","sstr","pointee","writef","wakeup","nonblocking","sigwinch","timespec","termios","tcgetattr","tcsetattr","tcgetwinsize","rustix","codepoint","codepoints","Raterm","mimetypes","Mimelist","renderables","redrawer"],"language":"en","version":"0.2","flagWords":[]}

View file

@ -29,7 +29,7 @@ impl Actor for AcceptPayload {
drop(lock);
let kind = kind.to_owned();
succ!(Lives::scope(cx.core, || {
succ!(Lives::scope(cx.core, |_| {
let body = payload.body.into_lua(&LUA)?;
for (id, cb) in handlers {
if let Err(e) = runtime_scope!(LUA, &id, cb.call::<()>(body.clone())) {

View file

@ -23,7 +23,7 @@ impl Actor for Dnd {
let Some(size) = cx.term.as_ref().and_then(|t| t.size().ok()) else { succ!() };
let area = yazi_binding::elements::Rect::from(size);
let result = Lives::scope(cx.core, move || {
let result = Lives::scope(cx.core, move |_| {
runtime_scope!(LUA, "root", {
let root = LUA.globals().raw_get::<Table>("Root")?.call_method::<Table>("new", area)?;

View file

@ -16,7 +16,7 @@ impl Actor for Lua {
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
let chunk = LUA.load(&*form.code).set_name("anonymous");
let result = Lives::scope(cx.core, || {
let result = Lives::scope(cx.core, |_| {
runtime_scope!(LUA, "inline", Sendable::value_to_data(&LUA, chunk.eval()?))
});
succ!(result?);

View file

@ -24,7 +24,7 @@ impl Actor for Mouse {
let Some(size) = cx.term.as_ref().and_then(|t| t.size().ok()) else { succ!() };
let area = yazi_binding::elements::Rect::from(size);
let result = Lives::scope(cx.core, move || {
let result = Lives::scope(cx.core, move |_| {
runtime_scope!(LUA, "root", {
let root = LUA.globals().raw_get::<Table>("Root")?.call_method::<Table>("new", area)?;

View file

@ -43,7 +43,7 @@ impl Actor for PluginDo {
};
drop(loader);
let result = Lives::scope(cx.core, || {
let result = Lives::scope(cx.core, |_| {
if let Some(cb) = opt.callback {
cb(&LUA, plugin)
} else {

View file

@ -21,7 +21,7 @@ impl Actor for Reflow {
let Some(size) = cx.term.as_ref().and_then(|t| t.size().ok()) else { succ!() };
let mut layout = LAYOUT.get();
let result = Lives::scope(cx.core, || {
let result = Lives::scope(cx.core, |_| {
let comps = (form.reflow)((Position::ORIGIN, size).into())?;
for v in comps.sequence_values::<Value>() {

View file

@ -16,7 +16,7 @@ impl Preflight {
return Ok(opt.1);
};
Ok(Lives::scope(cx.core, || {
Ok(Lives::scope(cx.core, |_| {
let mut body = opt.1.into_lua(&LUA)?;
for (id, cb) in handlers {
match runtime_scope!(LUA, &id, cb.call::<Value>(&body)) {

View file

@ -3,3 +3,5 @@ extern crate self as yazi_actor;
yazi_macro::mod_pub!(app cmp confirm core help input lives mgr notify pick spot tasks which);
yazi_macro::mod_flat!(actor context);
pub fn init() { lives::init(); }

View file

@ -1,10 +1,12 @@
use std::ops::Deref;
use mlua::{AnyUserData, IntoLua, MetaMethod, UserData, UserDataMethods, Value};
use mlua::{AnyUserData, IntoLua, MetaMethod, UserData, UserDataMethods, UserDataRef, Value};
use paste::paste;
use super::{Lives, PtrCell};
pub(super) type CoreRef = UserDataRef<Core>;
pub(super) struct Core {
inner: PtrCell<yazi_core::Core>,

View file

@ -5,8 +5,8 @@ use yazi_binding::{Range, Style};
use yazi_config::THEME;
use yazi_shared::{path::AsPath, url::UrlLike};
use super::Lives;
use crate::lives::PtrCell;
use super::{FILE_CACHE, Lives};
use crate::lives::{CoreRef, PtrCell};
pub(super) struct File {
idx: usize,
@ -32,7 +32,7 @@ impl File {
) -> mlua::Result<AnyUserData> {
use hashbrown::hash_map::Entry;
Ok(match super::FILE_CACHE.borrow_mut().entry(PtrCell(&folder.files[idx])) {
Ok(match unsafe { (*FILE_CACHE.get()).assume_init_mut() }.entry(PtrCell(&folder.files[idx])) {
Entry::Occupied(oe) => oe.into_mut().clone(),
Entry::Vacant(ve) => {
let ud = Lives::scoped_userdata(Self { idx, folder: folder.into(), tab: tab.into() })?;
@ -71,9 +71,8 @@ impl UserData for File {
Ok(if me.is_dir() { me.folder.files.sizes.get(&me.urn()).copied() } else { Some(me.len) })
});
methods.add_method("mime", |lua, me, ()| {
lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|core: &yazi_core::Core| {
core.mgr.mimetype.get(&me.url).map(|s| lua.create_string(s)).transpose()
})?
let core: CoreRef = lua.named_registry_value("cx")?;
core.mgr.mimetype.get(&me.url).map(|s| lua.create_string(s)).transpose()
});
methods.add_method("prefix", |lua, me, ()| {
if !me.url.has_trail() {
@ -85,20 +84,18 @@ impl UserData for File {
Some(lua.create_string(comp.as_path().encoded_bytes())).transpose()
});
methods.add_method("style", |lua, me, ()| {
lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|core: &yazi_core::Core| {
let mime = core.mgr.mimetype.get(&me.url).unwrap_or_default();
THEME.filetype.match_style(me, mime).map(Style::from)
})
let core: CoreRef = lua.named_registry_value("cx")?;
let mime = core.mgr.mimetype.get(&me.url).unwrap_or_default();
Ok(THEME.filetype.match_style(me, mime).map(Style::from))
});
methods.add_method("is_yanked", |lua, me, ()| {
lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|core: &yazi_core::Core| {
if !core.mgr.yanked.contains(&me.url) {
0u8
} else if core.mgr.yanked.cut {
2u8
} else {
1u8
}
let core: CoreRef = lua.named_registry_value("cx")?;
Ok(if !core.mgr.yanked.contains(&me.url) {
0u8
} else if core.mgr.yanked.cut {
2u8
} else {
1u8
})
});
methods.add_method("is_marked", |_, me, ()| {
@ -115,31 +112,30 @@ impl UserData for File {
});
methods.add_method("is_selected", |_, me, ()| Ok(me.tab.selected.contains(&me.url)));
methods.add_method("found", |lua, me, ()| {
lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|core: &yazi_core::Core| {
let Some(finder) = &core.active().finder else {
return Ok(None);
};
let core: CoreRef = lua.named_registry_value("cx")?;
let Some(finder) = &core.active().finder else {
return Ok(None);
};
let Some(idx) = finder.matched_idx(&me.folder, me.urn()) else {
return Ok(None);
};
let Some(idx) = finder.matched_idx(&me.folder, me.urn()) else {
return Ok(None);
};
Some(lua.create_sequence_from([idx.into_lua(lua)?, finder.matched.len().into_lua(lua)?]))
.transpose()
})
lua.create_sequence_from([idx.into_lua(lua)?, finder.matched.len().into_lua(lua)?]).map(Some)
});
methods.add_method("highlights", |lua, me, ()| {
lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|core: &yazi_core::Core| {
let Some(finder) = &core.active().finder else {
return None;
};
if me.folder.url != me.tab.current.url {
return None;
}
let core: CoreRef = lua.named_registry_value("cx")?;
let Some(finder) = &core.active().finder else {
return Ok(None);
};
if me.folder.url != me.tab.current.url {
return Ok(None);
}
let Some(Some(h)) = me.url.name().map(|s| finder.filter.highlighted(s)) else {
return Ok(None);
};
let h = finder.filter.highlighted(me.url.name()?)?;
Some(h.into_iter().map(Range::from).collect::<Vec<_>>())
})
lua.create_sequence_from(h.into_iter().map(Range::from)).map(Some)
});
}
}

View file

@ -1,39 +1,37 @@
use std::cell::RefCell;
use std::mem::MaybeUninit;
use hashbrown::HashMap;
use mlua::{AnyUserData, UserData};
use scopeguard::defer;
use tracing::error;
use yazi_plugin::LUA;
use yazi_shim::cell::RoCell;
use super::{Core, PtrCell};
use crate::lives::MutCell;
static TO_DESTROY: RoCell<RefCell<Vec<AnyUserData>>> = RoCell::new_const(RefCell::new(Vec::new()));
pub(super) static FILE_CACHE: RoCell<RefCell<HashMap<PtrCell<yazi_fs::File>, AnyUserData>>> =
RoCell::new();
pub(super) static TO_DESTROY: MutCell<Vec<AnyUserData>> = MutCell::new(Vec::new());
pub(super) static FILE_CACHE: MutCell<MaybeUninit<HashMap<PtrCell<yazi_fs::File>, AnyUserData>>> =
MutCell::new(MaybeUninit::uninit());
pub struct Lives;
impl Lives {
pub fn scope<T, F>(core: &yazi_core::Core, f: F) -> mlua::Result<T>
pub fn scope<T, F>(core: &mut yazi_core::Core, f: F) -> mlua::Result<T>
where
F: FnOnce() -> mlua::Result<T>,
F: FnOnce(&mut yazi_core::Core) -> mlua::Result<T>,
{
FILE_CACHE.init(Default::default());
defer! { FILE_CACHE.drop(); }
let result = LUA.scope(|scope| {
scope.add_destructor(|| {
for ud in TO_DESTROY.borrow_mut().drain(..) {
defer! {
unsafe {
(*FILE_CACHE.get()).assume_init_mut().clear();
for ud in (*TO_DESTROY.get()).drain(..) {
ud.destroy().expect("failed to destruct scoped userdata");
}
});
}
}
LUA.set_named_registry_value("cx", scope.create_any_userdata_ref(core)?)?;
LUA.globals().raw_set("cx", Core::make(core)?)?;
f()
});
LUA.set_named_registry_value("cx", Core::make(core)?)?;
LUA.globals().raw_set("cx", Core::make(core)?)?;
let result = f(core);
if let Err(ref e) = result {
error!("{e}");
@ -46,7 +44,7 @@ impl Lives {
T: UserData + 'static,
{
let ud = LUA.create_userdata(data)?;
TO_DESTROY.borrow_mut().push(ud.clone());
unsafe { &mut *TO_DESTROY.get() }.push(ud.clone());
Ok(ud)
}
}

View file

@ -1 +1,5 @@
yazi_macro::mod_flat!(behavior core file files filter finder folder lives mode preference preview ptr selected tab tabs task tasks which yanked);
yazi_macro::mod_flat!(behavior core file files filter finder folder lives mode mut_cell preference preview ptr selected tab tabs task tasks which yanked);
pub(super) fn init() {
unsafe { FILE_CACHE.get().write(std::mem::MaybeUninit::new(<_>::default())) };
}

View file

@ -0,0 +1,11 @@
use std::cell::UnsafeCell;
pub(super) struct MutCell<T>(UnsafeCell<T>);
unsafe impl<T> Sync for MutCell<T> {}
impl<T> MutCell<T> {
pub(super) const fn new(value: T) -> Self { Self(UnsafeCell::new(value)) }
pub(super) fn get(&self) -> *mut T { self.0.get() }
}

View file

@ -1,7 +1,5 @@
use mlua::{IntoLua, Lua, Value};
use tracing::error;
use super::Renderable;
use crate::{Composer, ComposerGet, ComposerSet};
pub fn compose(p_get: ComposerGet, p_set: ComposerSet) -> Composer<ComposerGet, ComposerSet> {
@ -37,24 +35,3 @@ pub fn compose(p_get: ComposerGet, p_set: ComposerSet) -> Composer<ComposerGet,
Composer::with_parent(get, set, p_get, p_set)
}
pub fn render_once<F>(value: Value, buf: &mut ratatui::buffer::Buffer, trans: F)
where
F: FnOnce(yazi_config::popup::Position) -> ratatui::layout::Rect + Copy,
{
match value {
Value::Table(tbl) => {
for widget in tbl.sequence_values::<Renderable>() {
match widget {
Ok(w) => w.render_with(buf, trans),
Err(e) => error!("Failed to convert to renderable elements: {e}"),
}
}
}
Value::UserData(ud) => match Renderable::try_from(&ud) {
Ok(w) => w.render_with(buf, trans),
Err(e) => error!("Failed to convert to renderable element: {e}"),
},
_ => error!("Expected a renderable element, or a table of them, got: {value:?}"),
}
}

View file

@ -1 +1 @@
yazi_macro::mod_flat!(align area bar border cell clear color constraint edge elements fill gauge layout line list pad pos rect renderable row span table text wrap);
yazi_macro::mod_flat!(align area bar border cell clear color constraint edge elements fill gauge layout line list pad pos rect renderable renderables row span table text wrap);

View file

@ -0,0 +1,29 @@
use mlua::Value;
use tracing::error;
use crate::elements::Renderable;
pub struct Renderables;
impl Renderables {
pub fn reduce<F>(value: Value, mut reducer: F)
where
F: FnMut(Renderable),
{
match value {
Value::Table(tbl) => {
for element in tbl.sequence_values::<Renderable>() {
match element {
Ok(r) => reducer(r),
Err(e) => error!("Failed to convert to renderable elements: {e}"),
}
}
}
Value::UserData(ud) => match Renderable::try_from(&ud) {
Ok(w) => reducer(w),
Err(e) => error!("Failed to convert to renderable element: {e}"),
},
_ => error!("Expected a renderable element, or a table of them, got: {value:?}"),
}
}
}

View file

@ -30,8 +30,8 @@ impl App {
let collision = COLLISION.swap(false, Ordering::Relaxed);
let preview_rect = LAYOUT.get().preview;
term.draw(|f| {
_ = Lives::scope(&self.core, || {
runtime_scope!(LUA, "root", Ok(f.render_widget(Root::new(&self.core), f.area())))
_ = Lives::scope(&mut self.core, |core| {
runtime_scope!(LUA, "root", Ok(f.render_widget(Root::new(core), f.area())))
});
})?;
@ -58,10 +58,10 @@ impl App {
let _guard = scopeguard::guard(self.core.cursor(), |c| Self::routine(false, c));
term.draw_partial(|f| {
_ = Lives::scope(&self.core, || {
_ = Lives::scope(&mut self.core, |core| {
runtime_scope!(LUA, "root", {
f.render_widget(crate::tasks::Progress::new(&self.core), f.area());
f.render_widget(crate::notify::Notify::new(&self.core), f.area());
f.render_widget(crate::tasks::Progress::new(core), f.area());
f.render_widget(crate::notify::Notify::new(core), f.area());
Ok(())
})
});

View file

@ -4,7 +4,7 @@ static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
yazi_macro::mod_pub!(app cmp confirm help input mgr notify pick spot tasks which);
yazi_macro::mod_flat!(dispatcher executor logs panic root router signals);
yazi_macro::mod_flat!(dispatcher executor logs panic renderer root router signals);
#[tokio::main]
async fn main() -> anyhow::Result<()> {
@ -40,5 +40,7 @@ async fn main() -> anyhow::Result<()> {
yazi_dds::serve();
yazi_actor::init();
yazi_shared::LOCAL_SET.run_until(app::App::serve()).await
}

View file

@ -1,29 +1,24 @@
use mlua::{ObjectLike, Table};
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
use tracing::error;
use yazi_binding::elements::render_once;
use yazi_core::Core;
use yazi_plugin::LUA;
use crate::Renderer;
pub(crate) struct Modal<'a> {
core: &'a Core,
core: &'a mut Core,
}
impl<'a> Modal<'a> {
#[inline]
pub(crate) fn new(core: &'a Core) -> Self { Self { core } }
pub(crate) fn new(core: &'a mut Core) -> Self { Self { core } }
}
impl Widget for Modal<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
let mut f = || {
let area = yazi_binding::elements::Rect::from(area);
let root = LUA.globals().raw_get::<Table>("Modal")?.call_method::<Table>("new", area)?;
let result =
Renderer::new(self.core, "Modal").with_redrawer("children_redraw").render(area, buf);
render_once(root.call_method("children_redraw", ())?, buf, |p| self.core.mgr.area(p));
Ok::<_, mlua::Error>(())
};
if let Err(e) = f() {
if let Err(e) = result {
error!("Failed to redraw the `Modal` component:\n{e}");
}
}

44
yazi-fm/src/renderer.rs Normal file
View file

@ -0,0 +1,44 @@
use mlua::{ObjectLike, Table};
use ratatui::{buffer::Buffer, layout::Rect};
use yazi_binding::elements::Renderables;
use yazi_core::Core;
use yazi_plugin::LUA;
pub(super) struct Renderer<'a> {
core: &'a mut Core,
component: &'a str,
constructor: &'a str,
redrawer: &'a str,
}
impl<'a> Renderer<'a> {
pub(super) fn new(core: &'a mut Core, component: &'a str) -> Self {
Self { core, component, constructor: "new", redrawer: "redraw" }
}
pub(super) fn with_constructor(mut self, constructor: &'a str) -> Self {
self.constructor = constructor;
self
}
pub(super) fn with_redrawer(mut self, redrawer: &'a str) -> Self {
self.redrawer = redrawer;
self
}
pub(super) fn render(self, area: Rect, buf: &mut Buffer) -> mlua::Result<()> {
let area = yazi_binding::elements::Rect::from(area);
let value = LUA
.globals()
.raw_get::<Table>(self.component)?
.call_method::<Table>(self.constructor, area)?
.call_method("redraw", ())?;
Renderables::reduce(value, |element| {
element.render_with(buf, |p| self.core.mgr.area(p));
});
Ok::<_, mlua::Error>(())
}
}

View file

@ -1,18 +1,18 @@
use mlua::{ObjectLike, Table};
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
use tracing::error;
use yazi_binding::elements::render_once;
use yazi_core::Core;
use yazi_plugin::LUA;
use super::{cmp, confirm, help, input, mgr, pick, spot, tasks, which};
use crate::Renderer;
pub(super) struct Root<'a> {
core: &'a Core,
core: &'a mut Core,
}
impl<'a> Root<'a> {
pub(super) fn new(core: &'a Core) -> Self { Self { core } }
pub(super) fn new(core: &'a mut Core) -> Self { Self { core } }
pub(super) fn reflow(area: Rect) -> mlua::Result<Table> {
let area = yazi_binding::elements::Rect::from(area);
@ -23,14 +23,7 @@ impl<'a> Root<'a> {
impl Widget for Root<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
let mut f = || {
let area = yazi_binding::elements::Rect::from(area);
let root = LUA.globals().raw_get::<Table>("Root")?.call_method::<Table>("new", area)?;
render_once(root.call_method("redraw", ())?, buf, |p| self.core.mgr.area(p));
Ok::<_, mlua::Error>(())
};
if let Err(e) = f() {
if let Err(e) = Renderer::new(self.core, "Root").render(area, buf) {
error!("Failed to redraw the `Root` component:\n{e}");
}

View file

@ -1,29 +1,21 @@
use mlua::{ObjectLike, Table};
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
use tracing::error;
use yazi_binding::elements::render_once;
use yazi_core::Core;
use yazi_plugin::LUA;
use crate::Renderer;
pub(crate) struct List<'a> {
core: &'a Core,
core: &'a mut Core,
}
impl<'a> List<'a> {
#[inline]
pub(crate) fn new(core: &'a Core) -> Self { Self { core } }
pub(crate) fn new(core: &'a mut Core) -> Self { Self { core } }
}
impl Widget for List<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
let mut f = || {
let area = yazi_binding::elements::Rect::from(area);
let root = LUA.globals().raw_get::<Table>("Tasks")?.call_method::<Table>("new", area)?;
render_once(root.call_method("redraw", ())?, buf, |p| self.core.mgr.area(p));
Ok::<_, mlua::Error>(())
};
if let Err(e) = f() {
if let Err(e) = Renderer::new(self.core, "Tasks").render(area, buf) {
error!("Failed to redraw the `Tasks` component:\n{e}");
}
}

View file

@ -1,30 +1,24 @@
use mlua::{ObjectLike, Table};
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
use tracing::error;
use yazi_binding::elements::render_once;
use yazi_config::LAYOUT;
use yazi_core::Core;
use yazi_plugin::LUA;
use crate::Renderer;
pub(crate) struct Progress<'a> {
core: &'a Core,
core: &'a mut Core,
}
impl<'a> Progress<'a> {
pub(crate) fn new(core: &'a Core) -> Self { Self { core } }
pub(crate) fn new(core: &'a mut Core) -> Self { Self { core } }
}
impl Widget for Progress<'_> {
fn render(self, _: Rect, buf: &mut Buffer) {
let mut f = || {
let area = yazi_binding::elements::Rect::from(LAYOUT.get().progress);
let progress =
LUA.globals().raw_get::<Table>("Progress")?.call_method::<Table>("use", area)?;
let area = LAYOUT.get().progress;
let result = Renderer::new(self.core, "Progress").with_constructor("use").render(area, buf);
render_once(progress.call_method("redraw", ())?, buf, |p| self.core.mgr.area(p));
Ok::<_, mlua::Error>(())
};
if let Err(e) = f() {
if let Err(e) = result {
error!("Failed to redraw the `Progress` component:\n{e}");
}
}

View file

@ -5,11 +5,11 @@ use yazi_core::{Core, tasks::TASKS_PERCENT};
use crate::tasks::List;
pub(crate) struct Tasks<'a> {
core: &'a Core,
core: &'a mut Core,
}
impl<'a> Tasks<'a> {
pub(crate) fn new(core: &'a Core) -> Self { Self { core } }
pub(crate) fn new(core: &'a mut Core) -> Self { Self { core } }
pub(super) fn area(area: Rect) -> Rect {
let chunk = layout::Layout::vertical([

View file

@ -123,7 +123,7 @@ pub(super) fn redraw(lua: &Lua) -> mlua::Result<Value> {
Value::UserData(ud) => lua.create_sequence_from([ud]),
_ => {
error!(
"Failed to `redraw()` the `{}` component: expected a table or UserData",
"Failed to `redraw()` the `{}` component: expected an element or a table of them",
id.display(),
);
lua.create_table()

View file

@ -55,6 +55,7 @@ impl<T> RoCell<T> {
self.inner.get().replace(MaybeUninit::uninit()).assume_init()
}
}
}
impl<T> Default for RoCell<T> {