mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
refactor: unify rendering behavior with a new renderer (#4038)
This commit is contained in:
parent
07a5deb109
commit
9b920ed2e3
27 changed files with 189 additions and 149 deletions
|
|
@ -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":[]}
|
||||
|
|
@ -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())) {
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -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?);
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>() {
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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(); }
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())) };
|
||||
}
|
||||
|
|
|
|||
11
yazi-actor/src/lives/mut_cell.rs
Normal file
11
yazi-actor/src/lives/mut_cell.rs
Normal 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() }
|
||||
}
|
||||
|
|
@ -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:?}"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
29
yazi-binding/src/elements/renderables.rs
Normal file
29
yazi-binding/src/elements/renderables.rs
Normal 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:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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(())
|
||||
})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
44
yazi-fm/src/renderer.rs
Normal 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>(())
|
||||
}
|
||||
}
|
||||
|
|
@ -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}");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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([
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ impl<T> RoCell<T> {
|
|||
self.inner.get().replace(MaybeUninit::uninit()).assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<T> Default for RoCell<T> {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue