Skip to content

Commit

Permalink
feat: new cx.layer API to determine the current UI layer (#2247)
Browse files Browse the repository at this point in the history
  • Loading branch information
sxyazi authored Jan 25, 2025
1 parent af9a875 commit da36cd6
Show file tree
Hide file tree
Showing 33 changed files with 199 additions and 147 deletions.
24 changes: 24 additions & 0 deletions yazi-fm/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ratatui::layout::Rect;
use yazi_core::{completion::Completion, confirm::Confirm, help::Help, input::Input, manager::Manager, notify::Notify, pick::Pick, tab::{Folder, Tab}, tasks::Tasks, which::Which};
use yazi_shared::Layer;

pub struct Ctx {
pub manager: Manager,
Expand Down Expand Up @@ -39,6 +40,29 @@ impl Ctx {
}
None
}

#[inline]
pub fn layer(&self) -> Layer {
if self.which.visible {
Layer::Which
} else if self.completion.visible {
Layer::Completion
} else if self.help.visible {
Layer::Help
} else if self.confirm.visible {
Layer::Confirm
} else if self.input.visible {
Layer::Input
} else if self.pick.visible {
Layer::Pick
} else if self.active().spot.visible() {
Layer::Spot
} else if self.tasks.visible {
Layer::Tasks
} else {
Layer::Manager
}
}
}

impl Ctx {
Expand Down
38 changes: 38 additions & 0 deletions yazi-fm/src/lives/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use std::ops::Deref;

use mlua::{AnyUserData, IntoLua, MetaMethod, UserData, Value};

use super::Lives;

pub(super) struct Ctx {
inner: *const crate::Ctx,
}

impl Deref for Ctx {
type Target = crate::Ctx;

fn deref(&self) -> &Self::Target { unsafe { &*self.inner } }
}

impl Ctx {
#[inline]
pub(super) fn make(inner: &crate::Ctx) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { inner })
}
}

impl UserData for Ctx {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Index, |lua, me, key: mlua::String| {
match key.as_bytes().as_ref() {
b"active" => super::Tab::make(me.active())?,
b"tabs" => super::Tabs::make(&me.manager.tabs)?,
b"tasks" => super::Tasks::make(&me.tasks)?,
b"yanked" => super::Yanked::make(&me.manager.yanked)?,
b"layer" => return yazi_plugin::bindings::Layer::from(me.layer()).into_lua(lua),
_ => return Ok(Value::Nil),
}
.into_lua(lua)
});
}
}
11 changes: 1 addition & 10 deletions yazi-fm/src/lives/lives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,7 @@ impl Lives {
});

LUA.set_named_registry_value("cx", scope.create_any_userdata_ref(cx)?)?;
LUA.globals().raw_set(
"cx",
LUA.create_table_from([
("active", super::Tab::make(cx.active())?),
("tabs", super::Tabs::make(&cx.manager.tabs)?),
("tasks", super::Tasks::make(&cx.tasks)?),
("yanked", super::Yanked::make(&cx.manager.yanked)?),
])?,
)?;

LUA.globals().raw_set("cx", super::Ctx::make(cx)?)?;
f()
});

Expand Down
5 changes: 1 addition & 4 deletions yazi-fm/src/lives/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
#![allow(clippy::module_inception)]

yazi_macro::mod_flat!(
preference file files filter finder folder iter lives mode preview selected tab tabs
tasks yanked
);
yazi_macro::mod_flat!(context file files filter finder folder iter lives mode preference preview selected tab tabs tasks yanked);
28 changes: 9 additions & 19 deletions yazi-fm/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,23 @@ impl<'a> Router<'a> {
#[inline]
pub(super) fn route(&mut self, key: Key) -> bool {
let cx = &mut self.app.cx;
let layer = cx.layer();

if cx.which.visible {
return cx.which.type_(key);
}
if cx.help.visible && cx.help.type_(&key) {
return true;
}
if cx.input.visible && cx.input.type_(&key) {
return true;
}

if cx.completion.visible {
self.matches(Layer::Completion, key) || self.matches(Layer::Input, key)
} else if cx.help.visible {
self.matches(Layer::Help, key)
} else if cx.input.visible {
self.matches(Layer::Input, key)
} else if cx.confirm.visible {
self.matches(Layer::Confirm, key)
} else if cx.pick.visible {
self.matches(Layer::Pick, key)
} else if cx.active().spot.visible() {
self.matches(Layer::Spot, key)
} else if cx.tasks.visible {
self.matches(Layer::Tasks, key)
} else {
self.matches(Layer::Manager, key)
use Layer as L;
match layer {
L::App => unreachable!(),
L::Manager | L::Tasks | L::Spot | L::Pick | L::Input | L::Confirm | L::Help => {
self.matches(layer, key)
}
L::Completion => self.matches(L::Completion, key) || self.matches(L::Input, key),
L::Which => cx.which.type_(key),
}
}

Expand Down
4 changes: 2 additions & 2 deletions yazi-plugin/preset/components/entity.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Entity = {
_inc = 1000,
_children = {
{ "space", id = 1, order = 1000 },
{ "spacer", id = 1, order = 1000 },
{ "icon", id = 2, order = 2000 },
{ "prefix", id = 3, order = 3000 },
{ "highlights", id = 4, order = 4000 },
Expand All @@ -12,7 +12,7 @@ Entity = {

function Entity:new(file) return setmetatable({ _file = file }, { __index = self }) end

function Entity:space() return " " end
function Entity:spacer() return " " end

function Entity:icon()
local icon = self._file:icon()
Expand Down
4 changes: 2 additions & 2 deletions yazi-plugin/preset/components/linemode.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ Linemode = {
_inc = 1000,
_children = {
{ "solo", id = 1, order = 1000 },
{ "space", id = 2, order = 2000 },
{ "spacer", id = 2, order = 2000 },
},
}

function Linemode:new(file) return setmetatable({ _file = file }, { __index = self }) end

function Linemode:space() return " " end
function Linemode:spacer() return " " end

function Linemode:solo()
local mode = cx.active.pref.linemode
Expand Down
9 changes: 9 additions & 0 deletions yazi-plugin/preset/components/root.lua
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,25 @@ end

-- Mouse events
function Root:click(event, up)
if tostring(cx.layer) ~= "manager" then
return
end
local c = ya.child_at(ui.Rect { x = event.x, y = event.y }, self:reflow())
return c and c:click(event, up)
end

function Root:scroll(event, step)
if tostring(cx.layer) ~= "manager" then
return
end
local c = ya.child_at(ui.Rect { x = event.x, y = event.y }, self:reflow())
return c and c:scroll(event, step)
end

function Root:touch(event, step)
if tostring(cx.layer) ~= "manager" then
return
end
local c = ya.child_at(ui.Rect { x = event.x, y = event.y }, self:reflow())
return c and c:touch(event, step)
end
Expand Down
14 changes: 14 additions & 0 deletions yazi-plugin/src/bindings/layer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use mlua::{MetaMethod, UserData};

#[derive(Clone, Copy)]
pub struct Layer(yazi_shared::Layer);

impl From<yazi_shared::Layer> for Layer {
fn from(event: yazi_shared::Layer) -> Self { Self(event) }
}

impl UserData for Layer {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.0.to_string()));
}
}
2 changes: 1 addition & 1 deletion yazi-plugin/src/bindings/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#![allow(clippy::module_inception)]

yazi_macro::mod_flat!(bindings cha chan icon image input mouse permit range window);
yazi_macro::mod_flat!(bindings cha chan icon image input layer mouse permit range window);
20 changes: 20 additions & 0 deletions yazi-plugin/src/composer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use mlua::{IntoLua, Lua, MetaMethod, Table, Value};

pub struct Composer;

impl Composer {
pub fn make<F>(lua: &Lua, cap: usize, f: F) -> mlua::Result<Value>
where
F: Fn(&Lua, &[u8]) -> mlua::Result<Value> + 'static,
{
let index = lua.create_function(move |lua, (ts, key): (Table, mlua::String)| {
let v = f(lua, key.as_bytes().as_ref())?;
ts.raw_set(key, v.clone())?;
Ok(v)
})?;

let tbl = lua.create_table_with_capacity(0, cap)?;
tbl.set_metatable(Some(lua.create_table_from([(MetaMethod::Index.name(), index)])?));
tbl.into_lua(lua)
}
}
34 changes: 15 additions & 19 deletions yazi-plugin/src/config/config.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use mlua::{IntoLua, Lua, LuaSerdeExt, MetaMethod, SerializeOptions, Table, Value};
use mlua::{IntoLua, Lua, LuaSerdeExt, SerializeOptions, Value};
use yazi_boot::BOOT;
use yazi_config::{MANAGER, PREVIEW, THEME};

use super::Plugin;
use crate::Composer;

pub const SER_OPTS: SerializeOptions =
SerializeOptions::new().serialize_none_to_null(false).serialize_unit_to_null(false);
Expand Down Expand Up @@ -35,24 +36,19 @@ impl<'a> Config<'a> {
}

pub fn install_plugin(self) -> mlua::Result<Self> {
let index = self.lua.create_function(|lua, (ts, key): (Table, mlua::String)| {
let value = match key.as_bytes().as_ref() {
b"fetchers" => Plugin::fetchers(lua)?,
b"spotter" => Plugin::spotter(lua)?,
b"preloaders" => Plugin::preloaders(lua)?,
b"previewer" => Plugin::previewer(lua)?,
_ => return Ok(Value::Nil),
}
.into_lua(lua)?;

ts.raw_set(key, value.clone())?;
Ok(value)
})?;

let fetcher = self.lua.create_table()?;
fetcher.set_metatable(Some(self.lua.create_table_from([(MetaMethod::Index.name(), index)])?));

self.lua.globals().raw_set("PLUGIN", fetcher)?;
self.lua.globals().raw_set(
"PLUGIN",
Composer::make(self.lua, 5, |lua, name| {
match name {
b"fetchers" => Plugin::fetchers(lua)?,
b"spotter" => Plugin::spotter(lua)?,
b"preloaders" => Plugin::preloaders(lua)?,
b"previewer" => Plugin::previewer(lua)?,
_ => return Ok(Value::Nil),
}
.into_lua(lua)
})?,
)?;
Ok(self)
}
}
4 changes: 2 additions & 2 deletions yazi-plugin/src/elements/bar.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use mlua::{Lua, Table, UserData};
use mlua::{Lua, MetaMethod, Table, UserData};
use ratatui::widgets::Borders;

use super::Area;
Expand Down Expand Up @@ -28,7 +28,7 @@ impl Bar {
("ALL", Borders::ALL.bits()),
])?;

