From 7bb5fbb4bb251e453fe33e129446e0f8863b76ad Mon Sep 17 00:00:00 2001 From: sxyazi Date: Sat, 27 Jan 2024 22:57:46 +0800 Subject: [PATCH] feat: plugin-specific state persistence --- yazi-fm/src/app/commands/plugin.rs | 29 ++++++++++------------- yazi-fm/src/app/commands/render.rs | 3 ++- yazi-fm/src/lives/lives.rs | 12 ++++++---- yazi-plugin/preset/components/folder.lua | 22 ++++++++++++++++- yazi-plugin/preset/components/header.lua | 8 +++++-- yazi-plugin/preset/components/manager.lua | 8 +++++-- yazi-plugin/preset/state.lua | 16 +++++++++++++ yazi-plugin/preset/ui.lua | 21 ---------------- yazi-plugin/preset/ya.lua | 2 +- yazi-plugin/src/elements/elements.rs | 3 +-- yazi-plugin/src/elements/layout.rs | 4 +--- yazi-plugin/src/isolate/entry.rs | 3 ++- yazi-plugin/src/plugin.rs | 2 +- 13 files changed, 77 insertions(+), 56 deletions(-) create mode 100644 yazi-plugin/preset/state.lua delete mode 100644 yazi-plugin/preset/ui.lua diff --git a/yazi-fm/src/app/commands/plugin.rs b/yazi-fm/src/app/commands/plugin.rs index 4443d049..3e5aa514 100644 --- a/yazi-fm/src/app/commands/plugin.rs +++ b/yazi-fm/src/app/commands/plugin.rs @@ -1,7 +1,7 @@ use std::fmt::Display; -use mlua::{ExternalError, ExternalResult, IntoLua, Table, TableExt, Value, Variadic}; -use tracing::{error, warn}; +use mlua::{ExternalError, ExternalResult, IntoLua, Table, TableExt, Variadic}; +use tracing::warn; use yazi_plugin::{LOADED, LUA}; use yazi_shared::{emit, event::Exec, Layer}; @@ -36,31 +36,26 @@ impl App { }; let args = Variadic::from_iter(opt.data.args.into_iter().filter_map(|v| v.into_lua(&LUA).ok())); - let mut ret: mlua::Result = Err("uninitialized plugin".into_lua_err()); + let result = Lives::scope(&self.cx, |_| { + LUA.globals().set("YAZI_PLUGIN_NAME", LUA.create_string(&opt.name)?)?; - Lives::scope(&self.cx, |_| { let mut plugin: Option = None; if let Some(b) = LOADED.read().get(&opt.name) { - match LUA.load(b).call(args) { - Ok(t) => plugin = Some(t), - Err(e) => ret = Err(e), - } + plugin = LUA.load(b).call(args)?; } - if let Some(plugin) = plugin { - ret = if let Some(cb) = opt.data.cb { cb(plugin) } else { plugin.call_method("entry", ()) }; - } - }); - if let Err(e) = ret { - error!("{e}"); - return; - } + let Some(plugin) = plugin else { + return Err("plugin not found".into_lua_err()); + }; + + if let Some(cb) = opt.data.cb { cb(plugin) } else { plugin.call_method("entry", ()) } + }); let Some(tx) = opt.data.tx else { return; }; - if let Ok(v) = ret.and_then(|v| v.try_into().into_lua_err()) { + if let Ok(v) = result.and_then(|v| v.try_into().into_lua_err()) { tx.send(v).ok(); } } diff --git a/yazi-fm/src/app/commands/render.rs b/yazi-fm/src/app/commands/render.rs index aca7d710..450d3f8a 100644 --- a/yazi-fm/src/app/commands/render.rs +++ b/yazi-fm/src/app/commands/render.rs @@ -13,8 +13,9 @@ impl App { let collision = COLLISION.swap(false, Ordering::Relaxed); let frame = term.draw(|f| { - Lives::scope(&self.cx, |_| { + _ = Lives::scope(&self.cx, |_| { f.render_widget(Root::new(&self.cx), f.size()); + Ok(()) }); if let Some((x, y)) = self.cx.cursor() { diff --git a/yazi-fm/src/lives/lives.rs b/yazi-fm/src/lives/lives.rs index c5c6d2e6..de3ca8c4 100644 --- a/yazi-fm/src/lives/lives.rs +++ b/yazi-fm/src/lives/lives.rs @@ -23,7 +23,10 @@ impl Lives { Ok(()) } - pub(crate) fn scope<'a>(cx: &'a Ctx, f: impl FnOnce(&Scope<'a, 'a>)) { + pub(crate) fn scope<'a, T>( + cx: &'a Ctx, + f: impl FnOnce(&Scope<'a, 'a>) -> mlua::Result, + ) -> mlua::Result { let result = LUA.scope(|scope| { LUA.set_named_registry_value("cx", scope.create_any_userdata_ref(cx)?)?; @@ -37,7 +40,7 @@ impl Lives { ])?, )?; - f(scope); + let ret = f(scope)?; LAYOUT.store(Arc::new(yazi_config::Layout { header: *global.get::<_, Table>("Header")?.get::<_, RectRef>("area")?, @@ -47,12 +50,13 @@ impl Lives { status: *global.get::<_, Table>("Status")?.get::<_, RectRef>("area")?, })); - Ok(()) + Ok(ret) }); - if let Err(e) = result { + if let Err(ref e) = result { error!("{e}"); } + result } pub(crate) fn partial_scope<'a>(cx: &'a Ctx, f: impl FnOnce(&Scope<'a, 'a>)) { diff --git a/yazi-plugin/preset/components/folder.lua b/yazi-plugin/preset/components/folder.lua index 8be22250..129f4674 100644 --- a/yazi-plugin/preset/components/folder.lua +++ b/yazi-plugin/preset/components/folder.lua @@ -19,6 +19,26 @@ function Folder:icon(file) return icon and ui.Span(" " .. icon.text .. " "):style(icon.style) or ui.Span("") end +function Folder:highlight_ranges(s, ranges) + if ranges == nil or #ranges == 0 then + return { ui.Span(s) } + end + + local spans = {} + local last = 0 + for _, r in ipairs(ranges) do + if r[1] > last then + spans[#spans + 1] = ui.Span(s:sub(last + 1, r[1])) + end + spans[#spans + 1] = ui.Span(s:sub(r[1] + 1, r[2])):style(THEME.manager.find_keyword) + last = r[2] + end + if last < #s then + spans[#spans + 1] = ui.Span(s:sub(last + 1)) + end + return spans +end + function Folder:highlighted_name(file) -- Complete prefix when searching across directories local prefix = file:prefix() or "" @@ -28,7 +48,7 @@ function Folder:highlighted_name(file) -- Range highlighting for filenames local highlights = file:highlights() - local spans = ui.highlight_ranges(prefix .. file.name, highlights) + local spans = self:highlight_ranges(prefix .. file.name, highlights) -- Show symlink target if MANAGER.show_symlink and file.link_to ~= nil then diff --git a/yazi-plugin/preset/components/header.lua b/yazi-plugin/preset/components/header.lua index 0642d9da..db119820 100644 --- a/yazi-plugin/preset/components/header.lua +++ b/yazi-plugin/preset/components/header.lua @@ -30,13 +30,17 @@ function Header:tabs() return ui.Line(spans) end -function Header:render(area) +function Header:layout(area) self.area = area - local chunks = ui.Layout() + return ui.Layout() :direction(ui.Layout.HORIZONTAL) :constraints({ ui.Constraint.Percentage(50), ui.Constraint.Percentage(50) }) :split(area) +end + +function Header:render(area) + local chunks = self:layout(area) local left = ui.Line { self:cwd() } local right = ui.Line { self:tabs() } diff --git a/yazi-plugin/preset/components/manager.lua b/yazi-plugin/preset/components/manager.lua index 4dcb4047..72633ada 100644 --- a/yazi-plugin/preset/components/manager.lua +++ b/yazi-plugin/preset/components/manager.lua @@ -2,10 +2,10 @@ Manager = { area = ui.Rect.default, } -function Manager:render(area) +function Manager:layout(area) self.area = area - local chunks = ui.Layout() + return ui.Layout() :direction(ui.Layout.HORIZONTAL) :constraints({ ui.Constraint.Ratio(MANAGER.ratio.parent, MANAGER.ratio.all), @@ -13,6 +13,10 @@ function Manager:render(area) ui.Constraint.Ratio(MANAGER.ratio.preview, MANAGER.ratio.all), }) :split(area) +end + +function Manager:render(area) + local chunks = self:layout(area) return ya.flat { -- Borders diff --git a/yazi-plugin/preset/state.lua b/yazi-plugin/preset/state.lua new file mode 100644 index 00000000..82eef48f --- /dev/null +++ b/yazi-plugin/preset/state.lua @@ -0,0 +1,16 @@ +local cache = {} + +state = setmetatable({ + clear = function() cache[YAZI_PLUGIN_NAME] = nil end, +}, { + __index = function(_, k) + local bucket = YAZI_PLUGIN_NAME + return cache[bucket] and cache[bucket][k] + end, + + __newindex = function(_, k, v) + local bucket = YAZI_PLUGIN_NAME + cache[bucket] = cache[bucket] or {} + cache[bucket][k] = v + end, +}) diff --git a/yazi-plugin/preset/ui.lua b/yazi-plugin/preset/ui.lua deleted file mode 100644 index 90082554..00000000 --- a/yazi-plugin/preset/ui.lua +++ /dev/null @@ -1,21 +0,0 @@ -ui = {} - -function ui.highlight_ranges(s, ranges) - if ranges == nil or #ranges == 0 then - return { ui.Span(s) } - end - - local spans = {} - local last = 0 - for _, r in ipairs(ranges) do - if r[1] > last then - spans[#spans + 1] = ui.Span(s:sub(last + 1, r[1])) - end - spans[#spans + 1] = ui.Span(s:sub(r[1] + 1, r[2])):style(THEME.manager.find_keyword) - last = r[2] - end - if last < #s then - spans[#spans + 1] = ui.Span(s:sub(last + 1)) - end - return spans -end diff --git a/yazi-plugin/preset/ya.lua b/yazi-plugin/preset/ya.lua index d21e89f1..a7e3bebe 100644 --- a/yazi-plugin/preset/ya.lua +++ b/yazi-plugin/preset/ya.lua @@ -39,7 +39,7 @@ function ya.sync(f) end local calls = ya.SYNC_CALLS - return function(...) return plugin_retrieve(ya.PLUGIN_NAME, calls, ...) end + return function(...) return plugin_retrieve(YAZI_PLUGIN_NAME, calls, ...) end end function ya.basename(str) return string.gsub(str, "(.*[/\\])(.*)", "%2") end diff --git a/yazi-plugin/src/elements/elements.rs b/yazi-plugin/src/elements/elements.rs index fa90c362..c9238bd5 100644 --- a/yazi-plugin/src/elements/elements.rs +++ b/yazi-plugin/src/elements/elements.rs @@ -3,8 +3,7 @@ use mlua::{AnyUserData, Lua, Table}; use crate::cast_to_renderable; pub fn init(lua: &Lua) -> mlua::Result<()> { - let globals = lua.globals(); - let ui: Table = globals.get("ui").or_else(|_| lua.create_table())?; + let ui: Table = lua.create_table()?; // Register super::Padding::register(lua)?; diff --git a/yazi-plugin/src/elements/layout.rs b/yazi-plugin/src/elements/layout.rs index ed336a74..718e5aaa 100644 --- a/yazi-plugin/src/elements/layout.rs +++ b/yazi-plugin/src/elements/layout.rs @@ -64,9 +64,7 @@ impl UserData for Layout { ud.borrow_mut::()?.constraints = value.into_iter().map(|c| c.0).collect(); Ok(ud) }); - methods.add_function("split", |lua, (ud, value): (AnyUserData, RectRef)| { - let me = ud.borrow::()?; - + methods.add_method("split", |lua, me, value: RectRef| { let mut layout = ratatui::layout::Layout::new( if me.direction == VERTICAL { ratatui::layout::Direction::Vertical diff --git a/yazi-plugin/src/isolate/entry.rs b/yazi-plugin/src/isolate/entry.rs index 1fee4eb8..142c0ed5 100644 --- a/yazi-plugin/src/isolate/entry.rs +++ b/yazi-plugin/src/isolate/entry.rs @@ -9,8 +9,9 @@ pub async fn entry(name: String, args: Vec) -> mlua::Result<()> { tokio::task::spawn_blocking(move || { let lua = slim_lua()?; - let args = Variadic::from_iter(args.into_iter().filter_map(|v| v.into_lua(&lua).ok())); + lua.globals().set("YAZI_PLUGIN_NAME", lua.create_string(&name)?)?; + let args = Variadic::from_iter(args.into_iter().filter_map(|v| v.into_lua(&lua).ok())); let plugin: Table = if let Some(b) = LOADED.read().get(&name) { lua.load(b).call(args)? } else { diff --git a/yazi-plugin/src/plugin.rs b/yazi-plugin/src/plugin.rs index b7940f18..a8b7cda1 100644 --- a/yazi-plugin/src/plugin.rs +++ b/yazi-plugin/src/plugin.rs @@ -14,7 +14,7 @@ pub fn init() { // Base lua.load(include_str!("../preset/inspect/inspect.lua")).exec()?; - lua.load(include_str!("../preset/ui.lua")).exec()?; + lua.load(include_str!("../preset/state.lua")).exec()?; lua.load(include_str!("../preset/ya.lua")).exec()?; crate::elements::init(lua)?;