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

View file

@ -11,7 +11,7 @@ strip = true
[workspace.dependencies] [workspace.dependencies]
ansi-to-tui = "7.0.0" ansi-to-tui = "7.0.0"
anyhow = "1.0.92" anyhow = "1.0.93"
base64 = "0.22.1" base64 = "0.22.1"
bitflags = "2.6.0" bitflags = "2.6.0"
clap = { version = "4.5.20", features = [ "derive" ] } clap = { version = "4.5.20", features = [ "derive" ] }
@ -19,9 +19,9 @@ crossterm = { version = "0.28.1", features = [ "event-stream" ] }
dirs = "5.0.1" dirs = "5.0.1"
futures = "0.3.31" futures = "0.3.31"
globset = "0.4.15" globset = "0.4.15"
libc = "0.2.161" libc = "0.2.162"
md-5 = "0.10.6" 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" parking_lot = "0.12.3"
ratatui = { version = "0.29.0", features = [ "unstable-rendered-line-info" ] } ratatui = { version = "0.29.0", features = [ "unstable-rendered-line-info" ] }
regex = "1.11.1" regex = "1.11.1"
@ -29,7 +29,7 @@ scopeguard = "1.2.0"
serde = { version = "1.0.214", features = [ "derive" ] } serde = { version = "1.0.214", features = [ "derive" ] }
serde_json = "1.0.132" serde_json = "1.0.132"
shell-words = "1.1.0" 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-stream = "0.1.16"
tokio-util = "0.7.12" tokio-util = "0.7.12"
tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] } tracing = { version = "0.1.40", features = [ "max_level_debug", "release_max_level_warn" ] }

View file

