From 25c96557edbc856523056ce67e5920cd3c3c076c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Thu, 8 Feb 2024 16:05:37 +0800 Subject: [PATCH] feat: allows access to complete app data for all tabs (#644) --- yazi-core/src/manager/tabs.rs | 21 ++--- yazi-fm/src/app/commands/update_progress.rs | 11 +-- yazi-fm/src/lives/active.rs | 76 ------------------ yazi-fm/src/lives/config.rs | 34 ++++++++ yazi-fm/src/lives/file.rs | 11 ++- yazi-fm/src/lives/files.rs | 19 +++-- yazi-fm/src/lives/folder.rs | 45 ++++++----- yazi-fm/src/lives/lives.rs | 34 +++----- yazi-fm/src/lives/mod.rs | 10 ++- yazi-fm/src/lives/mode.rs | 33 ++++++++ yazi-fm/src/lives/preview.rs | 40 ++++++++++ yazi-fm/src/lives/tab.rs | 46 +++++++++++ yazi-fm/src/lives/tabs.rs | 88 +++++++-------------- yazi-fm/src/lives/tasks.rs | 31 +++++--- yazi-shared/src/ro_cell.rs | 7 ++ 15 files changed, 287 insertions(+), 219 deletions(-) delete mode 100644 yazi-fm/src/lives/active.rs create mode 100644 yazi-fm/src/lives/config.rs create mode 100644 yazi-fm/src/lives/mode.rs create mode 100644 yazi-fm/src/lives/preview.rs create mode 100644 yazi-fm/src/lives/tab.rs diff --git a/yazi-core/src/manager/tabs.rs b/yazi-core/src/manager/tabs.rs index 4b580ef5..2cfb8859 100644 --- a/yazi-core/src/manager/tabs.rs +++ b/yazi-core/src/manager/tabs.rs @@ -1,3 +1,5 @@ +use std::ops::{Deref, DerefMut}; + use yazi_config::BOOT; use yazi_shared::fs::Url; @@ -46,18 +48,19 @@ impl Tabs { } impl Tabs { - #[inline] - pub fn len(&self) -> usize { self.items.len() } - - #[inline] - pub fn iter(&self) -> impl Iterator { self.items.iter() } - - #[inline] - pub fn iter_mut(&mut self) -> impl Iterator { self.items.iter_mut() } - #[inline] pub fn active(&self) -> &Tab { &self.items[self.idx] } #[inline] pub(super) fn active_mut(&mut self) -> &mut Tab { &mut self.items[self.idx] } } + +impl Deref for Tabs { + type Target = Vec; + + fn deref(&self) -> &Self::Target { &self.items } +} + +impl DerefMut for Tabs { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.items } +} diff --git a/yazi-fm/src/app/commands/update_progress.rs b/yazi-fm/src/app/commands/update_progress.rs index 2ab49a79..ed2756b4 100644 --- a/yazi-fm/src/app/commands/update_progress.rs +++ b/yazi-fm/src/app/commands/update_progress.rs @@ -43,15 +43,16 @@ impl App { return; }; - Lives::partial_scope(&self.cx, |_| { + _ = Lives::scope(&self.cx, |_| { for patch in Progress::partial_render(term.current_buffer_mut()) { - term.backend_mut().draw(patch.iter().map(|(x, y, cell)| (*x, *y, cell))).ok(); + term.backend_mut().draw(patch.iter().map(|(x, y, cell)| (*x, *y, cell)))?; if let Some((x, y)) = self.cx.cursor() { - term.show_cursor().ok(); - term.set_cursor(x, y).ok(); + term.show_cursor()?; + term.set_cursor(x, y)?; } - term.backend_mut().flush().ok(); + term.backend_mut().flush()?; } + Ok(()) }); } } diff --git a/yazi-fm/src/lives/active.rs b/yazi-fm/src/lives/active.rs deleted file mode 100644 index 09785287..00000000 --- a/yazi-fm/src/lives/active.rs +++ /dev/null @@ -1,76 +0,0 @@ -use mlua::{AnyUserData, Lua, MetaMethod, UserDataFields, UserDataMethods, Value}; - -use super::Folder; - -pub(super) struct Active<'a, 'b> { - scope: &'b mlua::Scope<'a, 'a>, - - inner: &'a yazi_core::tab::Tab, -} - -impl<'a, 'b> Active<'a, 'b> { - pub(super) fn register(lua: &Lua) -> mlua::Result<()> { - lua.register_userdata_type::(|reg| { - reg.add_field_method_get("is_select", |_, me| Ok(me.is_select())); - reg.add_field_method_get("is_unset", |_, me| Ok(me.is_unset())); - reg.add_field_method_get("is_visual", |_, me| Ok(me.is_visual())); - reg.add_method("pending", |_, me, (idx, state): (usize, bool)| Ok(me.pending(idx, state))); - - reg.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.to_string())); - })?; - - lua.register_userdata_type::(|reg| { - reg.add_field_method_get("sort_by", |_, me| Ok(me.sort_by.to_string())); - reg.add_field_method_get("sort_sensitive", |_, me| Ok(me.sort_sensitive)); - reg.add_field_method_get("sort_reverse", |_, me| Ok(me.sort_reverse)); - reg.add_field_method_get("sort_dir_first", |_, me| Ok(me.sort_dir_first)); - - reg.add_field_method_get("linemode", |_, me| Ok(me.linemode.to_owned())); - reg.add_field_method_get("show_hidden", |_, me| Ok(me.show_hidden)); - })?; - - lua.register_userdata_type::(|reg| { - reg.add_field_method_get("skip", |_, me| Ok(me.skip)); - reg.add_field_function_get("folder", |_, me| me.named_user_value::("folder")); - })?; - - Ok(()) - } -} - -impl<'a, 'b> Active<'a, 'b> { - pub(crate) fn new(scope: &'b mlua::Scope<'a, 'a>, inner: &'a yazi_core::tab::Tab) -> Self { - Self { scope, inner } - } - - pub(crate) fn make(&self) -> mlua::Result> { - let ud = self.scope.create_any_userdata_ref(self.inner)?; - ud.set_named_user_value("mode", self.scope.create_any_userdata_ref(&self.inner.mode)?)?; - ud.set_named_user_value("conf", self.scope.create_any_userdata_ref(&self.inner.conf)?)?; - ud.set_named_user_value( - "parent", - self.inner.parent.as_ref().and_then(|p| Folder::make(self.scope, p).ok()), - )?; - ud.set_named_user_value("current", Folder::make(self.scope, &self.inner.current)?)?; - ud.set_named_user_value("preview", self.preview(self.inner)?)?; - - Ok(ud) - } - - fn preview(&self, tab: &'a yazi_core::tab::Tab) -> mlua::Result> { - let inner = &tab.preview; - - let ud = self.scope.create_any_userdata_ref(inner)?; - ud.set_named_user_value( - "folder", - tab - .current - .hovered() - .filter(|&f| f.is_dir()) - .and_then(|f| tab.history(&f.url)) - .and_then(|f| Folder::make(self.scope, f).ok()), - )?; - - Ok(ud) - } -} diff --git a/yazi-fm/src/lives/config.rs b/yazi-fm/src/lives/config.rs new file mode 100644 index 00000000..ccdb5490 --- /dev/null +++ b/yazi-fm/src/lives/config.rs @@ -0,0 +1,34 @@ +use std::ops::Deref; + +use mlua::{AnyUserData, Lua, UserDataFields}; + +use super::SCOPE; + +pub(super) struct Config { + inner: *const yazi_core::tab::Config, +} + +impl Deref for Config { + type Target = yazi_core::tab::Config; + + fn deref(&self) -> &Self::Target { unsafe { &*self.inner } } +} + +impl Config { + #[inline] + pub(super) fn make(inner: &yazi_core::tab::Config) -> mlua::Result> { + SCOPE.create_any_userdata(Self { inner }) + } + + pub(super) fn register(lua: &Lua) -> mlua::Result<()> { + lua.register_userdata_type::(|reg| { + reg.add_field_method_get("sort_by", |_, me| Ok(me.sort_by.to_string())); + reg.add_field_method_get("sort_sensitive", |_, me| Ok(me.sort_sensitive)); + reg.add_field_method_get("sort_reverse", |_, me| Ok(me.sort_reverse)); + reg.add_field_method_get("sort_dir_first", |_, me| Ok(me.sort_dir_first)); + + reg.add_field_method_get("linemode", |_, me| Ok(me.linemode.to_owned())); + reg.add_field_method_get("show_hidden", |_, me| Ok(me.show_hidden)); + }) + } +} diff --git a/yazi-fm/src/lives/file.rs b/yazi-fm/src/lives/file.rs index 806f8af4..bf2dbe87 100644 --- a/yazi-fm/src/lives/file.rs +++ b/yazi-fm/src/lives/file.rs @@ -1,11 +1,11 @@ use std::ops::Deref; -use mlua::{IntoLua, Lua, UserDataFields, UserDataMethods}; +use mlua::{AnyUserData, IntoLua, Lua, UserDataFields, UserDataMethods}; use yazi_config::THEME; use yazi_plugin::{bindings::{Cast, Cha, Icon, Range}, elements::Style, url::Url}; use yazi_shared::MIME_DIR; -use super::CtxRef; +use super::{CtxRef, SCOPE}; pub(super) struct File { idx: usize, @@ -20,7 +20,12 @@ impl Deref for File { impl File { #[inline] - pub(super) fn new(idx: usize, folder: &yazi_core::folder::Folder) -> Self { Self { idx, folder } } + pub(super) fn make( + idx: usize, + folder: &yazi_core::folder::Folder, + ) -> mlua::Result> { + SCOPE.create_any_userdata(Self { idx, folder }) + } pub(super) fn register(lua: &Lua) -> mlua::Result<()> { lua.register_userdata_type::(|reg| { diff --git a/yazi-fm/src/lives/files.rs b/yazi-fm/src/lives/files.rs index 50e4c781..2724c33f 100644 --- a/yazi-fm/src/lives/files.rs +++ b/yazi-fm/src/lives/files.rs @@ -1,8 +1,8 @@ use std::ops::{Deref, Range}; -use mlua::{Lua, MetaMethod, UserDataMethods}; +use mlua::{AnyUserData, Lua, MetaMethod, UserDataMethods}; -use super::File; +use super::{File, SCOPE}; pub(super) struct Files { folder: *const yazi_core::folder::Folder, @@ -17,20 +17,23 @@ impl Deref for Files { impl Files { #[inline] - pub(super) fn new(folder: &yazi_core::folder::Folder, window: Range) -> Self { - Self { folder, window } + pub(super) fn make( + folder: &yazi_core::folder::Folder, + window: Range, + ) -> mlua::Result> { + SCOPE.create_any_userdata(Self { folder, window }) } pub(super) fn register(lua: &Lua) -> mlua::Result<()> { lua.register_userdata_type::(|reg| { reg.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.window.end - me.window.start)); - reg.add_meta_method(MetaMethod::Index, |lua, me, mut key: usize| { - key += me.window.start; - if key > me.window.end || key == 0 { + reg.add_meta_method(MetaMethod::Index, |_, me, mut idx: usize| { + idx += me.window.start; + if idx > me.window.end || idx == 0 { Ok(None) } else { - Some(lua.create_any_userdata(File::new(key - 1, me.folder()))).transpose() + Some(File::make(idx - 1, me.folder())).transpose() } }); })?; diff --git a/yazi-fm/src/lives/folder.rs b/yazi-fm/src/lives/folder.rs index 92a2dd65..18a9bf7c 100644 --- a/yazi-fm/src/lives/folder.rs +++ b/yazi-fm/src/lives/folder.rs @@ -1,42 +1,45 @@ +use std::ops::Deref; + use mlua::{AnyUserData, Lua, UserDataFields}; use yazi_config::LAYOUT; use yazi_plugin::{bindings::Cast, url::Url}; -use super::{File, Files}; +use super::{File, Files, SCOPE}; -pub(super) struct Folder; +pub(super) struct Folder { + inner: *const yazi_core::folder::Folder, +} + +impl Deref for Folder { + type Target = yazi_core::folder::Folder; + + fn deref(&self) -> &Self::Target { unsafe { &*self.inner } } +} impl Folder { + #[inline] + pub(super) fn make(inner: &yazi_core::folder::Folder) -> mlua::Result> { + SCOPE.create_any_userdata(Self { inner }) + } + pub(super) fn register(lua: &Lua) -> mlua::Result<()> { - lua.register_userdata_type::(|reg| { + lua.register_userdata_type::(|reg| { reg.add_field_method_get("cwd", |lua, me| Url::cast(lua, me.cwd.clone())); - reg.add_field_method_get("files", |lua, me| { - lua.create_any_userdata(Files::new(me, 0..me.files.len())) - }); - reg.add_field_method_get("window", |lua, me| { - lua.create_any_userdata(Files::new( + reg.add_field_method_get("files", |_, me| Files::make(me, 0..me.files.len())); + reg.add_field_method_get("window", |_, me| { + Files::make( me, me.offset..me.files.len().min(me.offset + LAYOUT.load().preview.height as usize), - )) + ) }); reg.add_field_method_get("offset", |_, me| Ok(me.offset)); reg.add_field_method_get("cursor", |_, me| Ok(me.cursor)); - reg.add_field_method_get("hovered", |lua, me| { - me.hovered().map(|_| lua.create_any_userdata(File::new(me.cursor, me))).transpose() + reg.add_field_method_get("hovered", |_, me| { + me.hovered().map(|_| File::make(me.cursor, me)).transpose() }); })?; Ok(()) } } - -impl Folder { - #[inline] - pub(crate) fn make<'a>( - scope: &mlua::Scope<'a, 'a>, - inner: &'a yazi_core::folder::Folder, - ) -> mlua::Result> { - scope.create_any_userdata_ref(inner) - } -} diff --git a/yazi-fm/src/lives/lives.rs b/yazi-fm/src/lives/lives.rs index b174bd82..71677839 100644 --- a/yazi-fm/src/lives/lives.rs +++ b/yazi-fm/src/lives/lives.rs @@ -1,20 +1,26 @@ -use std::sync::Arc; +use std::{mem, sync::Arc}; use mlua::{Scope, Table}; use tracing::error; use yazi_config::LAYOUT; use yazi_plugin::{elements::RectRef, LUA}; +use yazi_shared::RoCell; use crate::Ctx; +pub(super) static SCOPE: RoCell<&mlua::Scope> = RoCell::new(); + pub(crate) struct Lives; impl Lives { pub(crate) fn register() -> mlua::Result<()> { - super::Active::register(&LUA)?; + super::Config::register(&LUA)?; super::File::register(&LUA)?; super::Files::register(&LUA)?; super::Folder::register(&LUA)?; + super::Mode::register(&LUA)?; + super::Preview::register(&LUA)?; + super::Tab::register(&LUA)?; super::Tabs::register(&LUA)?; super::Tasks::register(&LUA)?; @@ -26,15 +32,16 @@ impl Lives { f: impl FnOnce(&Scope<'a, 'a>) -> mlua::Result, ) -> mlua::Result { let result = LUA.scope(|scope| { + SCOPE.init(unsafe { mem::transmute(scope) }); LUA.set_named_registry_value("cx", scope.create_any_userdata_ref(cx)?)?; let global = LUA.globals(); global.set( "cx", LUA.create_table_from([ - ("active", super::Active::new(scope, cx.manager.active()).make()?), - ("tabs", super::Tabs::new(scope, &cx.manager.tabs).make()?), - ("tasks", super::Tasks::new(scope, &cx.tasks).make()?), + ("active", super::Tab::make(cx.manager.active())?), + ("tabs", super::Tabs::make(&cx.manager.tabs)?), + ("tasks", super::Tasks::make(&cx.tasks)?), ])?, )?; @@ -48,6 +55,7 @@ impl Lives { status: *global.get::<_, Table>("Status")?.get::<_, RectRef>("area")?, })); + SCOPE.drop(); Ok(ret) }); @@ -56,20 +64,4 @@ impl Lives { } result } - - pub(crate) fn partial_scope<'a>(cx: &'a Ctx, f: impl FnOnce(&Scope<'a, 'a>)) { - let result = LUA.scope(|scope| { - LUA.globals().set( - "cx", - LUA.create_table_from([("tasks", super::Tasks::new(scope, &cx.tasks).make()?)])?, - )?; - - f(scope); - Ok(()) - }); - - if let Err(e) = result { - error!("{e}"); - } - } } diff --git a/yazi-fm/src/lives/mod.rs b/yazi-fm/src/lives/mod.rs index 4690ffb0..b16a4ece 100644 --- a/yazi-fm/src/lives/mod.rs +++ b/yazi-fm/src/lives/mod.rs @@ -1,18 +1,24 @@ #![allow(clippy::module_inception)] -mod active; +mod config; mod file; mod files; mod folder; mod lives; +mod mode; +mod preview; +mod tab; mod tabs; mod tasks; -use active::*; +use config::*; use file::*; use files::*; use folder::*; pub(super) use lives::*; +use mode::*; +use preview::*; +use tab::*; use tabs::*; use tasks::*; diff --git a/yazi-fm/src/lives/mode.rs b/yazi-fm/src/lives/mode.rs new file mode 100644 index 00000000..f5fd0add --- /dev/null +++ b/yazi-fm/src/lives/mode.rs @@ -0,0 +1,33 @@ +use std::ops::Deref; + +use mlua::{AnyUserData, Lua, MetaMethod, UserDataFields, UserDataMethods}; + +use super::SCOPE; + +pub(super) struct Mode { + inner: *const yazi_core::tab::Mode, +} + +impl Deref for Mode { + type Target = yazi_core::tab::Mode; + + fn deref(&self) -> &Self::Target { unsafe { &*self.inner } } +} + +impl Mode { + #[inline] + pub(super) fn make(inner: &yazi_core::tab::Mode) -> mlua::Result> { + SCOPE.create_any_userdata(Self { inner }) + } + + pub(super) fn register(lua: &Lua) -> mlua::Result<()> { + lua.register_userdata_type::(|reg| { + reg.add_field_method_get("is_select", |_, me| Ok(me.is_select())); + reg.add_field_method_get("is_unset", |_, me| Ok(me.is_unset())); + reg.add_field_method_get("is_visual", |_, me| Ok(me.is_visual())); + reg.add_method("pending", |_, me, (idx, state): (usize, bool)| Ok(me.pending(idx, state))); + + reg.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.to_string())); + }) + } +} diff --git a/yazi-fm/src/lives/preview.rs b/yazi-fm/src/lives/preview.rs new file mode 100644 index 00000000..d81a9043 --- /dev/null +++ b/yazi-fm/src/lives/preview.rs @@ -0,0 +1,40 @@ +use std::ops::Deref; + +use mlua::{AnyUserData, Lua, UserDataFields}; + +use super::{Folder, SCOPE}; + +pub(super) struct Preview { + tab: *const yazi_core::tab::Tab, +} + +impl Deref for Preview { + type Target = yazi_core::tab::Preview; + + fn deref(&self) -> &Self::Target { &self.tab().preview } +} + +impl Preview { + #[inline] + pub(super) fn make(tab: &yazi_core::tab::Tab) -> mlua::Result> { + SCOPE.create_any_userdata(Self { tab }) + } + + pub(super) fn register(lua: &Lua) -> mlua::Result<()> { + lua.register_userdata_type::(|reg| { + reg.add_field_method_get("skip", |_, me| Ok(me.skip)); + reg.add_field_method_get("folder", |_, me| { + me.tab() + .current + .hovered() + .filter(|&f| f.is_dir()) + .and_then(|f| me.tab().history(&f.url)) + .map(Folder::make) + .transpose() + }); + }) + } + + #[inline] + fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } } +} diff --git a/yazi-fm/src/lives/tab.rs b/yazi-fm/src/lives/tab.rs new file mode 100644 index 00000000..81f66aa1 --- /dev/null +++ b/yazi-fm/src/lives/tab.rs @@ -0,0 +1,46 @@ +use std::ops::Deref; + +use mlua::{AnyUserData, Lua, UserDataFields, UserDataMethods}; + +use super::{Config, Folder, Mode, Preview, SCOPE}; + +pub(super) struct Tab { + inner: *const yazi_core::tab::Tab, +} + +impl Deref for Tab { + type Target = yazi_core::tab::Tab; + + fn deref(&self) -> &Self::Target { unsafe { &*self.inner } } +} + +impl Tab { + #[inline] + pub(super) fn make(inner: &yazi_core::tab::Tab) -> mlua::Result> { + SCOPE.create_any_userdata(Self { inner }) + } + + pub(super) fn register(lua: &Lua) -> mlua::Result<()> { + lua.register_userdata_type::(|reg| { + reg.add_method("name", |lua, me, ()| { + Some( + lua.create_string( + me.current + .cwd + .file_name() + .map_or(me.current.cwd.as_os_str().as_encoded_bytes(), |n| n.as_encoded_bytes()), + ), + ) + .transpose() + }); + + reg.add_field_method_get("mode", |_, me| Mode::make(&me.mode)); + reg.add_field_method_get("conf", |_, me| Config::make(&me.conf)); + reg.add_field_method_get("parent", |_, me| me.parent.as_ref().map(Folder::make).transpose()); + reg.add_field_method_get("current", |_, me| Folder::make(&me.current)); + reg.add_field_method_get("preview", |_, me| Preview::make(me)); + })?; + + Ok(()) + } +} diff --git a/yazi-fm/src/lives/tabs.rs b/yazi-fm/src/lives/tabs.rs index 3aa7f360..8f48170b 100644 --- a/yazi-fm/src/lives/tabs.rs +++ b/yazi-fm/src/lives/tabs.rs @@ -1,76 +1,42 @@ -// TODO: unsafe +use std::ops::Deref; -use mlua::{AnyUserData, Lua, MetaMethod, UserDataFields, UserDataMethods, Value}; +use mlua::{AnyUserData, ExternalError, Lua, MetaMethod, UserDataFields, UserDataMethods}; -use super::Folder; +use super::{Tab, SCOPE}; -pub(super) struct Tabs<'a, 'b> { - scope: &'b mlua::Scope<'a, 'a>, - - inner: &'a yazi_core::manager::Tabs, +pub(super) struct Tabs { + inner: *const yazi_core::manager::Tabs, } -impl<'a, 'b> Tabs<'a, 'b> { +impl Deref for Tabs { + type Target = yazi_core::manager::Tabs; + + fn deref(&self) -> &Self::Target { unsafe { &*self.inner } } +} + +impl Tabs { + #[inline] + pub(super) fn make(inner: &yazi_core::manager::Tabs) -> mlua::Result> { + SCOPE.create_any_userdata(Self { inner }) + } + pub(super) fn register(lua: &Lua) -> mlua::Result<()> { - lua.register_userdata_type::(|reg| { + lua.register_userdata_type::(|reg| { reg.add_field_method_get("idx", |_, me| Ok(me.idx)); + reg.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.len())); - reg.add_meta_function(MetaMethod::Index, |_, (me, index): (AnyUserData, usize)| { - let items = me.named_user_value::>("items")?; - Ok(items.get(index - 1).cloned()) - }); - })?; - lua.register_userdata_type::(|reg| { - reg.add_method("name", |lua, me, ()| { - Some( - lua.create_string( - me.current - .cwd - .file_name() - .map_or(me.current.cwd.as_os_str().as_encoded_bytes(), |n| n.as_encoded_bytes()), - ), - ) - .transpose() + reg.add_meta_method(MetaMethod::Index, |_, me, idx: usize| { + if idx > me.len() || idx == 0 { + Ok(None) + } else if idx - 1 == me.idx { + Err("Use `active` instead of `tabs` to access the current tab".into_lua_err()) + } else { + Some(Tab::make(&me[idx - 1])).transpose() + } }); - - reg.add_field_function_get("mode", |_, me| me.named_user_value::("mode")); - reg.add_field_function_get("conf", |_, me| me.named_user_value::("conf")); - reg.add_field_function_get("parent", |_, me| me.named_user_value::("parent")); - reg.add_field_function_get("current", |_, me| me.named_user_value::("current")); - reg.add_field_function_get("preview", |_, me| me.named_user_value::("preview")); })?; Ok(()) } } - -impl<'a, 'b> Tabs<'a, 'b> { - pub(crate) fn new(scope: &'b mlua::Scope<'a, 'a>, inner: &'a yazi_core::manager::Tabs) -> Self { - Self { scope, inner } - } - - pub(crate) fn make(&self) -> mlua::Result> { - let ud = self.scope.create_any_userdata_ref(self.inner)?; - - ud.set_named_user_value( - "items", - self.inner.iter().filter_map(|t| self.tab(t).ok()).collect::>(), - )?; - - Ok(ud) - } - - fn tab(&self, inner: &'a yazi_core::tab::Tab) -> mlua::Result> { - let ud = self.scope.create_any_userdata_ref(inner)?; - - ud.set_named_user_value( - "parent", - inner.parent.as_ref().and_then(|p| Folder::make(self.scope, p).ok()), - )?; - - ud.set_named_user_value("current", Folder::make(self.scope, &inner.current)?)?; - - Ok(ud) - } -} diff --git a/yazi-fm/src/lives/tasks.rs b/yazi-fm/src/lives/tasks.rs index 5f5befbd..cc83fe6b 100644 --- a/yazi-fm/src/lives/tasks.rs +++ b/yazi-fm/src/lives/tasks.rs @@ -1,25 +1,30 @@ +use std::ops::Deref; + use mlua::{AnyUserData, Lua, LuaSerdeExt, UserDataFields}; -pub(super) struct Tasks<'a, 'b> { - scope: &'b mlua::Scope<'a, 'a>, +use super::SCOPE; - inner: &'a yazi_core::tasks::Tasks, +pub(super) struct Tasks { + inner: *const yazi_core::tasks::Tasks, } -impl<'a, 'b> Tasks<'a, 'b> { +impl Deref for Tasks { + type Target = yazi_core::tasks::Tasks; + + fn deref(&self) -> &Self::Target { unsafe { &*self.inner } } +} + +impl Tasks { + #[inline] + pub(crate) fn make(inner: &yazi_core::tasks::Tasks) -> mlua::Result> { + SCOPE.create_any_userdata(Self { inner }) + } + pub(super) fn register(lua: &Lua) -> mlua::Result<()> { - lua.register_userdata_type::(|reg| { + lua.register_userdata_type::(|reg| { reg.add_field_method_get("progress", |lua, me| lua.to_value(&me.progress)) })?; Ok(()) } - - pub(crate) fn new(scope: &'b mlua::Scope<'a, 'a>, inner: &'a yazi_core::tasks::Tasks) -> Self { - Self { scope, inner } - } - - pub(crate) fn make(&self) -> mlua::Result> { - self.scope.create_any_userdata_ref(self.inner) - } } diff --git a/yazi-shared/src/ro_cell.rs b/yazi-shared/src/ro_cell.rs index cf2bd575..7a378d48 100644 --- a/yazi-shared/src/ro_cell.rs +++ b/yazi-shared/src/ro_cell.rs @@ -25,6 +25,13 @@ impl RoCell { { self.init(f()); } + + #[inline] + pub fn drop(&self) { + unsafe { + *self.0.get() = None; + } + } } impl Deref for RoCell {