bar.set_metatable(Some(lua.create_table_from([("__call", new)])?));
bar.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
Ok(bar)
}

Expand Down
4 changes: 2 additions & 2 deletions yazi-plugin/src/elements/border.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use mlua::{Lua, Table, UserData, Value};
use mlua::{Lua, MetaMethod, Table, UserData, Value};
use ratatui::widgets::{Borders, Widget};

use super::Area;
Expand Down Expand Up @@ -49,7 +49,7 @@ impl Border {
("QUADRANT_OUTSIDE", QUADRANT_OUTSIDE),
])?;

border.set_metatable(Some(lua.create_table_from([("__call", new)])?));
border.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));
Ok(border)
}

Expand Down
4 changes: 2 additions & 2 deletions yazi-plugin/src/elements/clear.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::sync::atomic::{AtomicBool, Ordering};

use mlua::{Lua, Table, UserData};
use mlua::{Lua, MetaMethod, Table, UserData};
use yazi_adapter::ADAPTOR;

use super::Area;
Expand All @@ -17,7 +17,7 @@ impl Clear {
let new = lua.create_function(|_, (_, area): (Table, Area)| Ok(Clear { area }))?;

let clear = lua.create_table()?;
clear.set_metatable(Some(lua.create_table_from([("__call", new)])?));
clear.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));

Ok(clear)
}
Expand Down
21 changes: 7 additions & 14 deletions yazi-plugin/src/elements/elements.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, Table, Value};
use mlua::{AnyUserData, IntoLua, Lua, Table, Value};
use tracing::error;

use super::Renderable;
use crate::Composer;

pub fn compose(lua: &Lua) -> mlua::Result<Table> {
let index = lua.create_function(|lua, (ts, key): (Table, mlua::String)| {
let value = match key.as_bytes().as_ref() {
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
Composer::make(lua, 20, |lua, key| {
match key {
b"Bar" => super::Bar::compose(lua)?,
b"Border" => super::Border::compose(lua)?,
b"Clear" => super::Clear::compose(lua)?,
Expand All @@ -26,16 +27,8 @@ pub fn compose(lua: &Lua) -> mlua::Result<Table> {
b"Text" => super::Text::compose(lua)?,
_ => return Ok(Value::Nil),
}
.into_lua(lua)?;

ts.raw_set(key, value.clone())?;
Ok(value)
})?;

let ui = lua.create_table_with_capacity(0, 20)?;
ui.set_metatable(Some(lua.create_table_from([(MetaMethod::Index.name(), index)])?));

Ok(ui)
.into_lua(lua)
})
}

pub fn render_once<F>(widgets: Table, buf: &mut ratatui::buffer::Buffer, trans: F)
Expand Down
4 changes: 2 additions & 2 deletions yazi-plugin/src/elements/gauge.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use mlua::{ExternalError, Lua, Table, UserData, UserDataMethods, Value};
use mlua::{ExternalError, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
use ratatui::widgets::Widget;

use super::{Area, Span};
Expand All @@ -19,7 +19,7 @@ impl Gauge {
let new = lua.create_function(|_, _: Table| Ok(Gauge::default()))?;

let gauge = lua.create_table()?;
gauge.set_metatable(Some(lua.create_table_from([("__call", new)])?));
gauge.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?));

Ok(gauge)
}
Expand Down
Loading

0 comments on commit da36cd6

Please sign in to comment.