refactor: upgrade to mlua v0.10.0 (#1842)

This commit is contained in:
三咲雅 · Misaki Masa 2024-11-08 21:38:54 +08:00 committed by sxyazi
parent baf062f3b1
commit a9a8a190a4
No known key found for this signature in database
97 changed files with 688 additions and 673 deletions

44
Cargo.lock generated
View file

@ -117,15 +117,15 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.92"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13"
checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
[[package]]
name = "arbitrary"
version = "1.4.0"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "775a8770d29db3dadcb858482cc240af7b2ffde4ac4de67d1d4955728103f0e2"
checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223"
[[package]]
name = "arg_enum_proc_macro"
@ -327,9 +327,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.1.35"
version = "1.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f57c4b4da2a9d619dd035f27316d7a426305b75be93d09e92f2b9229c34feaf"
checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70"
dependencies = [
"jobserver",
"libc",
@ -1392,19 +1392,18 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
[[package]]
name = "libc"
version = "0.2.161"
version = "0.2.162"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
[[package]]
name = "libfuzzer-sys"
version = "0.4.7"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7"
checksum = "9b9569d2f74e257076d8c6bfa73fb505b46b851e51ddaecc825944aa3bed17fa"
dependencies = [
"arbitrary",
"cc",
"once_cell",
]
[[package]]
@ -1539,17 +1538,18 @@ dependencies = [
[[package]]
name = "mlua"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d111deb18a9c9bd33e1541309f4742523bfab01d276bfa9a27519f6de9c11dc7"
version = "0.10.0"
source = "git+https://github.com/mlua-rs/mlua.git#c7094d470ff377775ba267ea78650d095db9b017"
dependencies = [
"anyhow",
"bstr",
"either",
"erased-serde",
"futures-util",
"mlua-sys",
"mlua_derive",
"num-traits",
"once_cell",
"parking_lot",
"rustc-hash",
"serde",
"serde-value",
@ -1558,8 +1558,7 @@ dependencies = [
[[package]]
name = "mlua-sys"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9eebac25c35a13285456c88ee2fde93d9aee8bcfdaf03f9d6d12be3391351ec"
source = "git+https://github.com/mlua-rs/mlua.git#c7094d470ff377775ba267ea78650d095db9b017"
dependencies = [
"cc",
"cfg-if",
@ -1570,11 +1569,10 @@ dependencies = [
[[package]]
name = "mlua_derive"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09697a6cec88e7f58a02c7ab5c18c611c6907c8654613df9cc0192658a4fb859"
version = "0.10.0"
source = "git+https://github.com/mlua-rs/mlua.git#c7094d470ff377775ba267ea78650d095db9b017"
dependencies = [
"itertools 0.12.1",
"itertools 0.13.0",
"once_cell",
"proc-macro-error",
"proc-macro2",
@ -2591,9 +2589,9 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.41.0"
version = "1.41.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb"
checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33"
dependencies = [
"backtrace",
"bytes",

View file

@ -11,7 +11,7 @@ strip = true
[workspace.dependencies]
ansi-to-tui = "7.0.0"
anyhow = "1.0.92"
anyhow = "1.0.93"
base64 = "0.22.1"
bitflags = "2.6.0"
clap = { version = "4.5.20", features = [ "derive" ] }
@ -19,9 +19,9 @@ crossterm = { version = "0.28.1", features = [ "event-stream" ] }
dirs = "5.0.1"
futures = "0.3.31"
globset = "0.4.15"
libc = "0.2.161"
libc = "0.2.162"
md-5 = "0.10.6"
mlua = { version = "0.9.9", features = [ "lua54", "serialize", "macros", "async" ] }
mlua = { git = "https://github.com/mlua-rs/mlua.git", features = [ "anyhow", "async", "error-send", "lua54", "macros", "serialize" ] }
parking_lot = "0.12.3"
ratatui = { version = "0.29.0", features = [ "unstable-rendered-line-info" ] }
regex = "1.11.1"
@ -29,7 +29,7 @@ scopeguard = "1.2.0"
serde = { version = "1.0.214", features = [ "derive" ] }
serde_json = "1.0.132"
shell-words = "1.1.0"
tokio = { version = "1.41.0", features = [ "full" ] }
tokio = { version = "1.41.1", features = [ "full" ] }
tokio-stream = "0.1.16"
tokio-util = "0.7.12"
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }

View file

@ -29,9 +29,9 @@ rustPlatform.buildRustPackage rec {
cargoLock = {
lockFile = "${src}/Cargo.lock";
# outputHashes = {
# "notify-6.1.1" = "sha256-5Ft2yvRPi2EaErcGBkF/3Xv6K7ijFGbdjmSqI4go/h4=";
# };
outputHashes = {
"mlua-0.10.0" = "sha256-Xg6/jc+UP8tbJJ6x1sbAgt8ZHt051xEBBcjmikQqYlw=";
};
};
env = {

View file

@ -107,7 +107,7 @@ impl<'a> Body<'a> {
pub fn with_sender(self, sender: u64) -> Payload<'a> { Payload::new(self).with_sender(sender) }
}
impl IntoLua<'_> for Body<'static> {
impl IntoLua for Body<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
match self {
Self::Hi(b) => b.into_lua(lua),

View file

@ -36,7 +36,7 @@ impl<'a> From<BodyBulk<'a>> for Body<'a> {
fn from(value: BodyBulk<'a>) -> Self { Self::Bulk(value) }
}
impl IntoLua<'_> for BodyBulk<'static> {
impl IntoLua for BodyBulk<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
BodyBulkIter { inner: self.changes.into_iter() }.into_lua(lua)
}
@ -48,7 +48,7 @@ pub struct BodyBulkIter {
}
impl UserData for BodyBulkIter {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.inner.len()));
methods.add_meta_function(MetaMethod::Pairs, |lua, me: AnyUserData| {

View file

@ -15,8 +15,8 @@ impl<'a> From<BodyBye> for Body<'a> {
fn from(value: BodyBye) -> Self { Self::Bye(value) }
}
impl IntoLua<'_> for BodyBye {
fn into_lua(self, _: &Lua) -> mlua::Result<Value<'_>> {
impl IntoLua for BodyBye {
fn into_lua(self, _: &Lua) -> mlua::Result<Value> {
Err("BodyBye cannot be converted to Lua").into_lua_err()
}
}

View file

@ -32,7 +32,7 @@ impl<'a> From<BodyCd<'a>> for Body<'a> {
fn from(value: BodyCd<'a>) -> Self { Self::Cd(value) }
}
impl IntoLua<'_> for BodyCd<'static> {
impl IntoLua for BodyCd<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
if let Some(Cow::Owned(url)) = Some(self.url).filter(|_| !self.dummy) {
lua.create_table_from([

View file

@ -27,7 +27,7 @@ impl From<BodyCustom> for Body<'_> {
fn from(value: BodyCustom) -> Self { Self::Custom(value) }
}
impl IntoLua<'_> for BodyCustom {
impl IntoLua for BodyCustom {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> { Sendable::data_to_value(lua, self.data) }
}

View file

@ -25,8 +25,8 @@ impl<'a> From<BodyDelete<'a>> for Body<'a> {
fn from(value: BodyDelete<'a>) -> Self { Self::Delete(value) }
}
impl IntoLua<'_> for BodyDelete<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value<'_>> {
impl IntoLua for BodyDelete<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
let urls = lua.create_table_with_capacity(self.urls.len(), 0)?;
// In most cases, `self.urls` will be `Cow::Owned`, so

View file

@ -23,8 +23,8 @@ impl From<BodyHey> for Body<'_> {
fn from(value: BodyHey) -> Self { Self::Hey(value) }
}
impl IntoLua<'_> for BodyHey {
fn into_lua(self, _: &Lua) -> mlua::Result<Value<'_>> {
impl IntoLua for BodyHey {
fn into_lua(self, _: &Lua) -> mlua::Result<Value> {
Err("BodyHey cannot be converted to Lua").into_lua_err()
}
}

View file

@ -31,8 +31,8 @@ impl<'a> From<BodyHi<'a>> for Body<'a> {
fn from(value: BodyHi<'a>) -> Self { Self::Hi(value) }
}
impl IntoLua<'_> for BodyHi<'_> {
fn into_lua(self, _: &Lua) -> mlua::Result<Value<'_>> {
impl IntoLua for BodyHi<'_> {
fn into_lua(self, _: &Lua) -> mlua::Result<Value> {
Err("BodyHi cannot be converted to Lua").into_lua_err()
}
}

View file

@ -28,7 +28,7 @@ impl<'a> From<BodyHover<'a>> for Body<'a> {
fn from(value: BodyHover<'a>) -> Self { Self::Hover(value) }
}
impl IntoLua<'_> for BodyHover<'static> {
impl IntoLua for BodyHover<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
if let Some(Cow::Owned(url)) = self.url {
lua.create_table_from([

View file

@ -29,7 +29,7 @@ impl<'a> From<BodyMove<'a>> for Body<'a> {
fn from(value: BodyMove<'a>) -> Self { Self::Move(value) }
}
impl IntoLua<'_> for BodyMove<'static> {
impl IntoLua for BodyMove<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
lua.create_table_from([("items", self.items.into_owned())])?.into_lua(lua)
}
@ -42,7 +42,7 @@ pub struct BodyMoveItem {
pub to: Url,
}
impl IntoLua<'_> for BodyMoveItem {
impl IntoLua for BodyMoveItem {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
lua
.create_table_from([

View file

@ -31,7 +31,7 @@ impl<'a> From<BodyRename<'a>> for Body<'a> {
fn from(value: BodyRename<'a>) -> Self { Self::Rename(value) }
}
impl IntoLua<'_> for BodyRename<'static> {
impl IntoLua for BodyRename<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
lua
.create_table_from([

View file

@ -17,7 +17,7 @@ impl<'a> From<BodyTab> for Body<'a> {
fn from(value: BodyTab) -> Self { Self::Tab(value) }
}
impl IntoLua<'_> for BodyTab {
impl IntoLua for BodyTab {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
lua.create_table_from([("idx", self.idx)])?.into_lua(lua)
}

View file

@ -25,8 +25,8 @@ impl<'a> From<BodyTrash<'a>> for Body<'a> {
fn from(value: BodyTrash<'a>) -> Self { Self::Trash(value) }
}
impl IntoLua<'_> for BodyTrash<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value<'_>> {
impl IntoLua for BodyTrash<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
let urls = lua.create_table_with_capacity(self.urls.len(), 0)?;
// In most cases, `self.urls` will be `Cow::Owned`, so

View file

@ -32,8 +32,8 @@ impl<'a> From<BodyYank<'a>> for Body<'a> {
fn from(value: BodyYank<'a>) -> Self { Self::Yank(value) }
}
impl IntoLua<'_> for BodyYank<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value<'_>> {
impl IntoLua for BodyYank<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
if let Some(Cow::Owned(urls)) = Some(self.urls).filter(|_| !self.dummy) {
BodyYankIter { cut: self.cut, urls: urls.into_iter().collect() }.into_lua(lua)
} else {
@ -49,11 +49,11 @@ pub struct BodyYankIter {
}
impl UserData for BodyYankIter {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("cut", |_, me| Ok(me.cut));
}
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.urls.len()));
methods.add_meta_method(MetaMethod::Index, |lua, me, idx: usize| {

View file

@ -7,15 +7,13 @@ use yazi_shared::{Id, RoCell, fs::Url};
use crate::{Client, ID, PEERS, body::{Body, BodyBulk, BodyCd, BodyDelete, BodyHi, BodyHover, BodyMove, BodyMoveItem, BodyRename, BodyTab, BodyTrash, BodyYank}};
pub static LOCAL: RoCell<RwLock<HashMap<String, HashMap<String, Function<'static>>>>> =
RoCell::new();
pub static LOCAL: RoCell<RwLock<HashMap<String, HashMap<String, Function>>>> = RoCell::new();
pub static REMOTE: RoCell<RwLock<HashMap<String, HashMap<String, Function<'static>>>>> =
RoCell::new();
pub static REMOTE: RoCell<RwLock<HashMap<String, HashMap<String, Function>>>> = RoCell::new();
macro_rules! sub {
($var:ident) => {
|plugin: &str, kind: &str, f: Function<'static>| {
|plugin: &str, kind: &str, f: Function| {
let mut var = $var.write();
let Some(map) = var.get_mut(kind) else {
var.insert(kind.to_owned(), HashMap::from_iter([(plugin.to_owned(), f)]));
@ -51,11 +49,9 @@ macro_rules! unsub {
pub struct Pubsub;
impl Pubsub {
pub fn sub(plugin: &str, kind: &str, f: Function<'static>) -> bool {
sub!(LOCAL)(plugin, kind, f)
}
pub fn sub(plugin: &str, kind: &str, f: Function) -> bool { sub!(LOCAL)(plugin, kind, f) }
pub fn sub_remote(plugin: &str, kind: &str, f: Function<'static>) -> bool {
pub fn sub_remote(plugin: &str, kind: &str, f: Function) -> bool {
sub!(REMOTE)(plugin, kind, f) && Self::pub_from_hi()
}

View file

@ -44,6 +44,7 @@ impl Sendable {
}
}
Value::Error(_) => Err("error is not supported".into_lua_err())?,
Value::Other(..) => Err("unknown data is not supported".into_lua_err())?,
})
}
@ -87,7 +88,7 @@ impl Sendable {
for v in data {
vec.push(Self::data_to_value(lua, v)?);
}
Ok(MultiValue::from_iter(vec))
Ok(MultiValue::from_vec(vec))
}
pub fn values_to_vec(values: MultiValue) -> mlua::Result<Vec<Data>> {
@ -117,6 +118,7 @@ impl Sendable {
}
}
Value::Error(_) => Err("error is not supported".into_lua_err())?,
Value::Other(..) => Err("unknown data is not supported".into_lua_err())?,
})
}

View file

@ -23,10 +23,10 @@ impl App {
return;
};
_ = Lives::scope(&self.cx, |_| {
_ = Lives::scope(&self.cx, || {
let body = payload.body.into_lua(&LUA)?;
for f in map.values() {
if let Err(e) = f.call::<_, ()>(body.clone()) {
if let Err(e) = f.call::<()>(body.clone()) {
error!("Failed to call `{kind}` handler: {e}");
}
}

View file

@ -1,5 +1,5 @@
use crossterm::event::{MouseEvent, MouseEventKind};
use mlua::{Table, TableExt};
use mlua::{ObjectLike, Table};
use tracing::error;
use yazi_config::MANAGER;
use yazi_plugin::{LUA, bindings::Cast};
@ -21,9 +21,9 @@ impl App {
let Some(size) = self.term.as_ref().and_then(|t| t.size().ok()) else { return };
let Ok(evt) = yazi_plugin::bindings::MouseEvent::cast(&LUA, event) else { return };
let res = Lives::scope(&self.cx, move |_| {
let res = Lives::scope(&self.cx, move || {
let area = yazi_plugin::elements::Rect::from(size);
let root = LUA.globals().raw_get::<_, Table>("Root")?.call_method::<_, Table>("new", area)?;
let root = LUA.globals().raw_get::<Table>("Root")?.call_method::<Table>("new", area)?;
if matches!(event.kind, MouseEventKind::Down(_) if MANAGER.mouse_events.draggable()) {
root.raw_set("_drag_start", evt.clone())?;

View file

@ -1,6 +1,6 @@
use std::fmt::Display;
use mlua::TableExt;
use mlua::ObjectLike;
use scopeguard::defer;
use tracing::warn;
use yazi_dds::Sendable;
@ -62,7 +62,7 @@ impl App {
};
drop(loader);
_ = Lives::scope(&self.cx, |_| {
_ = Lives::scope(&self.cx, || {
if let Some(cb) = opt.cb {
cb(&LUA, plugin)
} else {

View file

@ -23,7 +23,7 @@ impl App {
let Some(size) = self.term.as_ref().and_then(|t| t.size().ok()) else { return };
let mut layout = LAYOUT.get();
let result = Lives::scope(&self.cx, |_| {
let result = Lives::scope(&self.cx, || {
let comps = Root::reflow((Position::ORIGIN, size).into())?;
for v in comps.sequence_values::<Value>() {
@ -33,10 +33,10 @@ impl App {
};
let id: mlua::String = t.get("_id")?;
match id.to_str()? {
"current" => layout.current = *t.raw_get::<_, yazi_plugin::elements::Rect>("_area")?,
"preview" => layout.preview = *t.raw_get::<_, yazi_plugin::elements::Rect>("_area")?,
"progress" => layout.progress = *t.raw_get::<_, yazi_plugin::elements::Rect>("_area")?,
match id.to_str()?.as_ref() {
"current" => layout.current = *t.raw_get::<yazi_plugin::elements::Rect>("_area")?,
"preview" => layout.preview = *t.raw_get::<yazi_plugin::elements::Rect>("_area")?,
"progress" => layout.progress = *t.raw_get::<yazi_plugin::elements::Rect>("_area")?,
_ => {}
}
}

View file

@ -19,7 +19,7 @@ impl App {
let collision = COLLISION.swap(false, Ordering::Relaxed);
let frame = term
.draw(|f| {
_ = Lives::scope(&self.cx, |_| Ok(f.render_widget(Root::new(&self.cx), f.area())));
_ = Lives::scope(&self.cx, || Ok(f.render_widget(Root::new(&self.cx), f.area())));
if let Some(pos) = self.cx.cursor() {
f.set_cursor_position(pos);
@ -48,7 +48,7 @@ impl App {
let frame = term
.draw_partial(|f| {
_ = Lives::scope(&self.cx, |_| {
_ = Lives::scope(&self.cx, || {
f.render_widget(crate::tasks::Progress, f.area());
f.render_widget(crate::notify::Notify::new(&self.cx), f.area());
Ok(())

View file

@ -1,8 +1,8 @@
use std::ops::Deref;
use mlua::{AnyUserData, Lua, UserDataFields};
use mlua::{AnyUserData, UserData, UserDataFields};
use super::SCOPE;
use super::Lives;
pub(super) struct Config {
inner: *const yazi_core::tab::Config,
@ -16,20 +16,20 @@ impl Deref for Config {
impl Config {
#[inline]
pub(super) fn make(inner: &yazi_core::tab::Config) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { inner })
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|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("sort_translit", |_, me| Ok(me.sort_translit));
reg.add_field_method_get("linemode", |_, me| Ok(me.linemode.to_owned()));
reg.add_field_method_get("show_hidden", |_, me| Ok(me.show_hidden));
})
pub(super) fn make(inner: &yazi_core::tab::Config) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { inner })
}
}
impl UserData for Config {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("sort_by", |_, me| Ok(me.sort_by.to_string()));
fields.add_field_method_get("sort_sensitive", |_, me| Ok(me.sort_sensitive));
fields.add_field_method_get("sort_reverse", |_, me| Ok(me.sort_reverse));
fields.add_field_method_get("sort_dir_first", |_, me| Ok(me.sort_dir_first));
fields.add_field_method_get("sort_translit", |_, me| Ok(me.sort_translit));
fields.add_field_method_get("linemode", |_, me| Ok(me.linemode.to_owned()));
fields.add_field_method_get("show_hidden", |_, me| Ok(me.show_hidden));
}
}

View file

@ -1,11 +1,12 @@
use std::ops::Deref;
use mlua::{AnyUserData, IntoLua, Lua, UserDataFields, UserDataMethods};
use mlua::{AnyUserData, IntoLua, UserData, UserDataFields, UserDataMethods};
use yazi_config::THEME;
use yazi_plugin::{bindings::Range, elements::Style};
use yazi_shared::MIME_DIR;
use super::{CtxRef, SCOPE};
use super::Lives;
use crate::Ctx;
pub(super) struct File {
idx: usize,
@ -29,23 +30,36 @@ impl File {
idx: usize,
folder: &yazi_fs::Folder,
tab: &yazi_core::tab::Tab,
) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { idx, folder, tab })
) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { idx, folder, tab })
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
yazi_plugin::file::File::register_with(reg);
#[inline]
fn folder(&self) -> &yazi_fs::Folder { unsafe { &*self.folder } }
reg.add_field_method_get("idx", |_, me| Ok(me.idx + 1));
reg.add_method("size", |_, me, ()| {
#[inline]
fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } }
}
impl UserData for File {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
yazi_plugin::impl_file_fields!(fields);
fields.add_field_method_get("idx", |_, me| Ok(me.idx + 1));
}
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
yazi_plugin::impl_file_methods!(methods);
methods.add_method("size", |_, me, ()| {
Ok(if me.is_dir() { me.folder().files.sizes.get(me.urn()).copied() } else { Some(me.len) })
});
reg.add_method("mime", |lua, me, ()| {
let cx = lua.named_registry_value::<CtxRef>("cx")?;
Ok(cx.manager.mimetype.get_owned(&me.url))
methods.add_method("mime", |lua, me, ()| {
lua
.named_registry_value::<AnyUserData>("cx")?
.borrow_scoped(|cx: &Ctx| cx.manager.mimetype.get_owned(&me.url))
});
reg.add_method("prefix", |lua, me, ()| {
methods.add_method("prefix", |lua, me, ()| {
if !me.folder().url.is_search() {
return Ok(None);
}
@ -54,25 +68,27 @@ impl File {
p.next_back();
Some(lua.create_string(p.as_path().as_os_str().as_encoded_bytes())).transpose()
});
reg.add_method("style", |lua, me, ()| {
let cx = lua.named_registry_value::<CtxRef>("cx")?;
methods.add_method("style", |lua, me, ()| {
lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|cx: &Ctx| {
let mime =
if me.is_dir() { MIME_DIR } else { cx.manager.mimetype.get(&me.url).unwrap_or_default() };
Ok(THEME.filetypes.iter().find(|&x| x.matches(me, mime)).map(|x| Style::from(x.style)))
THEME.filetypes.iter().find(|&x| x.matches(me, mime)).map(|x| Style::from(x.style))
})
});
reg.add_method("is_hovered", |_, me, ()| Ok(me.idx == me.folder().cursor));
reg.add_method("is_yanked", |lua, me, ()| {
let cx = lua.named_registry_value::<CtxRef>("cx")?;
Ok(if !cx.manager.yanked.contains(&me.url) {
methods.add_method("is_hovered", |_, me, ()| Ok(me.idx == me.folder().cursor));
methods.add_method("is_yanked", |lua, me, ()| {
lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|cx: &Ctx| {
if !cx.manager.yanked.contains(&me.url) {
0u8
} else if cx.manager.yanked.cut {
2u8
} else {
1u8
}
})
});
reg.add_method("is_marked", |_, me, ()| {
methods.add_method("is_marked", |_, me, ()| {
use yazi_core::tab::Mode::*;
if !me.tab().mode.is_visual() || me.folder().url != me.tab().current.url {
return Ok(0u8);
@ -84,16 +100,16 @@ impl File {
_ => 0u8,
})
});
reg.add_method("is_selected", |_, me, ()| Ok(me.tab().selected.contains_key(&me.url)));
reg.add_method("in_parent", |_, me, ()| {
methods.add_method("is_selected", |_, me, ()| Ok(me.tab().selected.contains_key(&me.url)));
methods.add_method("in_parent", |_, me, ()| {
Ok(me.tab().parent.as_ref().is_some_and(|f| me.folder().url == f.url))
});
reg.add_method("in_current", |_, me, ()| Ok(me.folder().url == me.tab().current.url));
reg.add_method("in_preview", |_, me, ()| {
methods.add_method("in_current", |_, me, ()| Ok(me.folder().url == me.tab().current.url));
methods.add_method("in_preview", |_, me, ()| {
Ok(me.tab().hovered().is_some_and(|f| f.url == me.folder().url))
});
reg.add_method("found", |lua, me, ()| {
let cx = lua.named_registry_value::<CtxRef>("cx")?;
methods.add_method("found", |lua, me, ()| {
lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|cx: &Ctx| {
let Some(finder) = &cx.manager.active().finder else {
return Ok(None);
};
@ -104,29 +120,20 @@ impl File {
Some(lua.create_sequence_from([idx.into_lua(lua)?, finder.matched().len().into_lua(lua)?]))
.transpose()
})
});
reg.add_method("highlights", |lua, me, ()| {
let cx = lua.named_registry_value::<CtxRef>("cx")?;
methods.add_method("highlights", |lua, me, ()| {
lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|cx: &Ctx| {
let Some(finder) = &cx.manager.active().finder else {
return Ok(None);
return None;
};
if me.folder().url != me.tab().current.url {
return Ok(None);
return None;
}
let Some(h) = finder.filter.highlighted(me.name()) else {
return Ok(None);
};
Ok(Some(h.into_iter().map(Range::from).collect::<Vec<_>>()))
let h = finder.filter.highlighted(me.name())?;
Some(h.into_iter().map(Range::from).collect::<Vec<_>>())
})
});
})?;
Ok(())
}
#[inline]
fn folder(&self) -> &yazi_fs::Folder { unsafe { &*self.folder } }
#[inline]
fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } }
}

View file

@ -1,8 +1,8 @@
use std::ops::{Deref, Range};
use mlua::{AnyUserData, Lua, MetaMethod, UserDataFields, UserDataMethods};
use mlua::{AnyUserData, MetaMethod, UserData, UserDataFields, UserDataMethods};
use super::{File, Filter, SCOPE};
use super::{File, Filter, Lives};
pub(super) struct Files {
window: Range<usize>,
@ -22,27 +22,8 @@ impl Files {
window: Range<usize>,
folder: &yazi_fs::Folder,
tab: &yazi_core::tab::Tab,
) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { window, folder, tab })
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
reg.add_field_method_get("filter", |_, me| me.filter().map(Filter::make).transpose());
reg.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.window.end - me.window.start));
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(File::make(idx - 1, me.folder(), me.tab())).transpose()
}
});
})?;
Ok(())
) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { window, folder, tab })
}
#[inline]
@ -51,3 +32,22 @@ impl Files {
#[inline]
fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } }
}
impl UserData for Files {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("filter", |_, me| me.filter().map(Filter::make).transpose());
}
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.window.end - me.window.start));
methods.add_meta_method(MetaMethod::Index, |_, me, mut idx: usize| {
idx += me.window.start;
if idx > me.window.end || idx == 0 {
Ok(None)
} else {
Some(File::make(idx - 1, me.folder(), me.tab())).transpose()
}
});
}
}

View file

@ -1,8 +1,8 @@
use std::ops::Deref;
use mlua::{AnyUserData, Lua, MetaMethod, UserDataMethods};
use mlua::{AnyUserData, MetaMethod, UserData, UserDataMethods};
use super::SCOPE;
use super::Lives;
pub(super) struct Filter {
inner: *const yazi_fs::Filter,
@ -16,13 +16,13 @@ impl Deref for Filter {
impl Filter {
#[inline]
pub(super) fn make(inner: &yazi_fs::Filter) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { inner })
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
reg.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.to_string()));
})
pub(super) fn make(inner: &yazi_fs::Filter) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { inner })
}
}
impl UserData for Filter {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.to_string()));
}
}

View file

@ -1,8 +1,8 @@
use std::ops::Deref;
use mlua::{AnyUserData, Lua, MetaMethod, UserDataMethods};
use mlua::{AnyUserData, MetaMethod, UserData, UserDataMethods};
use super::SCOPE;
use super::Lives;
pub(super) struct Finder {
inner: *const yazi_core::tab::Finder,
@ -16,13 +16,13 @@ impl Deref for Finder {
impl Finder {
#[inline]
pub(super) fn make(inner: &yazi_core::tab::Finder) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { inner })
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
reg.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.filter.to_string()));
})
pub(super) fn make(inner: &yazi_core::tab::Finder) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { inner })
}
}
impl UserData for Finder {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.filter.to_string()));
}
}

View file

@ -1,10 +1,10 @@
use std::ops::{Deref, Range};
use mlua::{AnyUserData, Lua, UserDataFields};
use mlua::{AnyUserData, Lua, UserData, UserDataFields};
use yazi_config::LAYOUT;
use yazi_plugin::{bindings::Cast, url::Url};
use super::{File, Files, SCOPE};
use super::{File, Files, Lives};
pub(super) struct Folder {
window: Range<usize>,
@ -24,7 +24,7 @@ impl Folder {
window: Option<Range<usize>>,
inner: &yazi_fs::Folder,
tab: &yazi_core::tab::Tab,
) -> mlua::Result<AnyUserData<'static>> {
) -> mlua::Result<AnyUserData> {
let window = match window {
Some(w) => w,
None => {
@ -33,23 +33,10 @@ impl Folder {
}
};
SCOPE.create_any_userdata(Self { window, inner, tab })
Lives::scoped_userdata(Self { window, inner, tab })
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
reg.add_field_method_get("cwd", |lua, me| Url::cast(lua, me.url.to_owned()));
reg.add_field_method_get("files", |_, me| Files::make(0..me.files.len(), me, me.tab()));
reg.add_field_method_get("stage", |lua, me| lua.create_any_userdata(me.stage));
reg.add_field_method_get("window", |_, me| Files::make(me.window.clone(), me, me.tab()));
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", |_, me| {
me.hovered().map(|_| File::make(me.cursor, me, me.tab())).transpose()
});
})?;
lua.register_userdata_type::<yazi_fs::FolderStage>(|reg| {
reg.add_field_method_get("is_loading", |_, me| Ok(*me == yazi_fs::FolderStage::Loading));
})?;
@ -60,3 +47,18 @@ impl Folder {
#[inline]
fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } }
}
impl UserData for Folder {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("cwd", |lua, me| Url::cast(lua, me.url.to_owned()));
fields.add_field_method_get("files", |_, me| Files::make(0..me.files.len(), me, me.tab()));
fields.add_field_method_get("stage", |lua, me| lua.create_any_userdata(me.stage));
fields.add_field_method_get("window", |_, me| Files::make(me.window.clone(), me, me.tab()));
fields.add_field_method_get("offset", |_, me| Ok(me.offset));
fields.add_field_method_get("cursor", |_, me| Ok(me.cursor));
fields.add_field_method_get("hovered", |_, me| {
me.hovered().map(|_| File::make(me.cursor, me, me.tab())).transpose()
});
}
}

View file

@ -1,6 +1,6 @@
use mlua::AnyUserData;
use mlua::{AnyUserData, UserData};
use super::SCOPE;
use super::Lives;
pub(super) struct Iter<I: Iterator<Item = T>, T> {
inner: I,
@ -9,8 +9,8 @@ pub(super) struct Iter<I: Iterator<Item = T>, T> {
impl<I: Iterator<Item = T> + 'static, T: 'static> Iter<I, T> {
#[inline]
pub(super) fn make(inner: I) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { inner, count: 0 })
pub(super) fn make(inner: I) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { inner, count: 0 })
}
}
@ -23,3 +23,5 @@ impl<I: Iterator<Item = T>, T> Iterator for Iter<I, T> {
Some((self.count, next))
}
}
impl<I: Iterator<Item = T>, T> UserData for Iter<I, T> {}

View file

@ -1,49 +1,33 @@
use std::mem;
use std::cell::RefCell;
use mlua::Scope;
use scopeguard::defer;
use mlua::{AnyUserData, UserData};
use tracing::error;
use yazi_plugin::LUA;
use yazi_shared::RoCell;
use crate::Ctx;
pub(super) static SCOPE: RoCell<&mlua::Scope> = RoCell::new();
static TO_DESTROY: RoCell<RefCell<Vec<AnyUserData>>> = RoCell::new_const(RefCell::new(Vec::new()));
pub(crate) struct Lives;
impl Lives {
pub(crate) fn register() -> mlua::Result<()> {
super::Config::register(&LUA)?;
super::File::register(&LUA)?;
super::Files::register(&LUA)?;
super::Filter::register(&LUA)?;
super::Finder::register(&LUA)?;
super::Folder::register(&LUA)?;
super::Mode::register(&LUA)?;
super::Preview::register(&LUA)?;
super::Selected::register(&LUA)?;
super::Tab::register(&LUA)?;
super::Tabs::register(&LUA)?;
super::Tasks::register(&LUA)?;
super::Yanked::register(&LUA)?;
Ok(())
}
pub(crate) fn scope<'a, T>(
cx: &'a Ctx,
f: impl FnOnce(&Scope<'a, 'a>) -> mlua::Result<T>,
) -> mlua::Result<T> {
pub(crate) fn scope<T>(cx: &Ctx, f: impl FnOnce() -> mlua::Result<T>) -> mlua::Result<T> {
let result = LUA.scope(|scope| {
defer! { SCOPE.drop(); }
SCOPE.init(unsafe {
mem::transmute::<&mlua::Scope<'a, 'a>, &mlua::Scope<'static, 'static>>(scope)
scope.add_destructor(|| {
for ud in TO_DESTROY.borrow_mut().drain(..) {
ud.destroy().expect("failed to destruct scoped userdata");
}
});
LUA.set_named_registry_value("cx", scope.create_any_userdata_ref(cx)?)?;
let globals = LUA.globals();
globals.raw_set(
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.manager.active())?),
@ -53,7 +37,7 @@ impl Lives {
])?,
)?;
f(scope)
f()
});
if let Err(ref e) = result {
@ -61,4 +45,14 @@ impl Lives {
}
result
}
#[inline]
pub(crate) fn scoped_userdata<T>(data: T) -> mlua::Result<AnyUserData>
where
T: UserData + 'static,
{
let ud = LUA.create_userdata(data)?;
TO_DESTROY.borrow_mut().push(ud.clone());
Ok(ud)
}
}

View file

@ -4,5 +4,3 @@ yazi_macro::mod_flat!(
config file files filter finder folder iter lives mode preview selected tab tabs
tasks yanked
);
type CtxRef<'lua> = mlua::UserDataRef<'lua, crate::Ctx>;

View file

@ -1,8 +1,8 @@
use std::ops::Deref;
use mlua::{AnyUserData, Lua, MetaMethod, UserDataFields, UserDataMethods};
use mlua::{AnyUserData, MetaMethod, UserData, UserDataFields, UserDataMethods};
use super::SCOPE;
use super::Lives;
pub(super) struct Mode {
inner: *const yazi_core::tab::Mode,
@ -16,17 +16,19 @@ impl Deref for Mode {
impl Mode {
#[inline]
pub(super) fn make(inner: &yazi_core::tab::Mode) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { inner })
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|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_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.to_string()));
})
pub(super) fn make(inner: &yazi_core::tab::Mode) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { inner })
}
}
impl UserData for Mode {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("is_select", |_, me| Ok(me.is_select()));
fields.add_field_method_get("is_unset", |_, me| Ok(me.is_unset()));
fields.add_field_method_get("is_visual", |_, me| Ok(me.is_visual()));
}
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.to_string()));
}
}

View file

@ -1,9 +1,9 @@
use std::ops::Deref;
use mlua::{AnyUserData, Lua, UserDataFields};
use mlua::{AnyUserData, UserData, UserDataFields};
use yazi_config::LAYOUT;
use super::{Folder, SCOPE};
use super::{Folder, Lives};
pub(super) struct Preview {
tab: *const yazi_core::tab::Tab,
@ -17,14 +17,18 @@ impl Deref for Preview {
impl Preview {
#[inline]
pub(super) fn make(tab: &yazi_core::tab::Tab) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { tab })
pub(super) fn make(tab: &yazi_core::tab::Tab) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { tab })
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
reg.add_field_method_get("skip", |_, me| Ok(me.skip));
reg.add_field_method_get("folder", |_, me| {
#[inline]
fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } }
}
impl UserData for Preview {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("skip", |_, me| Ok(me.skip));
fields.add_field_method_get("folder", |_, me| {
me.tab()
.hovered_folder()
.map(|f| {
@ -33,9 +37,5 @@ impl Preview {
})
.transpose()
});
})
}
#[inline]
fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } }
}

View file

@ -1,9 +1,9 @@
use std::{collections::{HashMap, hash_map}, ops::Deref};
use mlua::{AnyUserData, IntoLuaMulti, Lua, MetaMethod, UserDataMethods, UserDataRefMut};
use mlua::{AnyUserData, IntoLuaMulti, MetaMethod, UserData, UserDataMethods, UserDataRefMut};
use yazi_plugin::{bindings::Cast, url::Url};
use super::{Iter, SCOPE};
use super::{Iter, Lives};
#[derive(Clone, Copy)]
pub(super) struct Selected {
@ -18,17 +18,19 @@ impl Deref for Selected {
impl Selected {
#[inline]
pub(super) fn make(
inner: &HashMap<yazi_shared::fs::Url, u64>,
) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { inner })
pub(super) fn make(inner: &HashMap<yazi_shared::fs::Url, u64>) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { inner })
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
reg.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.len()));
#[inline]
fn inner(&self) -> &'static HashMap<yazi_shared::fs::Url, u64> { unsafe { &*self.inner } }
}
reg.add_meta_method(MetaMethod::Pairs, |lua, me, ()| {
impl UserData for Selected {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.len()));
methods.add_meta_method(MetaMethod::Pairs, |lua, me, ()| {
let iter = lua.create_function(
|lua, mut iter: UserDataRefMut<Iter<hash_map::Keys<yazi_shared::fs::Url, u64>, _>>| {
if let Some(next) = iter.next() {
@ -41,11 +43,5 @@ impl Selected {
Ok((iter, Iter::make(me.inner().keys())))
});
})?;
Ok(())
}
#[inline]
fn inner(&self) -> &'static HashMap<yazi_shared::fs::Url, u64> { unsafe { &*self.inner } }
}

View file

@ -1,9 +1,9 @@
use std::ops::Deref;
use mlua::{AnyUserData, Lua, UserDataFields, UserDataMethods};
use mlua::{AnyUserData, UserData, UserDataFields, UserDataMethods};
use yazi_plugin::url::UrlRef;
use super::{Config, Finder, Folder, Mode, Preview, SCOPE, Selected};
use super::{Config, Finder, Folder, Lives, Mode, Preview, Selected};
pub(super) struct Tab {
inner: *const yazi_core::tab::Tab,
@ -17,33 +17,33 @@ impl Deref for Tab {
impl Tab {
#[inline]
pub(super) fn make(inner: &yazi_core::tab::Tab) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { inner })
pub(super) fn make(inner: &yazi_core::tab::Tab) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { inner })
}
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
reg.add_field_method_get("id", |_, me| Ok(me.id.get()));
reg.add_method("name", |lua, me, ()| {
lua.create_string(me.current.url.name().as_encoded_bytes())
});
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("current", |_, me| Folder::make(None, &me.current, me));
reg.add_field_method_get("parent", |_, me| {
impl UserData for Tab {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("id", |_, me| Ok(me.id.get()));
fields.add_field_method_get("mode", |_, me| Mode::make(&me.mode));
fields.add_field_method_get("conf", |_, me| Config::make(&me.conf));
fields.add_field_method_get("current", |_, me| Folder::make(None, &me.current, me));
fields.add_field_method_get("parent", |_, me| {
me.parent.as_ref().map(|f| Folder::make(None, f, me)).transpose()
});
reg.add_method("history", |_, me, url: UrlRef| {
fields.add_field_method_get("selected", |_, me| Selected::make(&me.selected));
fields.add_field_method_get("preview", |_, me| Preview::make(me));
fields.add_field_method_get("finder", |_, me| me.finder.as_ref().map(Finder::make).transpose());
}
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_method("name", |lua, me, ()| {
lua.create_string(me.current.url.name().as_encoded_bytes())
});
methods.add_method("history", |_, me, url: UrlRef| {
me.history.get(&url).map(|f| Folder::make(None, f, me)).transpose()
});
reg.add_field_method_get("selected", |_, me| Selected::make(&me.selected));
reg.add_field_method_get("preview", |_, me| Preview::make(me));
reg.add_field_method_get("finder", |_, me| me.finder.as_ref().map(Finder::make).transpose());
})?;
Ok(())
}
}

View file

@ -1,8 +1,8 @@
use std::ops::Deref;
use mlua::{AnyUserData, Lua, MetaMethod, UserDataFields, UserDataMethods};
use mlua::{AnyUserData, MetaMethod, UserData, UserDataFields, UserDataMethods};
use super::{SCOPE, Tab};
use super::{Lives, Tab};
pub(super) struct Tabs {
inner: *const yazi_core::manager::Tabs,
@ -16,25 +16,21 @@ impl Deref for Tabs {
impl Tabs {
#[inline]
pub(super) fn make(inner: &yazi_core::manager::Tabs) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { inner })
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
reg.add_field_method_get("idx", |_, me| Ok(me.cursor + 1));
reg.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.len()));
reg.add_meta_method(MetaMethod::Index, |_, me, idx: usize| {
if idx > me.len() || idx == 0 {
Ok(None)
} else {
Some(Tab::make(&me[idx - 1])).transpose()
}
});
})?;
Ok(())
pub(super) fn make(inner: &yazi_core::manager::Tabs) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { inner })
}
}
impl UserData for Tabs {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("idx", |_, me| Ok(me.cursor + 1));
}
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.len()));
methods.add_meta_method(MetaMethod::Index, |_, me, idx: usize| {
if idx > me.len() || idx == 0 { Ok(None) } else { Some(Tab::make(&me[idx - 1])).transpose() }
});
}
}

View file

@ -1,8 +1,8 @@
use std::ops::Deref;
use mlua::{AnyUserData, Lua, LuaSerdeExt, UserDataFields};
use mlua::{AnyUserData, LuaSerdeExt, UserData, UserDataFields};
use super::SCOPE;
use super::Lives;
pub(super) struct Tasks {
inner: *const yazi_core::tasks::Tasks,
@ -16,15 +16,13 @@ impl Deref for Tasks {
impl Tasks {
#[inline]
pub(super) fn make(inner: &yazi_core::tasks::Tasks) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { inner })
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
reg.add_field_method_get("progress", |lua, me| lua.to_value(&me.progress))
})?;
Ok(())
pub(super) fn make(inner: &yazi_core::tasks::Tasks) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { inner })
}
}
impl UserData for Tasks {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("progress", |lua, me| lua.to_value(&me.progress))
}
}

View file

@ -1,9 +1,9 @@
use std::{collections::hash_set, ops::Deref};
use mlua::{AnyUserData, IntoLuaMulti, Lua, MetaMethod, UserDataFields, UserDataMethods, UserDataRefMut};
use mlua::{AnyUserData, IntoLuaMulti, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRefMut};
use yazi_plugin::{bindings::Cast, url::Url};
use super::{Iter, SCOPE};
use super::{Iter, Lives};
pub(super) struct Yanked {
inner: *const yazi_core::manager::Yanked,
@ -17,17 +17,23 @@ impl Deref for Yanked {
impl Yanked {
#[inline]
pub(super) fn make(inner: &yazi_core::manager::Yanked) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self { inner })
pub(super) fn make(inner: &yazi_core::manager::Yanked) -> mlua::Result<AnyUserData> {
Lives::scoped_userdata(Self { inner })
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
reg.add_field_method_get("is_cut", |_, me| Ok(me.cut));
#[inline]
fn inner(&self) -> &'static yazi_core::manager::Yanked { unsafe { &*self.inner } }
}
reg.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.len()));
impl UserData for Yanked {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("is_cut", |_, me| Ok(me.cut));
}
reg.add_meta_method(MetaMethod::Pairs, |lua, me, ()| {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.len()));
methods.add_meta_method(MetaMethod::Pairs, |lua, me, ()| {
let iter = lua.create_function(
|lua, mut iter: UserDataRefMut<Iter<hash_set::Iter<yazi_shared::fs::Url>, _>>| {
if let Some(next) = iter.next() {
@ -40,9 +46,5 @@ impl Yanked {
Ok((iter, Iter::make(me.inner().iter())))
});
})
}
#[inline]
fn inner(&self) -> &'static yazi_core::manager::Yanked { unsafe { &*self.inner } }
}

View file

@ -1,4 +1,4 @@
use mlua::{Table, TableExt};
use mlua::{ObjectLike, Table};
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
use tracing::error;
use yazi_plugin::{LUA, elements::render_widgets};
@ -13,9 +13,9 @@ pub(super) struct Root<'a> {
impl<'a> Root<'a> {
pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(super) fn reflow<'lua>(area: Rect) -> mlua::Result<Table<'lua>> {
pub(super) fn reflow(area: Rect) -> mlua::Result<Table> {
let area = yazi_plugin::elements::Rect::from(area);
let root = LUA.globals().raw_get::<_, Table>("Root")?.call_method::<_, Table>("new", area)?;
let root = LUA.globals().raw_get::<Table>("Root")?.call_method::<Table>("new", area)?;
root.call_method("reflow", ())
}
}
@ -24,7 +24,7 @@ impl<'a> Widget for Root<'a> {
fn render(self, area: Rect, buf: &mut Buffer) {
let mut f = || {
let area = yazi_plugin::elements::Rect::from(area);
let root = LUA.globals().raw_get::<_, Table>("Root")?.call_method::<_, Table>("new", area)?;
let root = LUA.globals().raw_get::<Table>("Root")?.call_method::<Table>("new", area)?;
render_widgets(root.call_method("redraw", ())?, buf);
Ok::<_, mlua::Error>(())

View file

@ -1,4 +1,4 @@
use mlua::{Table, TableExt};
use mlua::{ObjectLike, Table};
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
use tracing::error;
use yazi_config::LAYOUT;
@ -11,7 +11,7 @@ impl Widget for Progress {
let mut f = || {
let area = yazi_plugin::elements::Rect::from(LAYOUT.get().progress);
let progress =
LUA.globals().raw_get::<_, Table>("Progress")?.call_method::<_, Table>("use", area)?;
LUA.globals().raw_get::<Table>("Progress")?.call_method::<Table>("use", area)?;
render_widgets(progress.call_method("redraw", ())?, buf);
Ok::<_, mlua::Error>(())

View file

@ -1,3 +1,5 @@
use mlua::Lua;
pub trait Cast<T> {
fn cast(lua: &mlua::Lua, data: T) -> mlua::Result<mlua::AnyUserData>;
fn cast(lua: &Lua, data: T) -> mlua::Result<mlua::AnyUserData>;
}

View file

@ -17,10 +17,7 @@ impl Icon {
}
impl Cast<&'static yazi_shared::theme::Icon> for Icon {
fn cast<'lua>(
lua: &'lua Lua,
data: &'static yazi_shared::theme::Icon,
) -> mlua::Result<AnyUserData<'lua>> {
fn cast(lua: &Lua, data: &'static yazi_shared::theme::Icon) -> mlua::Result<AnyUserData> {
lua.create_any_userdata(data)
}
}

View file

@ -28,8 +28,8 @@ impl<T: StreamExt<Item = Result<String, InputError>>> InputRx<T> {
}
impl<T: StreamExt<Item = Result<String, InputError>> + 'static> UserData for InputRx<T> {
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_async_method_mut("recv", |_, me, ()| async move {
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
methods.add_async_method_mut("recv", |_, mut me, ()| async move {
let mut inner = unsafe { Pin::new_unchecked(&mut me.inner) };
Ok(inner.next().await.map(Self::parse).unwrap_or((None, 0)))
});

View file

@ -3,7 +3,7 @@ use std::{mem, ops::Deref};
use mlua::{UserData, prelude::LuaUserDataMethods};
use tokio::sync::SemaphorePermit;
pub type PermitRef<'lua, F> = mlua::UserDataRef<'lua, Permit<F>>;
pub type PermitRef<F> = mlua::UserDataRef<Permit<F>>;
pub struct Permit<F: FnOnce()> {
inner: Option<SemaphorePermit<'static>>,
@ -36,7 +36,7 @@ impl<F: FnOnce()> Drop for Permit<F> {
}
impl<F: FnOnce()> UserData for Permit<F> {
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
methods.add_method_mut("drop", |_, me, ()| Ok(me.dropping()));
}
}

View file

@ -1,6 +1,6 @@
use std::{ops::Deref, str::FromStr};
use mlua::{ExternalResult, IntoLua};
use mlua::{ExternalResult, IntoLua, Lua};
pub struct Position(yazi_config::popup::Position);
@ -14,14 +14,14 @@ impl From<Position> for yazi_config::popup::Position {
fn from(value: Position) -> Self { value.0 }
}
impl<'a> TryFrom<mlua::Table<'a>> for Position {
impl TryFrom<mlua::Table> for Position {
type Error = mlua::Error;
fn try_from(t: mlua::Table<'a>) -> Result<Self, Self::Error> {
fn try_from(t: mlua::Table) -> Result<Self, Self::Error> {
use yazi_config::popup::{Offset, Origin, Position};
Ok(Self(Position {
origin: Origin::from_str(t.raw_get::<_, mlua::String>(1)?.to_str()?).into_lua_err()?,
origin: Origin::from_str(&t.raw_get::<mlua::String>(1)?.to_str()?).into_lua_err()?,
offset: Offset {
x: t.raw_get("x").unwrap_or_default(),
y: t.raw_get("y").unwrap_or_default(),
@ -32,8 +32,8 @@ impl<'a> TryFrom<mlua::Table<'a>> for Position {
}
}
impl IntoLua<'_> for Position {
fn into_lua(self, lua: &mlua::Lua) -> mlua::Result<mlua::Value> {
impl IntoLua for Position {
fn into_lua(self, lua: &Lua) -> mlua::Result<mlua::Value> {
lua
.create_table_from([
(1.into_lua(lua)?, self.origin.to_string().into_lua(lua)?),

View file

@ -1,4 +1,4 @@
use mlua::IntoLua;
use mlua::{IntoLua, Lua};
pub struct Range<T>(std::ops::Range<T>);
@ -6,11 +6,11 @@ impl<T> From<std::ops::Range<T>> for Range<T> {
fn from(value: std::ops::Range<T>) -> Self { Self(value) }
}
impl<'lua, T> IntoLua<'lua> for Range<T>
impl<T> IntoLua for Range<T>
where
T: IntoLua<'lua>,
T: IntoLua,
{
fn into_lua(self, lua: &'lua mlua::Lua) -> mlua::Result<mlua::Value<'lua>> {
fn into_lua(self, lua: &Lua) -> mlua::Result<mlua::Value> {
lua.create_sequence_from([self.0.start, self.0.end])?.into_lua(lua)
}
}

View file

@ -17,7 +17,7 @@ impl Default for Window {
}
impl UserData for Window {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("rows", |_, me| Ok(me.rows));
fields.add_field_method_get("cols", |_, me| Ok(me.cols));
fields.add_field_method_get("width", |_, me| Ok(me.width));

View file

@ -1,8 +1,10 @@
#![allow(clippy::module_inception)]
use mlua::Lua;
yazi_macro::mod_flat!(cha);
pub fn pour(lua: &mlua::Lua) -> mlua::Result<()> {
pub fn pour(lua: &Lua) -> mlua::Result<()> {
cha::Cha::register(lua)?;
cha::Cha::install(lua)?;

View file

@ -35,7 +35,7 @@ impl Bar {
}
impl UserData for Bar {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
crate::impl_area_method!(methods);
crate::impl_style_method!(methods, style);

View file

@ -53,7 +53,7 @@ impl Border {
}
impl UserData for Border {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
crate::impl_area_method!(methods);
crate::impl_style_method!(methods, style);

View file

@ -55,7 +55,7 @@ impl Renderable for Clear {
}
impl UserData for Clear {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
crate::impl_area_method!(methods);
}
}

View file

@ -14,7 +14,7 @@ impl From<Constraint> for ratatui::layout::Constraint {
}
impl UserData for Constraint {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
use ratatui::layout::Constraint as C;
methods.add_function("Min", |_, n: u16| Ok(Self(C::Min(n))));

View file

@ -21,7 +21,7 @@ impl Gauge {
}
impl UserData for Gauge {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
crate::impl_area_method!(methods);
crate::impl_style_method!(methods, style);

View file

@ -25,7 +25,7 @@ impl Layout {
}
impl UserData for Layout {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_function_mut("direction", |_, (ud, value): (AnyUserData, bool)| {
ud.borrow_mut::<Self>()?.direction = value;
Ok(ud)

View file

@ -20,7 +20,8 @@ impl Line {
let new = lua.create_function(|_, (_, value): (Table, Value)| Line::try_from(value))?;
let parse = lua.create_function(|_, code: mlua::String| {
let Some(line) = code.as_bytes().split_inclusive(|&b| b == b'\n').next() else {
let code = code.as_bytes();
let Some(line) = code.split_inclusive(|&b| b == b'\n').next() else {
return Ok(Line(Default::default()));
};
@ -46,13 +47,13 @@ impl Line {
}
}
impl TryFrom<Value<'_>> for Line {
impl TryFrom<Value> for Line {
type Error = mlua::Error;
fn try_from(value: Value) -> Result<Self, Self::Error> {
Ok(Self(match value {
Value::Table(tb) => return Self::try_from(tb),
Value::String(s) => s.to_string_lossy().into_owned().into(),
Value::String(s) => s.to_string_lossy().into(),
Value::UserData(ud) => {
if let Ok(Span(span)) = ud.take() {
span.into()
@ -68,14 +69,14 @@ impl TryFrom<Value<'_>> for Line {
}
}
impl TryFrom<Table<'_>> for Line {
impl TryFrom<Table> for Line {
type Error = mlua::Error;
fn try_from(tb: Table) -> Result<Self, Self::Error> {
let mut spans = Vec::with_capacity(tb.raw_len());
for v in tb.sequence_values() {
match v? {
Value::String(s) => spans.push(s.to_string_lossy().into_owned().into()),
Value::String(s) => spans.push(s.to_string_lossy().into()),
Value::UserData(ud) => {
if let Ok(Span(span)) = ud.take() {
spans.push(span);
@ -94,7 +95,7 @@ impl TryFrom<Table<'_>> for Line {
}
impl UserData for Line {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
crate::impl_style_method!(methods, 0.style);
crate::impl_style_shorthands!(methods, 0.style);

View file

@ -31,7 +31,7 @@ impl List {
}
impl UserData for List {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
crate::impl_area_method!(methods);
}
}

View file

@ -49,7 +49,7 @@ impl Padding {
}
impl UserData for Padding {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("left", |_, me| Ok(me.left));
fields.add_field_method_get("right", |_, me| Ok(me.right));
fields.add_field_method_get("top", |_, me| Ok(me.top));

View file

@ -41,7 +41,7 @@ impl Paragraph {
.load(mlua::chunk! {
return ui.Text($lines):area($area)
})
.call::<_, MultiValue>(())
.call::<MultiValue>(())
})?,
),
(
@ -52,7 +52,7 @@ impl Paragraph {
.load(mlua::chunk! {
return ui.Text[$key]
})
.call::<_, MultiValue>(())
.call::<MultiValue>(())
})?,
),
])?;

View file

@ -30,7 +30,7 @@ impl Position {
}
impl UserData for Position {
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("x", |_, me| Ok(me.x));
fields.add_field_method_get("y", |_, me| Ok(me.y));
}

View file

@ -43,7 +43,7 @@ impl Rect {
}
impl UserData for Rect {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("x", |_, me| Ok(me.x));
fields.add_field_method_get("y", |_, me| Ok(me.y));
fields.add_field_method_get("w", |_, me| Ok(me.width));
@ -55,7 +55,7 @@ impl UserData for Rect {
fields.add_field_method_get("bottom", |_, me| Ok(me.bottom()));
}
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_method("padding", |_, me, padding: Padding| {
let mut r = **me;
r.x = r.x.saturating_add(padding.left);

View file

@ -12,12 +12,12 @@ impl Span {
}
}
impl TryFrom<Value<'_>> for Span {
impl TryFrom<Value> for Span {
type Error = mlua::Error;
fn try_from(value: Value<'_>) -> Result<Self, Self::Error> {
fn try_from(value: Value) -> Result<Self, Self::Error> {
Ok(Self(match value {
Value::String(s) => s.to_string_lossy().into_owned().into(),
Value::String(s) => s.to_string_lossy().into(),
Value::UserData(ud) => {
if let Ok(Span(span)) = ud.take() {
span
@ -31,7 +31,7 @@ impl TryFrom<Value<'_>> for Span {
}
impl UserData for Span {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
crate::impl_style_method!(methods, 0.style);
crate::impl_style_shorthands!(methods, 0.style);

View file

@ -17,16 +17,16 @@ impl Style {
}
}
impl<'a> TryFrom<Table<'a>> for Style {
impl TryFrom<Table> for Style {
type Error = mlua::Error;
fn try_from(value: Table<'a>) -> Result<Self, Self::Error> {
fn try_from(value: Table) -> Result<Self, Self::Error> {
let mut style = ratatui::style::Style::default();
if let Ok(fg) = value.raw_get::<_, mlua::String>("fg") {
style.fg = Some(Color::from_str(fg.to_str()?).into_lua_err()?.into());
if let Ok(fg) = value.raw_get::<mlua::String>("fg") {
style.fg = Some(Color::from_str(&fg.to_str()?).into_lua_err()?.into());
}
if let Ok(bg) = value.raw_get::<_, mlua::String>("bg") {
style.bg = Some(Color::from_str(bg.to_str()?).into_lua_err()?.into());
if let Ok(bg) = value.raw_get::<mlua::String>("bg") {
style.bg = Some(Color::from_str(&bg.to_str()?).into_lua_err()?.into());
}
style.add_modifier =
ratatui::style::Modifier::from_bits_truncate(value.raw_get("modifier").unwrap_or_default());
@ -34,10 +34,10 @@ impl<'a> TryFrom<Table<'a>> for Style {
}
}
impl<'a> TryFrom<Value<'a>> for Style {
impl TryFrom<Value> for Style {
type Error = mlua::Error;
fn try_from(value: Value<'a>) -> Result<Self, Self::Error> {
fn try_from(value: Value) -> Result<Self, Self::Error> {
Ok(Self(match value {
Value::Nil => Default::default(),
Value::Table(tb) => Self::try_from(tb)?.0,
@ -52,7 +52,7 @@ impl From<yazi_shared::theme::Style> for Style {
}
impl UserData for Style {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
crate::impl_style_shorthands!(methods, 0);
methods.add_function_mut("patch", |_, (ud, value): (AnyUserData, Value)| {

View file

@ -36,7 +36,7 @@ impl Table {
}
impl UserData for Table {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
crate::impl_area_method!(methods);
methods.add_function_mut("header", |_, (ud, row): (AnyUserData, TableRow)| {
@ -114,7 +114,7 @@ impl From<TableRow> for ratatui::widgets::Row<'static> {
}
impl UserData for TableRow {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
crate::impl_style_method!(methods, style);
methods.add_function_mut("height", |_, (ud, value): (AnyUserData, u16)| {

View file

@ -31,7 +31,7 @@ impl Text {
let new = lua.create_function(|_, (_, value): (Table, Value)| Text::try_from(value))?;
let parse = lua.create_function(|_, code: mlua::String| {
Ok(Text { inner: code.into_text().into_lua_err()?, ..Default::default() })
Ok(Text { inner: code.as_bytes().into_text().into_lua_err()?, ..Default::default() })
})?;
let text = lua.create_table_from([
@ -52,13 +52,13 @@ impl Text {
}
}
impl TryFrom<Value<'_>> for Text {
impl TryFrom<Value> for Text {
type Error = mlua::Error;
fn try_from(value: Value) -> mlua::Result<Self> {
let inner = match value {
Value::Table(tb) => return Self::try_from(tb),
Value::String(s) => s.to_string_lossy().into_owned().into(),
Value::String(s) => s.to_string_lossy().into(),
Value::UserData(ud) => {
if let Ok(Line(line)) = ud.take() {
line.into()
@ -74,14 +74,14 @@ impl TryFrom<Value<'_>> for Text {
}
}
impl TryFrom<Table<'_>> for Text {
impl TryFrom<Table> for Text {
type Error = mlua::Error;
fn try_from(tb: Table<'_>) -> Result<Self, Self::Error> {
fn try_from(tb: Table) -> Result<Self, Self::Error> {
let mut lines = Vec::with_capacity(tb.raw_len());
for v in tb.sequence_values() {
match v? {
Value::String(s) => lines.push(s.to_string_lossy().into_owned().into()),
Value::String(s) => lines.push(s.to_string_lossy().into()),
Value::UserData(ud) => {
if let Ok(Span(span)) = ud.take() {
lines.push(span.into());
@ -116,7 +116,7 @@ impl From<Text> for ratatui::widgets::Paragraph<'static> {
}
impl UserData for Text {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
crate::impl_area_method!(methods);
crate::impl_style_method!(methods, inner.style);
crate::impl_style_shorthands!(methods, inner.style);

View file

@ -1,49 +1,18 @@
use mlua::{AnyUserData, Lua, Table, UserDataFields, UserDataMethods, UserDataRef, UserDataRegistry};
use yazi_config::THEME;
use mlua::{AnyUserData, Lua, Table, UserDataRef};
use crate::{bindings::{Cast, Icon}, cha::Cha, url::Url};
use crate::{bindings::Cast, impl_file_fields, impl_file_methods};
pub type FileRef<'lua> = UserDataRef<'lua, yazi_shared::fs::File>;
pub type FileRef = UserDataRef<yazi_shared::fs::File>;
pub struct File;
impl File {
#[inline]
pub fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<yazi_shared::fs::File>(Self::register_with)
}
pub fn register_with<T>(reg: &mut UserDataRegistry<T>)
where
T: AsRef<yazi_shared::fs::File>,
{
reg.add_field_method_get("cha", |lua, me| Cha::cast(lua, me.as_ref().cha));
reg.add_field_method_get("url", |lua, me| Url::cast(lua, me.as_ref().url_owned()));
reg.add_field_method_get("link_to", |lua, me| {
me.as_ref().link_to.clone().map(|u| Url::cast(lua, u)).transpose()
});
reg.add_field_method_get("name", |lua, me| {
Some(me.as_ref().name())
.filter(|s| !s.is_empty())
.map(|s| lua.create_string(s.as_encoded_bytes()))
.transpose()
});
reg.add_method("icon", |lua, me, ()| {
use yazi_shared::theme::IconCache;
let me = me.as_ref();
match me.icon.get() {
IconCache::Missing => {
let matched = THEME.icons.matches(me);
me.icon.set(matched.map_or(IconCache::Undefined, IconCache::Icon));
matched.map(|i| Icon::cast(lua, i)).transpose()
}
IconCache::Undefined => Ok(None),
IconCache::Icon(cached) => Some(Icon::cast(lua, cached)).transpose(),
}
});
lua.register_userdata_type::<yazi_shared::fs::File>(|reg| {
impl_file_fields!(reg);
impl_file_methods!(reg);
})
}
pub fn install(lua: &Lua) -> mlua::Result<()> {
@ -51,8 +20,8 @@ impl File {
"File",
lua.create_function(|lua, t: Table| {
Self::cast(lua, yazi_shared::fs::File {
url: t.raw_get::<_, AnyUserData>("url")?.take()?,
cha: t.raw_get::<_, AnyUserData>("cha")?.take()?,
url: t.raw_get::<AnyUserData>("url")?.take()?,
cha: t.raw_get::<AnyUserData>("cha")?.take()?,
..Default::default()
})
})?,

View file

@ -1,8 +1,10 @@
#![allow(clippy::module_inception)]
use mlua::Lua;
yazi_macro::mod_flat!(file);
pub fn pour(lua: &mlua::Lua) -> mlua::Result<()> {
pub fn pour(lua: &Lua) -> mlua::Result<()> {
file::File::register(lua)?;
file::File::install(lua)?;

View file

@ -19,24 +19,24 @@ pub fn install(lua: &Lua) -> mlua::Result<()> {
};
match meta {
Ok(m) => (Cha::cast(lua, m)?, Value::Nil).into_lua_multi(lua),
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
Ok(m) => (Cha::cast(&lua, m)?, Value::Nil).into_lua_multi(&lua),
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(&lua),
}
})?,
),
(
"write",
lua.create_async_function(|lua, (url, data): (UrlRef, mlua::String)| async move {
match fs::write(&*url, data).await {
Ok(_) => (true, Value::Nil).into_lua_multi(lua),
Err(e) => (false, e.raw_os_error()).into_lua_multi(lua),
match fs::write(&*url, data.as_bytes()).await {
Ok(_) => (true, Value::Nil).into_lua_multi(&lua),
Err(e) => (false, e.raw_os_error()).into_lua_multi(&lua),
}
})?,
),
(
"remove",
lua.create_async_function(|lua, (type_, url): (mlua::String, UrlRef)| async move {
let result = match type_.to_str()? {
let result = match &*type_.to_str()? {
"file" => fs::remove_file(&*url).await,
"dir" => fs::remove_dir(&*url).await,
"dir_all" => fs::remove_dir_all(&*url).await,
@ -47,17 +47,17 @@ pub fn install(lua: &Lua) -> mlua::Result<()> {
};
match result {
Ok(_) => (true, Value::Nil).into_lua_multi(lua),
Err(e) => (false, e.raw_os_error()).into_lua_multi(lua),
Ok(_) => (true, Value::Nil).into_lua_multi(&lua),
Err(e) => (false, e.raw_os_error()).into_lua_multi(&lua),
}
})?,
),
(
"read_dir",
lua.create_async_function(|lua, (dir, options): (UrlRef, Table)| async move {
let glob = if let Ok(s) = options.raw_get::<_, mlua::String>("glob") {
let glob = if let Ok(s) = options.raw_get::<mlua::String>("glob") {
Some(
GlobBuilder::new(s.to_str()?)
GlobBuilder::new(&s.to_str()?)
.case_insensitive(true)
.literal_separator(true)
.backslash_escape(false)
@ -75,7 +75,7 @@ pub fn install(lua: &Lua) -> mlua::Result<()> {
let mut it = match fs::read_dir(&*dir).await {
Ok(it) => it,
Err(e) => return (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
Err(e) => return (Value::Nil, e.raw_os_error()).into_lua_multi(&lua),
};
let mut files = vec![];
@ -97,7 +97,7 @@ pub fn install(lua: &Lua) -> mlua::Result<()> {
} else {
yazi_shared::fs::File::from_dummy(url, next.file_type().await.ok())
};
files.push(File::cast(lua, file)?);
files.push(File::cast(&lua, file)?);
}
let tbl = lua.create_table_with_capacity(files.len(), 0)?;
@ -105,15 +105,15 @@ pub fn install(lua: &Lua) -> mlua::Result<()> {
tbl.raw_push(f)?;
}
(tbl, Value::Nil).into_lua_multi(lua)
(tbl, Value::Nil).into_lua_multi(&lua)
})?,
),
(
"unique_name",
lua.create_async_function(|lua, url: UrlRef| async move {
match yazi_shared::fs::unique_name(url.clone(), async { false }).await {
Ok(u) => (Url::cast(lua, u)?, Value::Nil).into_lua_multi(lua),
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
Ok(u) => (Url::cast(&lua, u)?, Value::Nil).into_lua_multi(&lua),
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(&lua),
}
})?,
),

View file

@ -1,4 +1,4 @@
use mlua::{ExternalError, ExternalResult, Table, TableExt};
use mlua::{ExternalError, ExternalResult, ObjectLike, Table};
use tokio::runtime::Handle;
use yazi_dds::Sendable;
use yazi_shared::event::Data;

View file

@ -1,4 +1,4 @@
use mlua::{ExternalError, ExternalResult, Table, TableExt};
use mlua::{ExternalError, ExternalResult, ObjectLike, Table};
use tokio::runtime::Handle;
use yazi_config::LAYOUT;

View file

@ -1,6 +1,6 @@
use std::borrow::Cow;
use mlua::{ExternalError, ExternalResult, HookTriggers, Table, TableExt};
use mlua::{ExternalError, ExternalResult, HookTriggers, ObjectLike, Table, VmState};
use tokio::{runtime::Handle, select};
use tokio_util::sync::CancellationToken;
use tracing::error;
@ -29,7 +29,11 @@ pub fn peek(
lua.set_hook(
HookTriggers::new().on_calls().on_returns().every_nth_instruction(2000),
move |_, _| {
if ct1.is_cancelled() { Err("Peek task cancelled".into_lua_err()) } else { Ok(()) }
if ct1.is_cancelled() {
Err("Peek task cancelled".into_lua_err())
} else {
Ok(VmState::Continue)
}
},
);

View file

@ -1,4 +1,4 @@
use mlua::{ExternalError, ExternalResult, Table, TableExt};
use mlua::{ExternalError, ExternalResult, ObjectLike, Table};
use tokio::runtime::Handle;
use yazi_config::LAYOUT;

View file

@ -1,4 +1,4 @@
use mlua::TableExt;
use mlua::ObjectLike;
use yazi_config::LAYOUT;
use yazi_proxy::{AppProxy, options::{PluginCallback, PluginOpt}};
use yazi_shared::event::Cmd;

View file

@ -11,12 +11,15 @@ impl Chunk {
fn analyze(&mut self) {
for line in self.bytes.split(|&b| b == b'\n') {
if line.trim_ascii().is_empty() {
continue;
};
let Some(rest) = line.strip_prefix(b"---") else { break };
let rest = rest.trim_ascii();
let Some(pos) = rest.iter().position(|&b| b == b' ' || b == b'\t') else { break };
match (rest[..pos].trim_ascii(), rest[pos..].trim_ascii()) {
let Some(i) = rest.iter().position(|&b| b == b' ' || b == b'\t') else { break };
match (rest[..i].trim_ascii(), rest[i..].trim_ascii()) {
(b"@sync", b"entry") => self.sync_entry = true,
(_, []) => break,
(b, _) if b.strip_prefix(b"@").unwrap_or(b"").is_empty() => break,

View file

@ -63,9 +63,9 @@ impl Loader {
Ok(())
}
pub fn load<'a>(&self, lua: &'a Lua, id: &str) -> mlua::Result<Table<'a>> {
let loaded: Table = lua.globals().raw_get::<_, Table>("package")?.raw_get("loaded")?;
if let Ok(t) = loaded.raw_get::<_, Table>(id) {
pub fn load(&self, lua: &Lua, id: &str) -> mlua::Result<Table> {
let loaded: Table = lua.globals().raw_get::<Table>("package")?.raw_get("loaded")?;
if let Ok(t) = loaded.raw_get::<Table>(id) {
return Ok(t);
}
@ -79,14 +79,14 @@ impl Loader {
Ok(t)
}
pub fn try_load<'a>(&self, lua: &'a Lua, id: &str) -> mlua::Result<Table<'a>> {
let loaded: Table = lua.globals().raw_get::<_, Table>("package")?.raw_get("loaded")?;
pub fn try_load(&self, lua: &Lua, id: &str) -> mlua::Result<Table> {
let loaded: Table = lua.globals().raw_get::<Table>("package")?.raw_get("loaded")?;
loaded.raw_get(id)
}
pub fn load_with<'a>(&self, lua: &'a Lua, id: &str, chunk: &Chunk) -> mlua::Result<Table<'a>> {
let loaded: Table = lua.globals().raw_get::<_, Table>("package")?.raw_get("loaded")?;
if let Ok(t) = loaded.raw_get::<_, Table>(id) {
pub fn load_with(&self, lua: &Lua, id: &str, chunk: &Chunk) -> mlua::Result<Table> {
let loaded: Table = lua.globals().raw_get::<Table>("package")?.raw_get("loaded")?;
if let Ok(t) = loaded.raw_get::<Table>(id) {
return Ok(t);
}

View file

@ -1,6 +1,6 @@
use std::sync::Arc;
use mlua::{ExternalResult, Function, IntoLua, Lua, MultiValue, Table, TableExt, Value};
use mlua::{ExternalResult, Function, IntoLua, Lua, MultiValue, ObjectLike, Table, Value};
use super::LOADER;
use crate::RtRef;
@ -12,7 +12,7 @@ impl Require {
lua.globals().raw_set(
"require",
lua.create_function(|lua, id: mlua::String| {
let s = id.to_str()?;
let s = &id.to_str()?;
futures::executor::block_on(LOADER.ensure(s)).into_lua_err()?;
lua.named_registry_value::<RtRef>("rt")?.push(s);
@ -28,27 +28,27 @@ impl Require {
lua.globals().raw_set(
"require",
lua.create_async_function(|lua, id: mlua::String| async move {
let s = id.to_str()?;
let s = &id.to_str()?;
LOADER.ensure(s).await.into_lua_err()?;
lua.named_registry_value::<RtRef>("rt")?.push(s);
let mod_ = LOADER.load(lua, s);
let mod_ = LOADER.load(&lua, s);
lua.named_registry_value::<RtRef>("rt")?.pop();
Self::create_mt(lua, s, mod_?, false)
Self::create_mt(&lua, s, mod_?, false)
})?,
)
}
fn create_mt<'a>(lua: &'a Lua, id: &str, mod_: Table<'a>, sync: bool) -> mlua::Result<Table<'a>> {
fn create_mt(lua: &Lua, id: &str, mod_: Table, sync: bool) -> mlua::Result<Table> {
let id: Arc<str> = Arc::from(id);
let mt = lua.create_table_from([
(
"__index",
lua.create_function(move |lua, (ts, key): (Table, mlua::String)| {
match ts.raw_get::<_, Table>("__mod")?.raw_get::<_, Value>(&key)? {
match ts.raw_get::<Table>("__mod")?.raw_get::<Value>(&key)? {
Value::Function(_) => {
Self::create_wrapper(lua, id.clone(), key.to_str()?, sync)?.into_lua(lua)
Self::create_wrapper(lua, id.clone(), &key.to_str()?, sync)?.into_lua(lua)
}
v => Ok(v),
}
@ -57,7 +57,7 @@ impl Require {
(
"__newindex",
lua.create_function(move |_, (ts, key, value): (Table, mlua::String, Value)| {
ts.raw_get::<_, Table>("__mod")?.raw_set(key, value)
ts.raw_get::<Table>("__mod")?.raw_set(key, value)
})?,
),
])?;
@ -67,19 +67,14 @@ impl Require {
Ok(ts)
}
fn create_wrapper<'a>(
lua: &'a Lua,
id: Arc<str>,
f: &str,
sync: bool,
) -> mlua::Result<Function<'a>> {
fn create_wrapper(lua: &Lua, id: Arc<str>, f: &str, sync: bool) -> mlua::Result<Function> {
let f: Arc<str> = Arc::from(f);
if sync {
lua.create_function(move |lua, args: MultiValue| {
let (mod_, args) = Self::split_mod_and_args(lua, &id, args)?;
lua.named_registry_value::<RtRef>("rt")?.push(&id);
let result = mod_.call_function::<_, MultiValue>(&f, args);
let result = mod_.call_function::<MultiValue>(&f, args);
lua.named_registry_value::<RtRef>("rt")?.pop();
result
})
@ -87,9 +82,9 @@ impl Require {
lua.create_async_function(move |lua, args: MultiValue| {
let (id, f) = (id.clone(), f.clone());
async move {
let (mod_, args) = Self::split_mod_and_args(lua, &id, args)?;
let (mod_, args) = Self::split_mod_and_args(&lua, &id, args)?;
lua.named_registry_value::<RtRef>("rt")?.push(&id);
let result = mod_.call_async_function::<_, MultiValue>(&f, args).await;
let result = mod_.call_async_function::<MultiValue>(&f, args).await;
lua.named_registry_value::<RtRef>("rt")?.pop();
result
}
@ -97,11 +92,11 @@ impl Require {
}
}
fn split_mod_and_args<'a>(
lua: &'a Lua,
fn split_mod_and_args(
lua: &Lua,
id: &str,
mut args: MultiValue<'a>,
) -> mlua::Result<(Table<'a>, MultiValue<'a>)> {
mut args: MultiValue,
) -> mlua::Result<(Table, MultiValue)> {
let Some(front) = args.pop_front() else {
return Ok((LOADER.try_load(lua, id)?, args));
};
@ -109,7 +104,7 @@ impl Require {
args.push_front(front);
return Ok((LOADER.try_load(lua, id)?, args));
};
Ok(if let Ok(mod_) = tbl.raw_get::<_, Table>("__mod") {
Ok(if let Ok(mod_) = tbl.raw_get::<Table>("__mod") {
args.push_front(Value::Table(mod_.clone()));
(mod_, args)
} else {

View file

@ -78,3 +78,46 @@ macro_rules! impl_style_shorthands {
});
};
}
#[macro_export]
macro_rules! impl_file_fields {
($fields:ident) => {
use mlua::UserDataFields;
use $crate::bindings::Cast;
$fields.add_field_method_get("cha", |lua, me| $crate::cha::Cha::cast(lua, me.cha));
$fields.add_field_method_get("url", |lua, me| $crate::url::Url::cast(lua, me.url_owned()));
$fields.add_field_method_get("link_to", |lua, me| {
me.link_to.clone().map(|u| $crate::url::Url::cast(lua, u)).transpose()
});
$fields.add_field_method_get("name", |lua, me| {
Some(me.name())
.filter(|s| !s.is_empty())
.map(|s| lua.create_string(s.as_encoded_bytes()))
.transpose()
});
};
}
#[macro_export]
macro_rules! impl_file_methods {
($methods:ident) => {
use mlua::UserDataMethods;
$methods.add_method("icon", |lua, me, ()| {
use yazi_shared::theme::IconCache;
use $crate::bindings::{Cast, Icon};
match me.icon.get() {
IconCache::Missing => {
let matched = yazi_config::THEME.icons.matches(me);
me.icon.set(matched.map_or(IconCache::Undefined, IconCache::Icon));
matched.map(|i| Icon::cast(lua, i)).transpose()
}
IconCache::Undefined => Ok(None),
IconCache::Icon(cached) => Some(Icon::cast(lua, cached)).transpose(),
}
});
};
}

View file

@ -1,4 +1,4 @@
use std::time::Duration;
use std::{ops::DerefMut, time::Duration};
use futures::future::try_join3;
use mlua::{AnyUserData, ExternalError, IntoLua, IntoLuaMulti, Table, UserData, Value};
@ -24,7 +24,7 @@ impl Child {
}
impl UserData for Child {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
#[inline]
async fn read_line(me: &mut Child) -> (Option<Vec<u8>>, u8) {
async fn read(r: Option<impl AsyncBufReadExt + Unpin>) -> Option<Vec<u8>> {
@ -42,7 +42,7 @@ impl UserData for Child {
}
}
methods.add_async_method_mut("read", |_, me, len: usize| async move {
methods.add_async_method_mut("read", |_, mut me, len: usize| async move {
async fn read(r: Option<impl AsyncBufReadExt + Unpin>, len: usize) -> Option<Vec<u8>> {
let mut r = r?;
let mut buf = vec![0; len];
@ -53,53 +53,54 @@ impl UserData for Child {
Some(buf)
}
let me = me.deref_mut();
Ok(select! {
Some(r) = read(me.stdout.as_mut(), len) => (r, 0u8),
Some(r) = read(me.stderr.as_mut(), len) => (r, 1u8),
else => (vec![], 2u8)
})
});
methods.add_async_method_mut("read_line", |lua, me, ()| async move {
match read_line(me).await {
(Some(b), event) => (lua.create_string(b)?, event).into_lua_multi(lua),
(None, event) => (Value::Nil, event).into_lua_multi(lua),
methods.add_async_method_mut("read_line", |lua, mut me, ()| async move {
match read_line(&mut me).await {
(Some(b), event) => (lua.create_string(b)?, event).into_lua_multi(&lua),
(None, event) => (Value::Nil, event).into_lua_multi(&lua),
}
});
methods.add_async_method_mut("read_line_with", |lua, me, options: Table| async move {
methods.add_async_method_mut("read_line_with", |lua, mut me, options: Table| async move {
let timeout = Duration::from_millis(options.raw_get("timeout")?);
let Ok(result) = tokio::time::timeout(timeout, read_line(me)).await else {
return (Value::Nil, 3u8).into_lua_multi(lua);
let Ok(result) = tokio::time::timeout(timeout, read_line(&mut me)).await else {
return (Value::Nil, 3u8).into_lua_multi(&lua);
};
match result {
(Some(b), event) => (lua.create_string(b)?, event).into_lua_multi(lua),
(None, event) => (Value::Nil, event).into_lua_multi(lua),
(Some(b), event) => (lua.create_string(b)?, event).into_lua_multi(&lua),
(None, event) => (Value::Nil, event).into_lua_multi(&lua),
}
});
methods.add_async_method_mut("write_all", |lua, me, src: mlua::String| async move {
methods.add_async_method_mut("write_all", |lua, mut me, src: mlua::String| async move {
let Some(stdin) = &mut me.stdin else {
return Err("stdin is not piped".into_lua_err());
};
match stdin.write_all(src.as_bytes()).await {
Ok(()) => (true, Value::Nil).into_lua_multi(lua),
Err(e) => (false, e.raw_os_error()).into_lua_multi(lua),
match stdin.write_all(&src.as_bytes()).await {
Ok(()) => (true, Value::Nil).into_lua_multi(&lua),
Err(e) => (false, e.raw_os_error()).into_lua_multi(&lua),
}
});
methods.add_async_method_mut("flush", |lua, me, ()| async move {
methods.add_async_method_mut("flush", |lua, mut me, ()| async move {
let Some(stdin) = &mut me.stdin else {
return Err("stdin is not piped".into_lua_err());
};
match stdin.flush().await {
Ok(()) => (true, Value::Nil).into_lua_multi(lua),
Err(e) => (false, e.raw_os_error()).into_lua_multi(lua),
Ok(()) => (true, Value::Nil).into_lua_multi(&lua),
Err(e) => (false, e.raw_os_error()).into_lua_multi(&lua),
}
});
methods.add_async_method_mut("wait", |lua, me, ()| async move {
methods.add_async_method_mut("wait", |lua, mut me, ()| async move {
drop(me.stdin.take());
match me.inner.wait().await {
Ok(status) => (Status::new(status), Value::Nil).into_lua_multi(lua),
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
Ok(status) => (Status::new(status), Value::Nil).into_lua_multi(&lua),
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(&lua),
}
});
methods.add_async_function("wait_with_output", |lua, ud: AnyUserData| async move {
@ -126,9 +127,9 @@ impl UserData for Child {
match result {
Ok((status, stdout, stderr)) => {
(Output::new(std::process::Output { status, stdout, stderr }), Value::Nil)
.into_lua_multi(lua)
.into_lua_multi(&lua)
}
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(&lua),
}
});
methods.add_method_mut("start_kill", |lua, me, ()| match me.inner.start_kill() {

View file

@ -37,7 +37,7 @@ impl Command {
}
impl UserData for Command {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
#[inline]
fn make_stdio(v: Value) -> mlua::Result<Stdio> {
match v {
@ -66,28 +66,26 @@ impl UserData for Command {
}
methods.add_function_mut("arg", |_, (ud, arg): (AnyUserData, mlua::String)| {
ud.borrow_mut::<Self>()?.inner.arg(arg.to_string_lossy().as_ref());
ud.borrow_mut::<Self>()?.inner.arg(arg.to_string_lossy());
Ok(ud)
});
methods.add_function_mut("args", |_, (ud, args): (AnyUserData, Vec<mlua::String>)| {
{
let mut me = ud.borrow_mut::<Self>()?;
for arg in args {
me.inner.arg(arg.to_string_lossy().as_ref());
me.inner.arg(arg.to_string_lossy());
}
}
Ok(ud)
});
methods.add_function_mut("cwd", |_, (ud, dir): (AnyUserData, mlua::String)| {
ud.borrow_mut::<Self>()?.inner.current_dir(dir.to_str()?);
ud.borrow_mut::<Self>()?.inner.current_dir(dir.to_str()?.as_ref());
Ok(ud)
});
methods.add_function_mut(
"env",
|_, (ud, key, value): (AnyUserData, mlua::String, mlua::String)| {
ud.borrow_mut::<Self>()?
.inner
.env(key.to_string_lossy().as_ref(), value.to_string_lossy().as_ref());
ud.borrow_mut::<Self>()?.inner.env(key.to_string_lossy(), value.to_string_lossy());
Ok(ud)
},
);
@ -107,16 +105,16 @@ impl UserData for Command {
Ok(child) => (Child::new(child), Value::Nil).into_lua_multi(lua),
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
});
methods.add_async_method_mut("output", |lua, me, ()| async move {
methods.add_async_method_mut("output", |lua, mut me, ()| async move {
match me.inner.output().await {
Ok(output) => (Output::new(output), Value::Nil).into_lua_multi(lua),
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
Ok(output) => (Output::new(output), Value::Nil).into_lua_multi(&lua),
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(&lua),
}
});
methods.add_async_method_mut("status", |lua, me, ()| async move {
methods.add_async_method_mut("status", |lua, mut me, ()| async move {
match me.inner.status().await {
Ok(status) => (Status::new(status), Value::Nil).into_lua_multi(lua),
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua),
Ok(status) => (Status::new(status), Value::Nil).into_lua_multi(&lua),
Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(&lua),
}
});
}

View file

@ -11,7 +11,7 @@ impl Output {
}
impl UserData for Output {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("status", |_, me| Ok(Status::new(me.inner.status)));
fields.add_field_method_get("stdout", |lua, me| lua.create_string(&me.inner.stdout));
fields.add_field_method_get("stderr", |lua, me| lua.create_string(&me.inner.stderr));

View file

@ -9,7 +9,7 @@ impl Status {
}
impl UserData for Status {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("success", |_, me| Ok(me.inner.success()));
fields.add_field_method_get("code", |_, me| Ok(me.inner.code()));
}

View file

@ -1,8 +1,10 @@
#![allow(clippy::module_inception)]
use mlua::Lua;
yazi_macro::mod_flat!(pubsub);
pub(super) fn install(lua: &'static mlua::Lua) -> mlua::Result<()> {
pub(super) fn install(lua: &'static Lua) -> mlua::Result<()> {
Pubsub::install(lua)?;
Ok(())

View file

@ -12,7 +12,7 @@ impl Pubsub {
ps.raw_set(
"pub",
lua.create_function(|_, (kind, value): (mlua::String, Value)| {
yazi_dds::Pubsub::pub_(Body::from_lua(kind.to_str()?, value)?);
yazi_dds::Pubsub::pub_(Body::from_lua(&kind.to_str()?, value)?);
Ok(())
})?,
)?;
@ -20,7 +20,7 @@ impl Pubsub {
ps.raw_set(
"pub_to",
lua.create_function(|_, (receiver, kind, value): (u64, mlua::String, Value)| {
yazi_dds::Pubsub::pub_to(receiver, Body::from_lua(kind.to_str()?, value)?);
yazi_dds::Pubsub::pub_to(receiver, Body::from_lua(&kind.to_str()?, value)?);
Ok(())
})?,
)?;
@ -32,7 +32,7 @@ impl Pubsub {
let Some(cur) = rt.current() else {
return Err("`sub()` must be called in a sync plugin").into_lua_err();
};
if !yazi_dds::Pubsub::sub(cur, kind.to_str()?, f) {
if !yazi_dds::Pubsub::sub(cur, &kind.to_str()?, f) {
return Err("`sub()` called twice").into_lua_err();
}
Ok(())
@ -46,7 +46,7 @@ impl Pubsub {
let Some(cur) = rt.current() else {
return Err("`sub_remote()` must be called in a sync plugin").into_lua_err();
};
if !yazi_dds::Pubsub::sub_remote(cur, kind.to_str()?, f) {
if !yazi_dds::Pubsub::sub_remote(cur, &kind.to_str()?, f) {
return Err("`sub_remote()` called twice").into_lua_err();
}
Ok(())
@ -57,7 +57,7 @@ impl Pubsub {
"unsub",
lua.create_function(|_, kind: mlua::String| {
if let Some(cur) = lua.named_registry_value::<RtRef>("rt")?.current() {
Ok(yazi_dds::Pubsub::unsub(cur, kind.to_str()?))
Ok(yazi_dds::Pubsub::unsub(cur, &kind.to_str()?))
} else {
Err("`unsub()` must be called in a sync plugin").into_lua_err()
}
@ -68,7 +68,7 @@ impl Pubsub {
"unsub_remote",
lua.create_function(|_, kind: mlua::String| {
if let Some(cur) = lua.named_registry_value::<RtRef>("rt")?.current() {
Ok(yazi_dds::Pubsub::unsub_remote(cur, kind.to_str()?))
Ok(yazi_dds::Pubsub::unsub_remote(cur, &kind.to_str()?))
} else {
Err("`unsub_remote()` must be called in a sync plugin").into_lua_err()
}

View file

@ -5,7 +5,7 @@ use mlua::{Function, UserData};
#[derive(Default)]
pub struct Runtime {
frames: VecDeque<RuntimeFrame>,
blocks: HashMap<String, Vec<Function<'static>>>,
blocks: HashMap<String, Vec<Function>>,
}
struct RuntimeFrame {
@ -13,7 +13,7 @@ struct RuntimeFrame {
calls: usize,
}
pub type RtRef<'lua> = mlua::UserDataRefMut<'lua, Runtime>;
pub type RtRef = mlua::UserDataRefMut<Runtime>;
impl Runtime {
pub fn new(id: &str) -> Self {
@ -38,11 +38,11 @@ impl Runtime {
})
}
pub fn get_block(&self, id: &str, calls: usize) -> Option<Function<'static>> {
pub fn get_block(&self, id: &str, calls: usize) -> Option<Function> {
self.blocks.get(id).and_then(|v| v.get(calls)).cloned()
}
pub fn put_block(&mut self, f: Function<'static>) -> bool {
pub fn put_block(&mut self, f: Function) -> bool {
let Some(cur) = self.frames.back() else { return false };
if let Some(v) = self.blocks.get_mut(&cur.id) {
v.push(f);

View file

@ -1,8 +1,10 @@
#![allow(clippy::module_inception)]
use mlua::Lua;
yazi_macro::mod_flat!(url);
pub fn pour(lua: &mlua::Lua) -> mlua::Result<()> {
pub fn pour(lua: &Lua) -> mlua::Result<()> {
url::Url::register(lua)?;
url::Url::install(lua)?;

View file

@ -2,7 +2,7 @@ use mlua::{AnyUserData, ExternalError, Lua, MetaMethod, UserDataFields, UserData
use crate::bindings::Cast;
pub type UrlRef<'lua> = UserDataRef<'lua, yazi_shared::fs::Url>;
pub type UrlRef = UserDataRef<yazi_shared::fs::Url>;
pub struct Url;
@ -27,7 +27,7 @@ impl Url {
});
reg.add_method("join", |lua, me, other: Value| {
Self::cast(lua, match other {
Value::String(s) => me.join(s.to_str()?),
Value::String(s) => me.join(s.to_str()?.as_ref()),
Value::UserData(ud) => me.join(&*ud.borrow::<yazi_shared::fs::Url>()?),
_ => Err("must be a string or a Url".into_lua_err())?,
})
@ -37,21 +37,21 @@ impl Url {
});
reg.add_method("starts_with", |_, me, base: Value| {
Ok(match base {
Value::String(s) => me.starts_with(s.to_str()?),
Value::String(s) => me.starts_with(s.to_str()?.as_ref()),
Value::UserData(ud) => me.starts_with(&*ud.borrow::<yazi_shared::fs::Url>()?),
_ => Err("must be a string or a Url".into_lua_err())?,
})
});
reg.add_method("ends_with", |_, me, child: Value| {
Ok(match child {
Value::String(s) => me.ends_with(s.to_str()?),
Value::String(s) => me.ends_with(s.to_str()?.as_ref()),
Value::UserData(ud) => me.ends_with(&*ud.borrow::<yazi_shared::fs::Url>()?),
_ => Err("must be a string or a Url".into_lua_err())?,
})
});
reg.add_method("strip_prefix", |lua, me, base: Value| {
let path = match base {
Value::String(s) => me.strip_prefix(s.to_str()?),
Value::String(s) => me.strip_prefix(s.to_str()?.as_ref()),
Value::UserData(ud) => me.strip_prefix(&*ud.borrow::<yazi_shared::fs::Url>()?),
_ => Err("must be a string or a Url".into_lua_err())?,
};
@ -68,7 +68,7 @@ impl Url {
let mut out = Vec::with_capacity(me.len() + other.len());
out.extend_from_slice(me);
out.extend_from_slice(other);
out.extend_from_slice(&other);
lua.create_string(out)
});
})
@ -78,7 +78,7 @@ impl Url {
lua.globals().raw_set(
"Url",
lua.create_function(|lua, url: mlua::String| {
Self::cast(lua, yazi_shared::fs::Url::from(url.to_str()?))
Self::cast(lua, yazi_shared::fs::Url::from(url.to_str()?.as_ref()))
})?,
)
}

View file

@ -1,6 +1,6 @@
use std::collections::HashMap;
use mlua::{ExternalError, Lua, Table, TableExt, Value};
use mlua::{ExternalError, Lua, ObjectLike, Table, Value};
use tracing::error;
use yazi_config::LAYOUT;
use yazi_dds::Sendable;
@ -43,15 +43,15 @@ impl Utils {
let id = id.to_str()?;
let mut layout = LAYOUT.get();
match id {
"current" => layout.current = *c.raw_get::<_, crate::elements::Rect>("_area")?,
"preview" => layout.preview = *c.raw_get::<_, crate::elements::Rect>("_area")?,
"progress" => layout.progress = *c.raw_get::<_, crate::elements::Rect>("_area")?,
match id.as_ref() {
"current" => layout.current = *c.raw_get::<crate::elements::Rect>("_area")?,
"preview" => layout.preview = *c.raw_get::<crate::elements::Rect>("_area")?,
"progress" => layout.progress = *c.raw_get::<crate::elements::Rect>("_area")?,
_ => {}
}
LAYOUT.set(layout);
match c.call_method::<_, Table>("redraw", ()) {
match c.call_method::<Table>("redraw", ()) {
Err(e) => {
error!("Failed to `redraw()` the `{id}` component:\n{e}");
lua.create_table()

View file

@ -10,9 +10,9 @@ impl Utils {
"image_show",
lua.create_async_function(|lua, (url, rect): (UrlRef, Rect)| async move {
if let Ok(area) = ADAPTOR.image_show(&url, *rect).await {
Rect::from(area).into_lua(lua)
Rect::from(area).into_lua(&lua)
} else {
Value::Nil.into_lua(lua)
Value::Nil.into_lua(&lua)
}
})?,
)?;

View file

@ -15,12 +15,12 @@ impl Utils {
fn parse_keys(value: Value) -> mlua::Result<Vec<Key>> {
Ok(match value {
Value::String(s) => {
vec![Key::from_str(s.to_str()?).into_lua_err()?]
vec![Key::from_str(&s.to_str()?).into_lua_err()?]
}
Value::Table(t) => {
let mut v = Vec::with_capacity(10);
for s in t.sequence_values::<mlua::String>() {
v.push(Key::from_str(s?.to_str()?).into_lua_err()?);
v.push(Key::from_str(&s?.to_str()?).into_lua_err()?);
}
v
}
@ -35,7 +35,7 @@ impl Utils {
let (tx, mut rx) = mpsc::channel::<usize>(1);
let mut cands = Vec::with_capacity(30);
for (i, cand) in t.raw_get::<_, Table>("cands")?.sequence_values::<Table>().enumerate() {
for (i, cand) in t.raw_get::<Table>("cands")?.sequence_values::<Table>().enumerate() {
let cand = cand?;
cands.push(Chord {
on: Self::parse_keys(cand.raw_get("on")?)?,
@ -65,24 +65,24 @@ impl Utils {
title: t.raw_get("title")?,
value: t.raw_get("value").unwrap_or_default(),
cursor: None, // TODO
position: Position::try_from(t.raw_get::<_, Table>("position")?)?.into(),
position: Position::try_from(t.raw_get::<Table>("position")?)?.into(),
realtime,
completion: false,
highlight: false,
}));
if !realtime {
return InputRx::consume(rx).await.into_lua_multi(lua);
return InputRx::consume(rx).await.into_lua_multi(&lua);
}
let debounce = t.raw_get::<_, f64>("debounce").unwrap_or_default();
let debounce = t.raw_get::<f64>("debounce").unwrap_or_default();
if debounce < 0.0 {
Err("negative debounce duration".into_lua_err())
} else if debounce == 0.0 {
(InputRx::new(rx), Value::Nil).into_lua_multi(lua)
(InputRx::new(rx), Value::Nil).into_lua_multi(&lua)
} else {
(InputRx::new(Debounce::new(rx, Duration::from_secs_f64(debounce))), Value::Nil)
.into_lua_multi(lua)
.into_lua_multi(&lua)
}
})?,
)?;

View file

@ -16,7 +16,7 @@ pub struct PreviewLock {
pub data: Vec<Box<dyn Renderable + Send>>,
}
impl<'a> TryFrom<Table<'a>> for PreviewLock {
impl TryFrom<Table> for PreviewLock {
type Error = mlua::Error;
fn try_from(t: Table) -> Result<Self, Self::Error> {
@ -43,9 +43,9 @@ impl Utils {
let inner = match Highlighter::new(&lock.url).highlight(lock.skip, *area).await {
Ok(text) => text,
Err(e @ PeekError::Exceed(max)) => return (e.to_string(), max).into_lua_multi(lua),
Err(e @ PeekError::Exceed(max)) => return (e.to_string(), max).into_lua_multi(&lua),
Err(e @ PeekError::Unexpected(_)) => {
return (e.to_string(), Value::Nil).into_lua_multi(lua);
return (e.to_string(), Value::Nil).into_lua_multi(&lua);
}
};
@ -56,7 +56,7 @@ impl Utils {
})];
emit!(Call(Cmd::new("update_peeked").with_any("lock", lock), Layer::Manager));
(Value::Nil, Value::Nil).into_lua_multi(lua)
(Value::Nil, Value::Nil).into_lua_multi(&lua)
})?,
)?;

View file

@ -11,7 +11,7 @@ impl Utils {
pub(super) fn sync(lua: &'static Lua, ya: &Table) -> mlua::Result<()> {
ya.raw_set(
"sync",
lua.create_function(|lua, f: Function<'static>| {
lua.create_function(|lua, f: Function| {
let mut rt = lua.named_registry_value::<RtRef>("rt")?;
if !rt.put_block(f.clone()) {
return Err("`ya.sync()` must be called in a plugin").into_lua_err();
@ -20,7 +20,7 @@ impl Utils {
let cur = rt.current().unwrap().to_owned();
lua.create_function(move |lua, mut args: MultiValue| {
args.push_front(Value::Table(LOADER.try_load(lua, &cur)?));
f.call::<_, MultiValue>(args)
f.call::<MultiValue>(args)
})
})?,
)?;
@ -38,7 +38,7 @@ impl Utils {
lua.create_async_function(move |lua, args: MultiValue| async move {
if let Some(cur) = lua.named_registry_value::<RtRef>("rt")?.current() {
Sendable::list_to_values(lua, Self::retrieve(cur, block, args).await?)
Sendable::list_to_values(&lua, Self::retrieve(cur, block, args).await?)
} else {
Err("block spawned by `ya.sync()` must be called in a plugin").into_lua_err()
}
@ -49,7 +49,7 @@ impl Utils {
Ok(())
}
async fn retrieve(id: &str, calls: usize, args: MultiValue<'_>) -> mlua::Result<Vec<Data>> {
async fn retrieve(id: &str, calls: usize, args: MultiValue) -> mlua::Result<Vec<Data>> {
let args = Sendable::values_to_vec(args)?;
let (tx, rx) = oneshot::channel::<Vec<Data>>();
@ -60,7 +60,7 @@ impl Utils {
return Err("sync block not found".into_lua_err());
};
let args: Vec<_> = [Ok(Value::Table(plugin))]
let args = [Ok(Value::Table(plugin))]
.into_iter()
.chain(args.into_iter().map(|d| Sendable::data_to_value(lua, d)))
.collect::<mlua::Result<_>>()?;

View file

@ -26,13 +26,14 @@ impl Utils {
ya.raw_set(
"quote",
lua.create_function(|_, (s, unix): (mlua::String, Option<bool>)| {
lua.create_function(|lua, (s, unix): (mlua::String, Option<bool>)| {
let s = s.to_str()?;
let s = match unix {
Some(true) => yazi_shared::shell::escape_unix(s.to_str()?),
Some(false) => yazi_shared::shell::escape_windows(s.to_str()?),
None => yazi_shared::shell::escape_native(s.to_str()?),
Some(true) => yazi_shared::shell::escape_unix(s.as_ref()),
Some(false) => yazi_shared::shell::escape_windows(s.as_ref()),
None => yazi_shared::shell::escape_native(s.as_ref()),
};
Ok(s.into_owned())
lua.create_string(s.as_ref())
})?,
)?;

View file

@ -1,9 +1,11 @@
use mlua::Lua;
#[cfg(unix)]
pub(super) static HOSTNAME_CACHE: std::sync::OnceLock<Option<String>> = std::sync::OnceLock::new();
pub(super) struct Utils;
pub fn install(lua: &'static mlua::Lua) -> mlua::Result<()> {
pub fn install(lua: &'static Lua) -> mlua::Result<()> {
let ya = lua.create_table()?;
Utils::app(lua, &ya)?;
@ -22,7 +24,7 @@ pub fn install(lua: &'static mlua::Lua) -> mlua::Result<()> {
lua.globals().raw_set("ya", ya)
}
pub fn install_isolate(lua: &mlua::Lua) -> mlua::Result<()> {
pub fn install_isolate(lua: &Lua) -> mlua::Result<()> {
let ya = lua.create_table()?;
Utils::app(lua, &ya)?;

View file

@ -18,16 +18,16 @@ impl TryFrom<Cmd> for NotifyOpt {
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_any("option").ok_or(()) }
}
impl<'a> TryFrom<mlua::Table<'a>> for NotifyOpt {
impl TryFrom<mlua::Table> for NotifyOpt {
type Error = mlua::Error;
fn try_from(t: mlua::Table) -> Result<Self, Self::Error> {
let timeout = t.raw_get::<_, f64>("timeout")?;
let timeout = t.raw_get("timeout")?;
if timeout < 0.0 {
return Err("timeout must be non-negative".into_lua_err());
}
let level = if let Ok(s) = t.raw_get::<_, mlua::String>("level") {
let level = if let Ok(s) = t.raw_get::<mlua::String>("level") {
s.to_str()?.parse().into_lua_err()?
} else {
Default::default()

View file

@ -21,11 +21,6 @@ impl Deref for File {
fn deref(&self) -> &Self::Target { &self.cha }
}
impl AsRef<File> for File {
#[inline]
fn as_ref(&self) -> &File { self }
}
impl File {
#[inline]
pub async fn from(url: Url) -> Result<Self> {

View file

@ -11,6 +11,9 @@ impl<T> RoCell<T> {
#[inline]
pub const fn new() -> Self { Self(UnsafeCell::new(None)) }
#[inline]
pub const fn new_const(value: T) -> Self { Self(UnsafeCell::new(Some(value))) }
#[inline]
pub fn init(&self, value: T) {
debug_assert!(!self.initialized());