@ -29,9 +29,9 @@ rustPlatform.buildRustPackage rec {
cargoLock = { cargoLock = {
lockFile = "${src}/Cargo.lock"; lockFile = "${src}/Cargo.lock";
# outputHashes = { outputHashes = {
# "notify-6.1.1" = "sha256-5Ft2yvRPi2EaErcGBkF/3Xv6K7ijFGbdjmSqI4go/h4="; "mlua-0.10.0" = "sha256-Xg6/jc+UP8tbJJ6x1sbAgt8ZHt051xEBBcjmikQqYlw=";
# }; };
}; };
env = { 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) } 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> { fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
match self { match self {
Self::Hi(b) => b.into_lua(lua), 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) } 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> { fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
BodyBulkIter { inner: self.changes.into_iter() }.into_lua(lua) BodyBulkIter { inner: self.changes.into_iter() }.into_lua(lua)
} }
@ -48,7 +48,7 @@ pub struct BodyBulkIter {
} }
impl UserData for 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_method(MetaMethod::Len, |_, me, ()| Ok(me.inner.len()));
methods.add_meta_function(MetaMethod::Pairs, |lua, me: AnyUserData| { 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) } fn from(value: BodyBye) -> Self { Self::Bye(value) }
} }
impl IntoLua<'_> for BodyBye { impl IntoLua for BodyBye {
fn into_lua(self, _: &Lua) -> mlua::Result<Value<'_>> { fn into_lua(self, _: &Lua) -> mlua::Result<Value> {
Err("BodyBye cannot be converted to Lua").into_lua_err() 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) } 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> { fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
if let Some(Cow::Owned(url)) = Some(self.url).filter(|_| !self.dummy) { if let Some(Cow::Owned(url)) = Some(self.url).filter(|_| !self.dummy) {
lua.create_table_from([ lua.create_table_from([

View file

@ -27,7 +27,7 @@ impl From<BodyCustom> for Body<'_> {
fn from(value: BodyCustom) -> Self { Self::Custom(value) } 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) } 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) } fn from(value: BodyDelete<'a>) -> Self { Self::Delete(value) }
} }
impl IntoLua<'_> for BodyDelete<'static> { impl IntoLua for BodyDelete<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value<'_>> { fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
let urls = lua.create_table_with_capacity(self.urls.len(), 0)?; let urls = lua.create_table_with_capacity(self.urls.len(), 0)?;
// In most cases, `self.urls` will be `Cow::Owned`, so // 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) } fn from(value: BodyHey) -> Self { Self::Hey(value) }
} }
impl IntoLua<'_> for BodyHey { impl IntoLua for BodyHey {
fn into_lua(self, _: &Lua) -> mlua::Result<Value<'_>> { fn into_lua(self, _: &Lua) -> mlua::Result<Value> {
Err("BodyHey cannot be converted to Lua").into_lua_err() 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) } fn from(value: BodyHi<'a>) -> Self { Self::Hi(value) }
} }
impl IntoLua<'_> for BodyHi<'_> { impl IntoLua for BodyHi<'_> {
fn into_lua(self, _: &Lua) -> mlua::Result<Value<'_>> { fn into_lua(self, _: &Lua) -> mlua::Result<Value> {
Err("BodyHi cannot be converted to Lua").into_lua_err() 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) } 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> { fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
if let Some(Cow::Owned(url)) = self.url { if let Some(Cow::Owned(url)) = self.url {
lua.create_table_from([ 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) } 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> { fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
lua.create_table_from([("items", self.items.into_owned())])?.into_lua(lua) lua.create_table_from([("items", self.items.into_owned())])?.into_lua(lua)
} }
@ -42,7 +42,7 @@ pub struct BodyMoveItem {
pub to: Url, pub to: Url,
} }
impl IntoLua<'_> for BodyMoveItem { impl IntoLua for BodyMoveItem {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> { fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
lua lua
.create_table_from([ .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) } 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> { fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
lua lua
.create_table_from([ .create_table_from([

View file

@ -17,7 +17,7 @@ impl<'a> From<BodyTab> for Body<'a> {
fn from(value: BodyTab) -> Self { Self::Tab(value) } 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> { fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
lua.create_table_from([("idx", self.idx)])?.into_lua(lua) 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) } fn from(value: BodyTrash<'a>) -> Self { Self::Trash(value) }
} }
impl IntoLua<'_> for BodyTrash<'static> { impl IntoLua for BodyTrash<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value<'_>> { fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
let urls = lua.create_table_with_capacity(self.urls.len(), 0)?; let urls = lua.create_table_with_capacity(self.urls.len(), 0)?;
// In most cases, `self.urls` will be `Cow::Owned`, so // 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) } fn from(value: BodyYank<'a>) -> Self { Self::Yank(value) }
} }
impl IntoLua<'_> for BodyYank<'static> { impl IntoLua for BodyYank<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value<'_>> { fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
if let Some(Cow::Owned(urls)) = Some(self.urls).filter(|_| !self.dummy) { if let Some(Cow::Owned(urls)) = Some(self.urls).filter(|_| !self.dummy) {
BodyYankIter { cut: self.cut, urls: urls.into_iter().collect() }.into_lua(lua) BodyYankIter { cut: self.cut, urls: urls.into_iter().collect() }.into_lua(lua)
} else { } else {
@ -49,11 +49,11 @@ pub struct BodyYankIter {
} }
impl UserData for 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)); 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::Len, |_, me, ()| Ok(me.urls.len()));
methods.add_meta_method(MetaMethod::Index, |lua, me, idx: usize| { 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}}; 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>>>>> = pub static LOCAL: RoCell<RwLock<HashMap<String, HashMap<String, Function>>>> = RoCell::new();
RoCell::new();
pub static REMOTE: RoCell<RwLock<HashMap<String, HashMap<String, Function<'static>>>>> = pub static REMOTE: RoCell<RwLock<HashMap<String, HashMap<String, Function>>>> = RoCell::new();
RoCell::new();
macro_rules! sub { macro_rules! sub {
($var:ident) => { ($var:ident) => {
|plugin: &str, kind: &str, f: Function<'static>| { |plugin: &str, kind: &str, f: Function| {
let mut var = $var.write(); let mut var = $var.write();
let Some(map) = var.get_mut(kind) else { let Some(map) = var.get_mut(kind) else {
var.insert(kind.to_owned(), HashMap::from_iter([(plugin.to_owned(), f)])); var.insert(kind.to_owned(), HashMap::from_iter([(plugin.to_owned(), f)]));
@ -51,11 +49,9 @@ macro_rules! unsub {
pub struct Pubsub; pub struct Pubsub;
impl Pubsub { impl Pubsub {
pub fn sub(plugin: &str, kind: &str, f: Function<'static>) -> bool { pub fn sub(plugin: &str, kind: &str, f: Function) -> bool { sub!(LOCAL)(plugin, kind, f) }
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() 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::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 { for v in data {
vec.push(Self::data_to_value(lua, v)?); 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>> { 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::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; return;
}; };
_ = Lives::scope(&self.cx, |_| { _ = Lives::scope(&self.cx, || {
let body = payload.body.into_lua(&LUA)?; let body = payload.body.into_lua(&LUA)?;
for f in map.values() { 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}"); error!("Failed to call `{kind}` handler: {e}");
} }
} }

View file

@ -1,5 +1,5 @@
use crossterm::event::{MouseEvent, MouseEventKind}; use crossterm::event::{MouseEvent, MouseEventKind};
use mlua::{Table, TableExt}; use mlua::{ObjectLike, Table};
use tracing::error; use tracing::error;
use yazi_config::MANAGER; use yazi_config::MANAGER;
use yazi_plugin::{LUA, bindings::Cast}; 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 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 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 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()) { if matches!(event.kind, MouseEventKind::Down(_) if MANAGER.mouse_events.draggable()) {
root.raw_set("_drag_start", evt.clone())?; root.raw_set("_drag_start", evt.clone())?;

View file

@ -1,6 +1,6 @@
use std::fmt::Display; use std::fmt::Display;
use mlua::TableExt; use mlua::ObjectLike;
use scopeguard::defer; use scopeguard::defer;
use tracing::warn; use tracing::warn;
use yazi_dds::Sendable; use yazi_dds::Sendable;
@ -62,7 +62,7 @@ impl App {
}; };
drop(loader); drop(loader);
_ = Lives::scope(&self.cx, |_| { _ = Lives::scope(&self.cx, || {
if let Some(cb) = opt.cb { if let Some(cb) = opt.cb {
cb(&LUA, plugin) cb(&LUA, plugin)
} else { } 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 Some(size) = self.term.as_ref().and_then(|t| t.size().ok()) else { return };
let mut layout = LAYOUT.get(); 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())?; let comps = Root::reflow((Position::ORIGIN, size).into())?;
for v in comps.sequence_values::<Value>() { for v in comps.sequence_values::<Value>() {
@ -33,10 +33,10 @@ impl App {
}; };
let id: mlua::String = t.get("_id")?; let id: mlua::String = t.get("_id")?;
match id.to_str()? { match id.to_str()?.as_ref() {
"current" => layout.current = *t.raw_get::<_, yazi_plugin::elements::Rect>("_area")?, "current" => layout.current = *t.raw_get::<yazi_plugin::elements::Rect>("_area")?,
"preview" => layout.preview = *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")?, "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 collision = COLLISION.swap(false, Ordering::Relaxed);
let frame = term let frame = term
.draw(|f| { .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() { if let Some(pos) = self.cx.cursor() {
f.set_cursor_position(pos); f.set_cursor_position(pos);
@ -48,7 +48,7 @@ impl App {
let frame = term let frame = term
.draw_partial(|f| { .draw_partial(|f| {
_ = Lives::scope(&self.cx, |_| { _ = Lives::scope(&self.cx, || {
f.render_widget(crate::tasks::Progress, f.area()); f.render_widget(crate::tasks::Progress, f.area());
f.render_widget(crate::notify::Notify::new(&self.cx), f.area()); f.render_widget(crate::notify::Notify::new(&self.cx), f.area());
Ok(()) Ok(())

View file

@ -1,8 +1,8 @@
use std::ops::Deref; use std::ops::Deref;
use mlua::{AnyUserData, Lua, UserDataFields}; use mlua::{AnyUserData, UserData, UserDataFields};
use super::SCOPE; use super::Lives;
pub(super) struct Config { pub(super) struct Config {
inner: *const yazi_core::tab::Config, inner: *const yazi_core::tab::Config,
@ -16,20 +16,20 @@ impl Deref for Config {
impl Config { impl Config {
#[inline] #[inline]
pub(super) fn make(inner: &yazi_core::tab::Config) -> mlua::Result<AnyUserData<'static>> { pub(super) fn make(inner: &yazi_core::tab::Config) -> mlua::Result<AnyUserData> {
SCOPE.create_any_userdata(Self { inner }) Lives::scoped_userdata(Self { inner })
} }
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| { impl UserData for Config {
reg.add_field_method_get("sort_by", |_, me| Ok(me.sort_by.to_string())); fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
reg.add_field_method_get("sort_sensitive", |_, me| Ok(me.sort_sensitive)); fields.add_field_method_get("sort_by", |_, me| Ok(me.sort_by.to_string()));
reg.add_field_method_get("sort_reverse", |_, me| Ok(me.sort_reverse)); fields.add_field_method_get("sort_sensitive", |_, me| Ok(me.sort_sensitive));
reg.add_field_method_get("sort_dir_first", |_, me| Ok(me.sort_dir_first)); fields.add_field_method_get("sort_reverse", |_, me| Ok(me.sort_reverse));
reg.add_field_method_get("sort_translit", |_, me| Ok(me.sort_translit)); 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));
reg.add_field_method_get("linemode", |_, me| Ok(me.linemode.to_owned()));
reg.add_field_method_get("show_hidden", |_, me| Ok(me.show_hidden)); 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 std::ops::Deref;
use mlua::{AnyUserData, IntoLua, Lua, UserDataFields, UserDataMethods}; use mlua::{AnyUserData, IntoLua, UserData, UserDataFields, UserDataMethods};
use yazi_config::THEME; use yazi_config::THEME;
use yazi_plugin::{bindings::Range, elements::Style}; use yazi_plugin::{bindings::Range, elements::Style};
use yazi_shared::MIME_DIR; use yazi_shared::MIME_DIR;
use super::{CtxRef, SCOPE}; use super::Lives;
use crate::Ctx;
pub(super) struct File { pub(super) struct File {
idx: usize, idx: usize,
@ -29,71 +30,86 @@ impl File {
idx: usize, idx: usize,
folder: &yazi_fs::Folder, folder: &yazi_fs::Folder,
tab: &yazi_core::tab::Tab, tab: &yazi_core::tab::Tab,
) -> mlua::Result<AnyUserData<'static>> { ) -> mlua::Result<AnyUserData> {
SCOPE.create_any_userdata(Self { idx, folder, tab }) Lives::scoped_userdata(Self { idx, folder, tab })
} }
pub(super) fn register(lua: &Lua) -> mlua::Result<()> { #[inline]
lua.register_userdata_type::<Self>(|reg| { fn folder(&self) -> &yazi_fs::Folder { unsafe { &*self.folder } }
yazi_plugin::file::File::register_with(reg);
reg.add_field_method_get("idx", |_, me| Ok(me.idx + 1)); #[inline]
reg.add_method("size", |_, me, ()| { fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } }
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))
});
reg.add_method("prefix", |lua, me, ()| {
if !me.folder().url.is_search() {
return Ok(None);
}
let mut p = me.url.strip_prefix(&me.folder().url).unwrap_or(&me.url).components(); impl UserData for File {
p.next_back(); fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
Some(lua.create_string(p.as_path().as_os_str().as_encoded_bytes())).transpose() yazi_plugin::impl_file_fields!(fields);
});
reg.add_method("style", |lua, me, ()| { fields.add_field_method_get("idx", |_, me| Ok(me.idx + 1));
let cx = lua.named_registry_value::<CtxRef>("cx")?; }
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) })
});
methods.add_method("mime", |lua, me, ()| {
lua
.named_registry_value::<AnyUserData>("cx")?
.borrow_scoped(|cx: &Ctx| cx.manager.mimetype.get_owned(&me.url))
});
methods.add_method("prefix", |lua, me, ()| {
if !me.folder().url.is_search() {
return Ok(None);
}
let mut p = me.url.strip_prefix(&me.folder().url).unwrap_or(&me.url).components();
p.next_back();
Some(lua.create_string(p.as_path().as_os_str().as_encoded_bytes())).transpose()
});
methods.add_method("style", |lua, me, ()| {
lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|cx: &Ctx| {
let mime = let mime =
if me.is_dir() { MIME_DIR } else { cx.manager.mimetype.get(&me.url).unwrap_or_default() }; 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, ()| { methods.add_method("is_hovered", |_, me, ()| Ok(me.idx == me.folder().cursor));
let cx = lua.named_registry_value::<CtxRef>("cx")?; methods.add_method("is_yanked", |lua, me, ()| {
Ok(if !cx.manager.yanked.contains(&me.url) { lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|cx: &Ctx| {
if !cx.manager.yanked.contains(&me.url) {
0u8 0u8
} else if cx.manager.yanked.cut { } else if cx.manager.yanked.cut {
2u8 2u8
} else { } else {
1u8 1u8
})
});
reg.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);
} }
})
});
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);
}
Ok(match &me.tab().mode { Ok(match &me.tab().mode {
Select(_, indices) if indices.contains(&me.idx) => 1u8, Select(_, indices) if indices.contains(&me.idx) => 1u8,
Unset(_, indices) if indices.contains(&me.idx) => 2u8, Unset(_, indices) if indices.contains(&me.idx) => 2u8,
_ => 0u8, _ => 0u8,
}) })
}); });
reg.add_method("is_selected", |_, me, ()| Ok(me.tab().selected.contains_key(&me.url))); methods.add_method("is_selected", |_, me, ()| Ok(me.tab().selected.contains_key(&me.url)));
reg.add_method("in_parent", |_, me, ()| { methods.add_method("in_parent", |_, me, ()| {
Ok(me.tab().parent.as_ref().is_some_and(|f| me.folder().url == f.url)) 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)); methods.add_method("in_current", |_, me, ()| Ok(me.folder().url == me.tab().current.url));
reg.add_method("in_preview", |_, me, ()| { methods.add_method("in_preview", |_, me, ()| {
Ok(me.tab().hovered().is_some_and(|f| f.url == me.folder().url)) Ok(me.tab().hovered().is_some_and(|f| f.url == me.folder().url))
}); });
reg.add_method("found", |lua, me, ()| { methods.add_method("found", |lua, me, ()| {
let cx = lua.named_registry_value::<CtxRef>("cx")?; lua.named_registry_value::<AnyUserData>("cx")?.borrow_scoped(|cx: &Ctx| {
let Some(finder) = &cx.manager.active().finder else { let Some(finder) = &cx.manager.active().finder else {
return Ok(None); return Ok(None);
}; };
@ -104,29 +120,20 @@ impl File {
Some(lua.create_sequence_from([idx.into_lua(lua)?, finder.matched().len().into_lua(lua)?])) Some(lua.create_sequence_from([idx.into_lua(lua)?, finder.matched().len().into_lua(lua)?]))
.transpose() .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 { let Some(finder) = &cx.manager.active().finder else {
return Ok(None); return None;
}; };
if me.folder().url != me.tab().current.url { 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 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 { pub(super) struct Files {
window: Range<usize>, window: Range<usize>,
@ -22,27 +22,8 @@ impl Files {
window: Range<usize>, window: Range<usize>,
folder: &yazi_fs::Folder, folder: &yazi_fs::Folder,
tab: &yazi_core::tab::Tab, tab: &yazi_core::tab::Tab,
) -> mlua::Result<AnyUserData<'static>> { ) -> mlua::Result<AnyUserData> {
SCOPE.create_any_userdata(Self { window, folder, tab }) Lives::scoped_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(())
} }
#[inline] #[inline]
@ -51,3 +32,22 @@ impl Files {
#[inline] #[inline]
fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } } 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 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 { pub(super) struct Filter {
inner: *const yazi_fs::Filter, inner: *const yazi_fs::Filter,
@ -16,13 +16,13 @@ impl Deref for Filter {
impl Filter { impl Filter {
#[inline] #[inline]
pub(super) fn make(inner: &yazi_fs::Filter) -> mlua::Result<AnyUserData<'static>> { pub(super) fn make(inner: &yazi_fs::Filter) -> mlua::Result<AnyUserData> {
SCOPE.create_any_userdata(Self { inner }) Lives::scoped_userdata(Self { inner })
} }
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| { impl UserData for Filter {
reg.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.to_string())); 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 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 { pub(super) struct Finder {
inner: *const yazi_core::tab::Finder, inner: *const yazi_core::tab::Finder,
@ -16,13 +16,13 @@ impl Deref for Finder {
impl Finder { impl Finder {
#[inline] #[inline]
pub(super) fn make(inner: &yazi_core::tab::Finder) -> mlua::Result<AnyUserData<'static>> { pub(super) fn make(inner: &yazi_core::tab::Finder) -> mlua::Result<AnyUserData> {
SCOPE.create_any_userdata(Self { inner }) Lives::scoped_userdata(Self { inner })
} }
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| { impl UserData for Finder {
reg.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.filter.to_string())); 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 std::ops::{Deref, Range};
use mlua::{AnyUserData, Lua, UserDataFields}; use mlua::{AnyUserData, Lua, UserData, UserDataFields};
use yazi_config::LAYOUT; use yazi_config::LAYOUT;
use yazi_plugin::{bindings::Cast, url::Url}; use yazi_plugin::{bindings::Cast, url::Url};
use super::{File, Files, SCOPE}; use super::{File, Files, Lives};
pub(super) struct Folder { pub(super) struct Folder {
window: Range<usize>, window: Range<usize>,
@ -24,7 +24,7 @@ impl Folder {
window: Option<Range<usize>>, window: Option<Range<usize>>,
inner: &yazi_fs::Folder, inner: &yazi_fs::Folder,
tab: &yazi_core::tab::Tab, tab: &yazi_core::tab::Tab,
) -> mlua::Result<AnyUserData<'static>> { ) -> mlua::Result<AnyUserData> {
let window = match window { let window = match window {
Some(w) => w, Some(w) => w,
None => { 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<()> { 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| { lua.register_userdata_type::<yazi_fs::FolderStage>(|reg| {
reg.add_field_method_get("is_loading", |_, me| Ok(*me == yazi_fs::FolderStage::Loading)); reg.add_field_method_get("is_loading", |_, me| Ok(*me == yazi_fs::FolderStage::Loading));
})?; })?;
@ -60,3 +47,18 @@ impl Folder {
#[inline] #[inline]
fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } } 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> { pub(super) struct Iter<I: Iterator<Item = T>, T> {
inner: I, 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> { impl<I: Iterator<Item = T> + 'static, T: 'static> Iter<I, T> {
#[inline] #[inline]
pub(super) fn make(inner: I) -> mlua::Result<AnyUserData<'static>> { pub(super) fn make(inner: I) -> mlua::Result<AnyUserData> {
SCOPE.create_any_userdata(Self { inner, count: 0 }) 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)) 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 mlua::{AnyUserData, UserData};
use scopeguard::defer;
use tracing::error; use tracing::error;
use yazi_plugin::LUA; use yazi_plugin::LUA;
use yazi_shared::RoCell; use yazi_shared::RoCell;
use crate::Ctx; 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; pub(crate) struct Lives;
impl Lives { impl Lives {
pub(crate) fn register() -> mlua::Result<()> { 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::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(()) Ok(())
} }
pub(crate) fn scope<'a, T>( pub(crate) fn scope<T>(cx: &Ctx, f: impl FnOnce() -> mlua::Result<T>) -> mlua::Result<T> {
cx: &'a Ctx,
f: impl FnOnce(&Scope<'a, 'a>) -> mlua::Result<T>,
) -> mlua::Result<T> {
let result = LUA.scope(|scope| { let result = LUA.scope(|scope| {
defer! { SCOPE.drop(); } scope.add_destructor(|| {
SCOPE.init(unsafe { for ud in TO_DESTROY.borrow_mut().drain(..) {
mem::transmute::<&mlua::Scope<'a, 'a>, &mlua::Scope<'static, 'static>>(scope) ud.destroy().expect("failed to destruct scoped userdata");
}
}); });
LUA.set_named_registry_value("cx", scope.create_any_userdata_ref(cx)?)?;
let globals = LUA.globals(); LUA.set_named_registry_value("cx", scope.create_any_userdata_ref(cx)?)?;
globals.raw_set( LUA.globals().raw_set(
"cx", "cx",
LUA.create_table_from([ LUA.create_table_from([
("active", super::Tab::make(cx.manager.active())?), ("active", super::Tab::make(cx.manager.active())?),
@ -53,7 +37,7 @@ impl Lives {
])?, ])?,
)?; )?;
f(scope) f()
}); });
if let Err(ref e) = result { if let Err(ref e) = result {
@ -61,4 +45,14 @@ impl Lives {
} }
result 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 config file files filter finder folder iter lives mode preview selected tab tabs
tasks yanked tasks yanked
); );
type CtxRef<'lua> = mlua::UserDataRef<'lua, crate::Ctx>;

View file

@ -1,8 +1,8 @@
use std::ops::Deref; 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 { pub(super) struct Mode {
inner: *const yazi_core::tab::Mode, inner: *const yazi_core::tab::Mode,
@ -16,17 +16,19 @@ impl Deref for Mode {
impl Mode { impl Mode {
#[inline] #[inline]
pub(super) fn make(inner: &yazi_core::tab::Mode) -> mlua::Result<AnyUserData<'static>> { pub(super) fn make(inner: &yazi_core::tab::Mode) -> mlua::Result<AnyUserData> {
SCOPE.create_any_userdata(Self { inner }) Lives::scoped_userdata(Self { inner })
} }
}
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| { impl UserData for Mode {
reg.add_field_method_get("is_select", |_, me| Ok(me.is_select())); fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
reg.add_field_method_get("is_unset", |_, me| Ok(me.is_unset())); fields.add_field_method_get("is_select", |_, me| Ok(me.is_select()));
reg.add_field_method_get("is_visual", |_, me| Ok(me.is_visual())); fields.add_field_method_get("is_unset", |_, me| Ok(me.is_unset()));
fields.add_field_method_get("is_visual", |_, me| Ok(me.is_visual()));
reg.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.to_string())); }
})
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 std::ops::Deref;
use mlua::{AnyUserData, Lua, UserDataFields}; use mlua::{AnyUserData, UserData, UserDataFields};
use yazi_config::LAYOUT; use yazi_config::LAYOUT;
use super::{Folder, SCOPE}; use super::{Folder, Lives};
pub(super) struct Preview { pub(super) struct Preview {
tab: *const yazi_core::tab::Tab, tab: *const yazi_core::tab::Tab,
@ -17,25 +17,25 @@ impl Deref for Preview {
impl Preview { impl Preview {
#[inline] #[inline]
pub(super) fn make(tab: &yazi_core::tab::Tab) -> mlua::Result<AnyUserData<'static>> { pub(super) fn make(tab: &yazi_core::tab::Tab) -> mlua::Result<AnyUserData> {
SCOPE.create_any_userdata(Self { tab }) 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| {
me.tab()
.hovered_folder()
.map(|f| {
let limit = LAYOUT.get().preview.height as usize;
Folder::make(Some(me.skip..f.files.len().min(me.skip + limit)), f, me.tab())
})
.transpose()
});
})
} }
#[inline] #[inline]
fn tab(&self) -> &yazi_core::tab::Tab { unsafe { &*self.tab } } 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| {
let limit = LAYOUT.get().preview.height as usize;
Folder::make(Some(me.skip..f.files.len().min(me.skip + limit)), f, me.tab())
})
.transpose()
});
}
}

View file

@ -1,9 +1,9 @@
use std::{collections::{HashMap, hash_map}, ops::Deref}; 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 yazi_plugin::{bindings::Cast, url::Url};
use super::{Iter, SCOPE}; use super::{Iter, Lives};
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub(super) struct Selected { pub(super) struct Selected {
@ -18,34 +18,30 @@ impl Deref for Selected {
impl Selected { impl Selected {
#[inline] #[inline]
pub(super) fn make( pub(super) fn make(inner: &HashMap<yazi_shared::fs::Url, u64>) -> mlua::Result<AnyUserData> {
inner: &HashMap<yazi_shared::fs::Url, u64>, Lives::scoped_userdata(Self { inner })
) -> 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::Len, |_, me, ()| Ok(me.len()));
reg.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() {
(next.0, Url::cast(lua, next.1.clone())?).into_lua_multi(lua)
} else {
().into_lua_multi(lua)
}
},
)?;
Ok((iter, Iter::make(me.inner().keys())))
});
})?;
Ok(())
} }
#[inline] #[inline]
fn inner(&self) -> &'static HashMap<yazi_shared::fs::Url, u64> { unsafe { &*self.inner } } fn inner(&self) -> &'static HashMap<yazi_shared::fs::Url, u64> { unsafe { &*self.inner } }
} }
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() {
(next.0, Url::cast(lua, next.1.clone())?).into_lua_multi(lua)
} else {
().into_lua_multi(lua)
}
},
)?;
Ok((iter, Iter::make(me.inner().keys())))
});
}
}

View file

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

View file

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

View file

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

View file

@ -1,9 +1,9 @@
use std::{collections::hash_set, ops::Deref}; 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 yazi_plugin::{bindings::Cast, url::Url};
use super::{Iter, SCOPE}; use super::{Iter, Lives};
pub(super) struct Yanked { pub(super) struct Yanked {
inner: *const yazi_core::manager::Yanked, inner: *const yazi_core::manager::Yanked,
@ -17,32 +17,34 @@ impl Deref for Yanked {
impl Yanked { impl Yanked {
#[inline] #[inline]
pub(super) fn make(inner: &yazi_core::manager::Yanked) -> mlua::Result<AnyUserData<'static>> { pub(super) fn make(inner: &yazi_core::manager::Yanked) -> mlua::Result<AnyUserData> {
SCOPE.create_any_userdata(Self { inner }) 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));
reg.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.len()));
reg.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() {
(next.0, Url::cast(lua, next.1.clone())?).into_lua_multi(lua)
} else {
().into_lua_multi(lua)
}
},
)?;
Ok((iter, Iter::make(me.inner().iter())))
});
})
} }
#[inline] #[inline]
fn inner(&self) -> &'static yazi_core::manager::Yanked { unsafe { &*self.inner } } fn inner(&self) -> &'static yazi_core::manager::Yanked { unsafe { &*self.inner } }
} }
impl UserData for Yanked {
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("is_cut", |_, me| Ok(me.cut));
}
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() {
(next.0, Url::cast(lua, next.1.clone())?).into_lua_multi(lua)
} else {
().into_lua_multi(lua)
}
},
)?;
Ok((iter, Iter::make(me.inner().iter())))
});
}
}

View file

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

View file

@ -1,3 +1,5 @@
use mlua::Lua;
pub trait Cast<T> { 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 { impl Cast<&'static yazi_shared::theme::Icon> for Icon {
fn cast<'lua>( fn cast(lua: &Lua, data: &'static yazi_shared::theme::Icon) -> mlua::Result<AnyUserData> {
lua: &'lua Lua,
data: &'static yazi_shared::theme::Icon,
) -> mlua::Result<AnyUserData<'lua>> {
lua.create_any_userdata(data) 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> { impl<T: StreamExt<Item = Result<String, InputError>> + 'static> UserData for InputRx<T> {
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
methods.add_async_method_mut("recv", |_, me, ()| async move { methods.add_async_method_mut("recv", |_, mut me, ()| async move {
let mut inner = unsafe { Pin::new_unchecked(&mut me.inner) }; let mut inner = unsafe { Pin::new_unchecked(&mut me.inner) };
Ok(inner.next().await.map(Self::parse).unwrap_or((None, 0))) 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 mlua::{UserData, prelude::LuaUserDataMethods};
use tokio::sync::SemaphorePermit; 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()> { pub struct Permit<F: FnOnce()> {
inner: Option<SemaphorePermit<'static>>, inner: Option<SemaphorePermit<'static>>,
@ -36,7 +36,7 @@ impl<F: FnOnce()> Drop for Permit<F> {
} }
impl<F: FnOnce()> UserData 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())); methods.add_method_mut("drop", |_, me, ()| Ok(me.dropping()));
} }
} }

View file

@ -1,6 +1,6 @@
use std::{ops::Deref, str::FromStr}; use std::{ops::Deref, str::FromStr};
use mlua::{ExternalResult, IntoLua}; use mlua::{ExternalResult, IntoLua, Lua};
pub struct Position(yazi_config::popup::Position); 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 } 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; 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}; use yazi_config::popup::{Offset, Origin, Position};
Ok(Self(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 { offset: Offset {
x: t.raw_get("x").unwrap_or_default(), x: t.raw_get("x").unwrap_or_default(),
y: t.raw_get("y").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 { impl IntoLua for Position {
fn into_lua(self, lua: &mlua::Lua) -> mlua::Result<mlua::Value> { fn into_lua(self, lua: &Lua) -> mlua::Result<mlua::Value> {
lua lua
.create_table_from([ .create_table_from([
(1.into_lua(lua)?, self.origin.to_string().into_lua(lua)?), (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>); 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) } 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 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) 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 { 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("rows", |_, me| Ok(me.rows));
fields.add_field_method_get("cols", |_, me| Ok(me.cols)); fields.add_field_method_get("cols", |_, me| Ok(me.cols));
fields.add_field_method_get("width", |_, me| Ok(me.width)); fields.add_field_method_get("width", |_, me| Ok(me.width));

View file

@ -1,8 +1,10 @@
#![allow(clippy::module_inception)] #![allow(clippy::module_inception)]
use mlua::Lua;
yazi_macro::mod_flat!(cha); 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::register(lua)?;
cha::Cha::install(lua)?; cha::Cha::install(lua)?;

View file

@ -35,7 +35,7 @@ impl Bar {
} }
impl UserData for 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_area_method!(methods);
crate::impl_style_method!(methods, style); crate::impl_style_method!(methods, style);

View file

@ -53,7 +53,7 @@ impl Border {
} }
impl UserData for 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_area_method!(methods);
crate::impl_style_method!(methods, style); crate::impl_style_method!(methods, style);

View file

@ -55,7 +55,7 @@ impl Renderable for Clear {
} }
impl UserData 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); crate::impl_area_method!(methods);
} }
} }

View file

@ -14,7 +14,7 @@ impl From<Constraint> for ratatui::layout::Constraint {
} }
impl UserData for 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; use ratatui::layout::Constraint as C;
methods.add_function("Min", |_, n: u16| Ok(Self(C::Min(n)))); methods.add_function("Min", |_, n: u16| Ok(Self(C::Min(n))));

View file

@ -21,7 +21,7 @@ impl Gauge {
} }
impl UserData for 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_area_method!(methods);
crate::impl_style_method!(methods, style); crate::impl_style_method!(methods, style);

View file

@ -25,7 +25,7 @@ impl Layout {
} }
impl UserData for 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)| { methods.add_function_mut("direction", |_, (ud, value): (AnyUserData, bool)| {
ud.borrow_mut::<Self>()?.direction = value; ud.borrow_mut::<Self>()?.direction = value;
Ok(ud) Ok(ud)

View file

@ -20,7 +20,8 @@ impl Line {
let new = lua.create_function(|_, (_, value): (Table, Value)| Line::try_from(value))?; let new = lua.create_function(|_, (_, value): (Table, Value)| Line::try_from(value))?;
let parse = lua.create_function(|_, code: mlua::String| { 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())); 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; 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 { Ok(Self(match value {
Value::Table(tb) => return Self::try_from(tb), 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) => { Value::UserData(ud) => {
if let Ok(Span(span)) = ud.take() { if let Ok(Span(span)) = ud.take() {
span.into() 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; type Error = mlua::Error;
fn try_from(tb: Table) -> Result<Self, Self::Error> { fn try_from(tb: Table) -> Result<Self, Self::Error> {
let mut spans = Vec::with_capacity(tb.raw_len()); let mut spans = Vec::with_capacity(tb.raw_len());
for v in tb.sequence_values() { for v in tb.sequence_values() {
match v? { 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) => { Value::UserData(ud) => {
if let Ok(Span(span)) = ud.take() { if let Ok(Span(span)) = ud.take() {
spans.push(span); spans.push(span);
@ -94,7 +95,7 @@ impl TryFrom<Table<'_>> for Line {
} }
impl UserData 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_method!(methods, 0.style);
crate::impl_style_shorthands!(methods, 0.style); crate::impl_style_shorthands!(methods, 0.style);

View file

@ -31,7 +31,7 @@ impl List {
} }
impl UserData for 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); crate::impl_area_method!(methods);
} }
} }

View file

@ -49,7 +49,7 @@ impl Padding {
} }
impl UserData for 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("left", |_, me| Ok(me.left));
fields.add_field_method_get("right", |_, me| Ok(me.right)); fields.add_field_method_get("right", |_, me| Ok(me.right));
fields.add_field_method_get("top", |_, me| Ok(me.top)); fields.add_field_method_get("top", |_, me| Ok(me.top));

View file

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

View file

@ -30,7 +30,7 @@ impl Position {
} }
impl UserData for 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("x", |_, me| Ok(me.x));
fields.add_field_method_get("y", |_, me| Ok(me.y)); fields.add_field_method_get("y", |_, me| Ok(me.y));
} }

View file

@ -43,7 +43,7 @@ impl Rect {
} }
impl UserData for 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("x", |_, me| Ok(me.x));
fields.add_field_method_get("y", |_, me| Ok(me.y)); fields.add_field_method_get("y", |_, me| Ok(me.y));
fields.add_field_method_get("w", |_, me| Ok(me.width)); 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())); 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| { methods.add_method("padding", |_, me, padding: Padding| {
let mut r = **me; let mut r = **me;
r.x = r.x.saturating_add(padding.left); 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; 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 { 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) => { Value::UserData(ud) => {
if let Ok(Span(span)) = ud.take() { if let Ok(Span(span)) = ud.take() {
span span
@ -31,7 +31,7 @@ impl TryFrom<Value<'_>> for Span {
} }
impl UserData 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_method!(methods, 0.style);
crate::impl_style_shorthands!(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; 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(); let mut style = ratatui::style::Style::default();
if let Ok(fg) = value.raw_get::<_, mlua::String>("fg") { if let Ok(fg) = value.raw_get::<mlua::String>("fg") {
style.fg = Some(Color::from_str(fg.to_str()?).into_lua_err()?.into()); style.fg = Some(Color::from_str(&fg.to_str()?).into_lua_err()?.into());
} }
if let Ok(bg) = value.raw_get::<_, mlua::String>("bg") { if let Ok(bg) = value.raw_get::<mlua::String>("bg") {
style.bg = Some(Color::from_str(bg.to_str()?).into_lua_err()?.into()); style.bg = Some(Color::from_str(&bg.to_str()?).into_lua_err()?.into());
} }
style.add_modifier = style.add_modifier =
ratatui::style::Modifier::from_bits_truncate(value.raw_get("modifier").unwrap_or_default()); 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; 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 { Ok(Self(match value {
Value::Nil => Default::default(), Value::Nil => Default::default(),
Value::Table(tb) => Self::try_from(tb)?.0, Value::Table(tb) => Self::try_from(tb)?.0,
@ -52,7 +52,7 @@ impl From<yazi_shared::theme::Style> for Style {
} }
impl UserData 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); crate::impl_style_shorthands!(methods, 0);
methods.add_function_mut("patch", |_, (ud, value): (AnyUserData, Value)| { methods.add_function_mut("patch", |_, (ud, value): (AnyUserData, Value)| {

View file

@ -36,7 +36,7 @@ impl Table {
} }
impl UserData for 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); crate::impl_area_method!(methods);
methods.add_function_mut("header", |_, (ud, row): (AnyUserData, TableRow)| { 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 { 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); crate::impl_style_method!(methods, style);
methods.add_function_mut("height", |_, (ud, value): (AnyUserData, u16)| { 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 new = lua.create_function(|_, (_, value): (Table, Value)| Text::try_from(value))?;
let parse = lua.create_function(|_, code: mlua::String| { 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([ 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; type Error = mlua::Error;
fn try_from(value: Value) -> mlua::Result<Self> { fn try_from(value: Value) -> mlua::Result<Self> {
let inner = match value { let inner = match value {
Value::Table(tb) => return Self::try_from(tb), 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) => { Value::UserData(ud) => {
if let Ok(Line(line)) = ud.take() { if let Ok(Line(line)) = ud.take() {
line.into() 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; 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()); let mut lines = Vec::with_capacity(tb.raw_len());
for v in tb.sequence_values() { for v in tb.sequence_values() {
match v? { 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) => { Value::UserData(ud) => {
if let Ok(Span(span)) = ud.take() { if let Ok(Span(span)) = ud.take() {
lines.push(span.into()); lines.push(span.into());
@ -116,7 +116,7 @@ impl From<Text> for ratatui::widgets::Paragraph<'static> {
} }
impl UserData for Text { 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_area_method!(methods);
crate::impl_style_method!(methods, inner.style); crate::impl_style_method!(methods, inner.style);
crate::impl_style_shorthands!(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 mlua::{AnyUserData, Lua, Table, UserDataRef};
use yazi_config::THEME;
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; pub struct File;
impl File { impl File {
#[inline] #[inline]
pub fn register(lua: &Lua) -> mlua::Result<()> { pub fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<yazi_shared::fs::File>(Self::register_with) lua.register_userdata_type::<yazi_shared::fs::File>(|reg| {
} impl_file_fields!(reg);
impl_file_methods!(reg);
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(),
}
});
} }
pub fn install(lua: &Lua) -> mlua::Result<()> { pub fn install(lua: &Lua) -> mlua::Result<()> {
@ -51,8 +20,8 @@ impl File {
"File", "File",
lua.create_function(|lua, t: Table| { lua.create_function(|lua, t: Table| {
Self::cast(lua, yazi_shared::fs::File { Self::cast(lua, yazi_shared::fs::File {
url: t.raw_get::<_, AnyUserData>("url")?.take()?, url: t.raw_get::<AnyUserData>("url")?.take()?,
cha: t.raw_get::<_, AnyUserData>("cha")?.take()?, cha: t.raw_get::<AnyUserData>("cha")?.take()?,
..Default::default() ..Default::default()
}) })
})?, })?,

View file

@ -1,8 +1,10 @@
#![allow(clippy::module_inception)] #![allow(clippy::module_inception)]
use mlua::Lua;
yazi_macro::mod_flat!(file); 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::register(lua)?;
file::File::install(lua)?; file::File::install(lua)?;

View file

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

View file

@ -1,6 +1,6 @@
use std::borrow::Cow; 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::{runtime::Handle, select};
use tokio_util::sync::CancellationToken; use tokio_util::sync::CancellationToken;
use tracing::error; use tracing::error;
@ -29,7 +29,11 @@ pub fn peek(
lua.set_hook( lua.set_hook(
HookTriggers::new().on_calls().on_returns().every_nth_instruction(2000), HookTriggers::new().on_calls().on_returns().every_nth_instruction(2000),
move |_, _| { 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 tokio::runtime::Handle;
use yazi_config::LAYOUT; use yazi_config::LAYOUT;

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
use std::sync::Arc; 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 super::LOADER;
use crate::RtRef; use crate::RtRef;
@ -12,7 +12,7 @@ impl Require {
lua.globals().raw_set( lua.globals().raw_set(
"require", "require",
lua.create_function(|lua, id: mlua::String| { 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()?; futures::executor::block_on(LOADER.ensure(s)).into_lua_err()?;
lua.named_registry_value::<RtRef>("rt")?.push(s); lua.named_registry_value::<RtRef>("rt")?.push(s);
@ -28,27 +28,27 @@ impl Require {
lua.globals().raw_set( lua.globals().raw_set(
"require", "require",
lua.create_async_function(|lua, id: mlua::String| async move { 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()?; LOADER.ensure(s).await.into_lua_err()?;
lua.named_registry_value::<RtRef>("rt")?.push(s); 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(); 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 id: Arc<str> = Arc::from(id);
let mt = lua.create_table_from([ let mt = lua.create_table_from([
( (
"__index", "__index",
lua.create_function(move |lua, (ts, key): (Table, mlua::String)| { 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(_) => { 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), v => Ok(v),
} }
@ -57,7 +57,7 @@ impl Require {
( (
"__newindex", "__newindex",
lua.create_function(move |_, (ts, key, value): (Table, mlua::String, Value)| { 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) Ok(ts)
} }
fn create_wrapper<'a>( fn create_wrapper(lua: &Lua, id: Arc<str>, f: &str, sync: bool) -> mlua::Result<Function> {
lua: &'a Lua,
id: Arc<str>,
f: &str,
sync: bool,
) -> mlua::Result<Function<'a>> {
let f: Arc<str> = Arc::from(f); let f: Arc<str> = Arc::from(f);
if sync { if sync {
lua.create_function(move |lua, args: MultiValue| { lua.create_function(move |lua, args: MultiValue| {
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); 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(); lua.named_registry_value::<RtRef>("rt")?.pop();
result result
}) })
@ -87,9 +82,9 @@ impl Require {
lua.create_async_function(move |lua, args: MultiValue| { lua.create_async_function(move |lua, args: MultiValue| {
let (id, f) = (id.clone(), f.clone()); let (id, f) = (id.clone(), f.clone());
async move { 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); 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(); lua.named_registry_value::<RtRef>("rt")?.pop();
result result
} }
@ -97,11 +92,11 @@ impl Require {
} }
} }
fn split_mod_and_args<'a>( fn split_mod_and_args(
lua: &'a Lua, lua: &Lua,
id: &str, id: &str,
mut args: MultiValue<'a>, mut args: MultiValue,
) -> mlua::Result<(Table<'a>, MultiValue<'a>)> { ) -> mlua::Result<(Table, MultiValue)> {
let Some(front) = args.pop_front() else { let Some(front) = args.pop_front() else {
return Ok((LOADER.try_load(lua, id)?, args)); return Ok((LOADER.try_load(lua, id)?, args));
}; };
@ -109,7 +104,7 @@ impl Require {
args.push_front(front); args.push_front(front);
return Ok((LOADER.try_load(lua, id)?, args)); 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())); args.push_front(Value::Table(mod_.clone()));
(mod_, args) (mod_, args)
} else { } 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 futures::future::try_join3;
use mlua::{AnyUserData, ExternalError, IntoLua, IntoLuaMulti, Table, UserData, Value}; use mlua::{AnyUserData, ExternalError, IntoLua, IntoLuaMulti, Table, UserData, Value};
@ -24,7 +24,7 @@ impl Child {
} }
impl UserData for 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] #[inline]
async fn read_line(me: &mut Child) -> (Option<Vec<u8>>, u8) { async fn read_line(me: &mut Child) -> (Option<Vec<u8>>, u8) {
async fn read(r: Option<impl AsyncBufReadExt + Unpin>) -> Option<Vec<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>> { async fn read(r: Option<impl AsyncBufReadExt + Unpin>, len: usize) -> Option<Vec<u8>> {
let mut r = r?; let mut r = r?;
let mut buf = vec![0; len]; let mut buf = vec![0; len];
@ -53,53 +53,54 @@ impl UserData for Child {
Some(buf) Some(buf)
} }
let me = me.deref_mut();
Ok(select! { Ok(select! {
Some(r) = read(me.stdout.as_mut(), len) => (r, 0u8), Some(r) = read(me.stdout.as_mut(), len) => (r, 0u8),
Some(r) = read(me.stderr.as_mut(), len) => (r, 1u8), Some(r) = read(me.stderr.as_mut(), len) => (r, 1u8),
else => (vec![], 2u8) else => (vec![], 2u8)
}) })
}); });
methods.add_async_method_mut("read_line", |lua, me, ()| async move { methods.add_async_method_mut("read_line", |lua, mut me, ()| async move {
match read_line(me).await { match read_line(&mut me).await {
(Some(b), event) => (lua.create_string(b)?, 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), (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 timeout = Duration::from_millis(options.raw_get("timeout")?);
let Ok(result) = tokio::time::timeout(timeout, read_line(me)).await else { let Ok(result) = tokio::time::timeout(timeout, read_line(&mut me)).await else {
return (Value::Nil, 3u8).into_lua_multi(lua); return (Value::Nil, 3u8).into_lua_multi(&lua);
}; };
match result { match result {
(Some(b), event) => (lua.create_string(b)?, 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), (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 { let Some(stdin) = &mut me.stdin else {
return Err("stdin is not piped".into_lua_err()); return Err("stdin is not piped".into_lua_err());
}; };
match stdin.write_all(src.as_bytes()).await { match stdin.write_all(&src.as_bytes()).await {
Ok(()) => (true, Value::Nil).into_lua_multi(lua), Ok(()) => (true, Value::Nil).into_lua_multi(&lua),
Err(e) => (false, e.raw_os_error()).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 { let Some(stdin) = &mut me.stdin else {
return Err("stdin is not piped".into_lua_err()); return Err("stdin is not piped".into_lua_err());
}; };
match stdin.flush().await { match stdin.flush().await {
Ok(()) => (true, Value::Nil).into_lua_multi(lua), Ok(()) => (true, Value::Nil).into_lua_multi(&lua),
Err(e) => (false, e.raw_os_error()).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()); drop(me.stdin.take());
match me.inner.wait().await { match me.inner.wait().await {
Ok(status) => (Status::new(status), Value::Nil).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), Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(&lua),
} }
}); });
methods.add_async_function("wait_with_output", |lua, ud: AnyUserData| async move { methods.add_async_function("wait_with_output", |lua, ud: AnyUserData| async move {
@ -126,9 +127,9 @@ impl UserData for Child {
match result { match result {
Ok((status, stdout, stderr)) => { Ok((status, stdout, stderr)) => {
(Output::new(std::process::Output { status, stdout, stderr }), Value::Nil) (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() { 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 { 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] #[inline]
fn make_stdio(v: Value) -> mlua::Result<Stdio> { fn make_stdio(v: Value) -> mlua::Result<Stdio> {
match v { match v {
@ -66,28 +66,26 @@ impl UserData for Command {
} }
methods.add_function_mut("arg", |_, (ud, arg): (AnyUserData, mlua::String)| { 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) Ok(ud)
}); });
methods.add_function_mut("args", |_, (ud, args): (AnyUserData, Vec<mlua::String>)| { methods.add_function_mut("args", |_, (ud, args): (AnyUserData, Vec<mlua::String>)| {
{ {
let mut me = ud.borrow_mut::<Self>()?; let mut me = ud.borrow_mut::<Self>()?;
for arg in args { for arg in args {
me.inner.arg(arg.to_string_lossy().as_ref()); me.inner.arg(arg.to_string_lossy());
} }
} }
Ok(ud) Ok(ud)
}); });
methods.add_function_mut("cwd", |_, (ud, dir): (AnyUserData, mlua::String)| { 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) Ok(ud)
}); });
methods.add_function_mut( methods.add_function_mut(
"env", "env",
|_, (ud, key, value): (AnyUserData, mlua::String, mlua::String)| { |_, (ud, key, value): (AnyUserData, mlua::String, mlua::String)| {
ud.borrow_mut::<Self>()? ud.borrow_mut::<Self>()?.inner.env(key.to_string_lossy(), value.to_string_lossy());
.inner
.env(key.to_string_lossy().as_ref(), value.to_string_lossy().as_ref());
Ok(ud) Ok(ud)
}, },
); );
@ -107,16 +105,16 @@ impl UserData for Command {
Ok(child) => (Child::new(child), Value::Nil).into_lua_multi(lua), Ok(child) => (Child::new(child), Value::Nil).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_async_method_mut("output", |lua, me, ()| async move { methods.add_async_method_mut("output", |lua, mut me, ()| async move {
match me.inner.output().await { match me.inner.output().await {
Ok(output) => (Output::new(output), Value::Nil).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), 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 { match me.inner.status().await {
Ok(status) => (Status::new(status), Value::Nil).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), Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(&lua),
} }
}); });
} }

View file

@ -11,7 +11,7 @@ impl Output {
} }
impl UserData for 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("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("stdout", |lua, me| lua.create_string(&me.inner.stdout));
fields.add_field_method_get("stderr", |lua, me| lua.create_string(&me.inner.stderr)); 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 { 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("success", |_, me| Ok(me.inner.success()));
fields.add_field_method_get("code", |_, me| Ok(me.inner.code())); fields.add_field_method_get("code", |_, me| Ok(me.inner.code()));
} }

View file

@ -1,8 +1,10 @@
#![allow(clippy::module_inception)] #![allow(clippy::module_inception)]
use mlua::Lua;
yazi_macro::mod_flat!(pubsub); 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)?; Pubsub::install(lua)?;
Ok(()) Ok(())

View file

@ -12,7 +12,7 @@ impl Pubsub {
ps.raw_set( ps.raw_set(
"pub", "pub",
lua.create_function(|_, (kind, value): (mlua::String, Value)| { 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(()) Ok(())
})?, })?,
)?; )?;
@ -20,7 +20,7 @@ impl Pubsub {
ps.raw_set( ps.raw_set(
"pub_to", "pub_to",
lua.create_function(|_, (receiver, kind, value): (u64, mlua::String, Value)| { 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(()) Ok(())
})?, })?,
)?; )?;
@ -32,7 +32,7 @@ impl Pubsub {
let Some(cur) = rt.current() else { let Some(cur) = rt.current() else {
return Err("`sub()` must be called in a sync plugin").into_lua_err(); 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(); return Err("`sub()` called twice").into_lua_err();
} }
Ok(()) Ok(())
@ -46,7 +46,7 @@ impl Pubsub {
let Some(cur) = rt.current() else { let Some(cur) = rt.current() else {
return Err("`sub_remote()` must be called in a sync plugin").into_lua_err(); 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(); return Err("`sub_remote()` called twice").into_lua_err();
} }
Ok(()) Ok(())
@ -57,7 +57,7 @@ impl Pubsub {
"unsub", "unsub",
lua.create_function(|_, kind: mlua::String| { lua.create_function(|_, kind: mlua::String| {
if let Some(cur) = lua.named_registry_value::<RtRef>("rt")?.current() { 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 { } else {
Err("`unsub()` must be called in a sync plugin").into_lua_err() Err("`unsub()` must be called in a sync plugin").into_lua_err()
} }
@ -68,7 +68,7 @@ impl Pubsub {
"unsub_remote", "unsub_remote",
lua.create_function(|_, kind: mlua::String| { lua.create_function(|_, kind: mlua::String| {
if let Some(cur) = lua.named_registry_value::<RtRef>("rt")?.current() { 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 { } else {
Err("`unsub_remote()` must be called in a sync plugin").into_lua_err() 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)] #[derive(Default)]
pub struct Runtime { pub struct Runtime {
frames: VecDeque<RuntimeFrame>, frames: VecDeque<RuntimeFrame>,
blocks: HashMap<String, Vec<Function<'static>>>, blocks: HashMap<String, Vec<Function>>,
} }
struct RuntimeFrame { struct RuntimeFrame {
@ -13,7 +13,7 @@ struct RuntimeFrame {
calls: usize, calls: usize,
} }
pub type RtRef<'lua> = mlua::UserDataRefMut<'lua, Runtime>; pub type RtRef = mlua::UserDataRefMut<Runtime>;
impl Runtime { impl Runtime {
pub fn new(id: &str) -> Self { 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() 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 }; let Some(cur) = self.frames.back() else { return false };
if let Some(v) = self.blocks.get_mut(&cur.id) { if let Some(v) = self.blocks.get_mut(&cur.id) {
v.push(f); v.push(f);

View file

@ -1,8 +1,10 @@
#![allow(clippy::module_inception)] #![allow(clippy::module_inception)]
use mlua::Lua;
yazi_macro::mod_flat!(url); 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::register(lua)?;
url::Url::install(lua)?; url::Url::install(lua)?;

View file

@ -2,7 +2,7 @@ use mlua::{AnyUserData, ExternalError, Lua, MetaMethod, UserDataFields, UserData
use crate::bindings::Cast; 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; pub struct Url;
@ -27,7 +27,7 @@ impl Url {
}); });
reg.add_method("join", |lua, me, other: Value| { reg.add_method("join", |lua, me, other: Value| {
Self::cast(lua, match other { 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>()?), Value::UserData(ud) => me.join(&*ud.borrow::<yazi_shared::fs::Url>()?),
_ => Err("must be a string or a Url".into_lua_err())?, _ => 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| { reg.add_method("starts_with", |_, me, base: Value| {
Ok(match base { 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>()?), Value::UserData(ud) => me.starts_with(&*ud.borrow::<yazi_shared::fs::Url>()?),
_ => Err("must be a string or a Url".into_lua_err())?, _ => Err("must be a string or a Url".into_lua_err())?,
}) })
}); });
reg.add_method("ends_with", |_, me, child: Value| { reg.add_method("ends_with", |_, me, child: Value| {
Ok(match child { 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>()?), Value::UserData(ud) => me.ends_with(&*ud.borrow::<yazi_shared::fs::Url>()?),
_ => Err("must be a string or a Url".into_lua_err())?, _ => Err("must be a string or a Url".into_lua_err())?,
}) })
}); });
reg.add_method("strip_prefix", |lua, me, base: Value| { reg.add_method("strip_prefix", |lua, me, base: Value| {
let path = match base { 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>()?), Value::UserData(ud) => me.strip_prefix(&*ud.borrow::<yazi_shared::fs::Url>()?),
_ => Err("must be a string or a Url".into_lua_err())?, _ => 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()); let mut out = Vec::with_capacity(me.len() + other.len());
out.extend_from_slice(me); out.extend_from_slice(me);
out.extend_from_slice(other); out.extend_from_slice(&other);
lua.create_string(out) lua.create_string(out)
}); });
}) })
@ -78,7 +78,7 @@ impl Url {
lua.globals().raw_set( lua.globals().raw_set(
"Url", "Url",
lua.create_function(|lua, url: mlua::String| { 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 std::collections::HashMap;
use mlua::{ExternalError, Lua, Table, TableExt, Value}; use mlua::{ExternalError, Lua, ObjectLike, Table, Value};
use tracing::error; use tracing::error;
use yazi_config::LAYOUT; use yazi_config::LAYOUT;
use yazi_dds::Sendable; use yazi_dds::Sendable;
@ -43,15 +43,15 @@ impl Utils {
let id = id.to_str()?; let id = id.to_str()?;
let mut layout = LAYOUT.get(); let mut layout = LAYOUT.get();
match id { match id.as_ref() {
"current" => layout.current = *c.raw_get::<_, crate::elements::Rect>("_area")?, "current" => layout.current = *c.raw_get::<crate::elements::Rect>("_area")?,
"preview" => layout.preview = *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")?, "progress" => layout.progress = *c.raw_get::<crate::elements::Rect>("_area")?,
_ => {} _ => {}
} }
LAYOUT.set(layout); LAYOUT.set(layout);
match c.call_method::<_, Table>("redraw", ()) { match c.call_method::<Table>("redraw", ()) {
Err(e) => { Err(e) => {
error!("Failed to `redraw()` the `{id}` component:\n{e}"); error!("Failed to `redraw()` the `{id}` component:\n{e}");
lua.create_table() lua.create_table()

View file

@ -10,9 +10,9 @@ impl Utils {
"image_show", "image_show",
lua.create_async_function(|lua, (url, rect): (UrlRef, Rect)| async move { lua.create_async_function(|lua, (url, rect): (UrlRef, Rect)| async move {
if let Ok(area) = ADAPTOR.image_show(&url, *rect).await { if let Ok(area) = ADAPTOR.image_show(&url, *rect).await {
Rect::from(area).into_lua(lua) Rect::from(area).into_lua(&lua)
} else { } 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>> { fn parse_keys(value: Value) -> mlua::Result<Vec<Key>> {
Ok(match value { Ok(match value {
Value::String(s) => { 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) => { Value::Table(t) => {
let mut v = Vec::with_capacity(10); let mut v = Vec::with_capacity(10);
for s in t.sequence_values::<mlua::String>() { 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 v
} }
@ -35,7 +35,7 @@ impl Utils {
let (tx, mut rx) = mpsc::channel::<usize>(1); let (tx, mut rx) = mpsc::channel::<usize>(1);
let mut cands = Vec::with_capacity(30); 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?; let cand = cand?;
cands.push(Chord { cands.push(Chord {
on: Self::parse_keys(cand.raw_get("on")?)?, on: Self::parse_keys(cand.raw_get("on")?)?,
@ -65,24 +65,24 @@ impl Utils {
title: t.raw_get("title")?, title: t.raw_get("title")?,
value: t.raw_get("value").unwrap_or_default(), value: t.raw_get("value").unwrap_or_default(),
cursor: None, // TODO cursor: None, // TODO
position: Position::try_from(t.raw_get::<_, Table>("position")?)?.into(), position: Position::try_from(t.raw_get::<Table>("position")?)?.into(),
realtime, realtime,
completion: false, completion: false,
highlight: false, highlight: false,
})); }));
if !realtime { 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 { if debounce < 0.0 {
Err("negative debounce duration".into_lua_err()) Err("negative debounce duration".into_lua_err())
} else if debounce == 0.0 { } else if debounce == 0.0 {
(InputRx::new(rx), Value::Nil).into_lua_multi(lua) (InputRx::new(rx), Value::Nil).into_lua_multi(&lua)
} else { } else {
(InputRx::new(Debounce::new(rx, Duration::from_secs_f64(debounce))), Value::Nil) (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>>, pub data: Vec<Box<dyn Renderable + Send>>,
} }
impl<'a> TryFrom<Table<'a>> for PreviewLock { impl TryFrom<Table> for PreviewLock {
type Error = mlua::Error; type Error = mlua::Error;
fn try_from(t: Table) -> Result<Self, Self::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 { let inner = match Highlighter::new(&lock.url).highlight(lock.skip, *area).await {
Ok(text) => text, 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(_)) => { 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)); 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<()> { pub(super) fn sync(lua: &'static Lua, ya: &Table) -> mlua::Result<()> {
ya.raw_set( ya.raw_set(
"sync", "sync",
lua.create_function(|lua, f: Function<'static>| { lua.create_function(|lua, f: Function| {
let mut rt = lua.named_registry_value::<RtRef>("rt")?; let mut rt = lua.named_registry_value::<RtRef>("rt")?;
if !rt.put_block(f.clone()) { if !rt.put_block(f.clone()) {
return Err("`ya.sync()` must be called in a plugin").into_lua_err(); 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(); let cur = rt.current().unwrap().to_owned();
lua.create_function(move |lua, mut args: MultiValue| { lua.create_function(move |lua, mut args: MultiValue| {
args.push_front(Value::Table(LOADER.try_load(lua, &cur)?)); 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 { lua.create_async_function(move |lua, args: MultiValue| async move {
if let Some(cur) = lua.named_registry_value::<RtRef>("rt")?.current() { 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 { } else {
Err("block spawned by `ya.sync()` must be called in a plugin").into_lua_err() Err("block spawned by `ya.sync()` must be called in a plugin").into_lua_err()
} }
@ -49,7 +49,7 @@ impl Utils {
Ok(()) 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 args = Sendable::values_to_vec(args)?;
let (tx, rx) = oneshot::channel::<Vec<Data>>(); let (tx, rx) = oneshot::channel::<Vec<Data>>();
@ -60,7 +60,7 @@ impl Utils {
return Err("sync block not found".into_lua_err()); return Err("sync block not found".into_lua_err());
}; };
let args: Vec<_> = [Ok(Value::Table(plugin))] let args = [Ok(Value::Table(plugin))]
.into_iter() .into_iter()
.chain(args.into_iter().map(|d| Sendable::data_to_value(lua, d))) .chain(args.into_iter().map(|d| Sendable::data_to_value(lua, d)))
.collect::<mlua::Result<_>>()?; .collect::<mlua::Result<_>>()?;

View file

@ -26,13 +26,14 @@ impl Utils {
ya.raw_set( ya.raw_set(
"quote", "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 { let s = match unix {
Some(true) => yazi_shared::shell::escape_unix(s.to_str()?), Some(true) => yazi_shared::shell::escape_unix(s.as_ref()),
Some(false) => yazi_shared::shell::escape_windows(s.to_str()?), Some(false) => yazi_shared::shell::escape_windows(s.as_ref()),
None => yazi_shared::shell::escape_native(s.to_str()?), 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)] #[cfg(unix)]
pub(super) static HOSTNAME_CACHE: std::sync::OnceLock<Option<String>> = std::sync::OnceLock::new(); pub(super) static HOSTNAME_CACHE: std::sync::OnceLock<Option<String>> = std::sync::OnceLock::new();
pub(super) struct Utils; 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()?; let ya = lua.create_table()?;
Utils::app(lua, &ya)?; Utils::app(lua, &ya)?;
@ -22,7 +24,7 @@ pub fn install(lua: &'static mlua::Lua) -> mlua::Result<()> {
lua.globals().raw_set("ya", ya) 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()?; let ya = lua.create_table()?;
Utils::app(lua, &ya)?; 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(()) } 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; type Error = mlua::Error;
fn try_from(t: mlua::Table) -> Result<Self, Self::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 { if timeout < 0.0 {
return Err("timeout must be non-negative".into_lua_err()); 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()? s.to_str()?.parse().into_lua_err()?
} else { } else {
Default::default() Default::default()

View file

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

View file

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