mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: new relay-notify-push DDS event to allow custom notification handlers (#3642)
This commit is contained in:
parent
dfdb235d74
commit
a015d4a7ef
33 changed files with 117 additions and 143 deletions
|
|
@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
### Added
|
||||
|
||||
- Allow using `ps.sub()` in `init.lua` directly without a plugin ([#3638])
|
||||
- New `relay-notify-push` DDS event to allow custom notification handlers ([#3642])
|
||||
- New `cx.which` API to access the which component state ([#3617])
|
||||
- New `ind-which-activate` DDS event to change the which component behavior ([#3608])
|
||||
|
||||
|
|
@ -1636,3 +1637,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
[#3633]: https://github.com/sxyazi/yazi/pull/3633
|
||||
[#3634]: https://github.com/sxyazi/yazi/pull/3634
|
||||
[#3638]: https://github.com/sxyazi/yazi/pull/3638
|
||||
[#3642]: https://github.com/sxyazi/yazi/pull/3642
|
||||
|
|
|
|||
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -5538,6 +5538,7 @@ version = "26.1.22"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"crossterm 0.29.0",
|
||||
"either",
|
||||
"futures",
|
||||
"hashbrown 0.16.1",
|
||||
"libc",
|
||||
|
|
@ -5765,6 +5766,7 @@ version = "26.1.22"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"crossterm 0.29.0",
|
||||
"either",
|
||||
"scopeguard",
|
||||
"tokio",
|
||||
"tracing",
|
||||
|
|
@ -5835,6 +5837,7 @@ dependencies = [
|
|||
"bitflags 2.10.0",
|
||||
"core-foundation-sys",
|
||||
"dirs",
|
||||
"either",
|
||||
"foldhash",
|
||||
"hashbrown 0.16.1",
|
||||
"libc",
|
||||
|
|
@ -6056,6 +6059,7 @@ version = "26.1.22"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"deadpool",
|
||||
"either",
|
||||
"futures",
|
||||
"hashbrown 0.16.1",
|
||||
"parking_lot",
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ core-foundation-sys = "0.8.7"
|
|||
crossterm = { version = "0.29.0", features = [ "event-stream" ] }
|
||||
dirs = "6.0.0"
|
||||
dyn-clone = "1.0.20"
|
||||
either = { version = "1.15.0" }
|
||||
foldhash = "0.2.0"
|
||||
futures = "0.3.31"
|
||||
globset = "0.4.18"
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ yazi-widgets = { path = "../yazi-widgets", version = "26.1.22" }
|
|||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
crossterm = { workspace = true }
|
||||
either = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use anyhow::Result;
|
|||
use mlua::IntoLua;
|
||||
use tracing::error;
|
||||
use yazi_actor::lives::Lives;
|
||||
use yazi_binding::runtime_mut;
|
||||
use yazi_binding::runtime_scope;
|
||||
use yazi_dds::{LOCAL, Payload, REMOTE};
|
||||
use yazi_macro::succ;
|
||||
use yazi_plugin::LUA;
|
||||
|
|
@ -31,11 +31,9 @@ impl Actor for AcceptPayload {
|
|||
succ!(Lives::scope(&cx.core, || {
|
||||
let body = payload.body.into_lua(&LUA)?;
|
||||
for (id, cb) in handlers {
|
||||
let blocking = runtime_mut!(LUA)?.critical_push(&id, true);
|
||||
if let Err(e) = cb.call::<()>(body.clone()) {
|
||||
if let Err(e) = runtime_scope!(LUA, &id, cb.call::<()>(body.clone())) {
|
||||
error!("Failed to run `{kind}` event handler in your `{id}` plugin: {e}");
|
||||
}
|
||||
runtime_mut!(LUA)?.critical_pop(blocking)?;
|
||||
}
|
||||
Ok(())
|
||||
})?);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use crossterm::event::MouseEventKind;
|
|||
use mlua::{ObjectLike, Table};
|
||||
use tracing::error;
|
||||
use yazi_actor::lives::Lives;
|
||||
use yazi_binding::runtime_scope;
|
||||
use yazi_config::YAZI;
|
||||
use yazi_macro::succ;
|
||||
use yazi_parser::app::MouseOpt;
|
||||
|
|
@ -20,11 +21,14 @@ impl Actor for Mouse {
|
|||
|
||||
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
|
||||
let event = yazi_binding::MouseEvent::from(opt.event);
|
||||
|
||||
let Some(size) = cx.term.as_ref().and_then(|t| t.size().ok()) else { succ!() };
|
||||
let area = yazi_binding::elements::Rect::from(size);
|
||||
|
||||
let result = Lives::scope(&cx.core, move || {
|
||||
let area = yazi_binding::elements::Rect::from(size);
|
||||
let root = LUA.globals().raw_get::<Table>("Root")?.call_method::<Table>("new", area)?;
|
||||
let root = runtime_scope!(LUA, "root", {
|
||||
LUA.globals().raw_get::<Table>("Root")?.call_method::<Table>("new", area)
|
||||
})?;
|
||||
|
||||
if matches!(event.kind, MouseEventKind::Down(_) if YAZI.mgr.mouse_events.get().draggable()) {
|
||||
root.raw_set("_drag_start", event)?;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::Result;
|
||||
use mlua::{ErrorContext, ExternalError, IntoLua, Value};
|
||||
use yazi_binding::runtime_mut;
|
||||
use yazi_binding::runtime_scope;
|
||||
use yazi_dds::{LOCAL, spark::{Spark, SparkKind}};
|
||||
use yazi_plugin::LUA;
|
||||
|
||||
|
|
@ -18,11 +18,7 @@ impl Preflight {
|
|||
Ok(Lives::scope(cx.core, || {
|
||||
let mut body = opt.1.into_lua(&LUA)?;
|
||||
for (id, cb) in handlers {
|
||||
let blocking = runtime_mut!(LUA)?.critical_push(&id, true);
|
||||
let result = cb.call::<Value>(&body);
|
||||
runtime_mut!(LUA)?.critical_pop(blocking)?;
|
||||
|
||||
match result {
|
||||
match runtime_scope!(LUA, &id, cb.call::<Value>(&body)) {
|
||||
Ok(Value::Nil) => {
|
||||
Err(format!("`{kind}` event cancelled by `{id}` plugin on preflight").into_lua_err())?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@ pub(super) static FILE_CACHE: RoCell<RefCell<HashMap<PtrCell<yazi_fs::File>, Any
|
|||
pub struct Lives;
|
||||
|
||||
impl Lives {
|
||||
pub fn scope<T>(core: &yazi_core::Core, f: impl FnOnce() -> mlua::Result<T>) -> mlua::Result<T> {
|
||||
pub fn scope<T, F>(core: &yazi_core::Core, f: F) -> mlua::Result<T>
|
||||
where
|
||||
F: FnOnce() -> mlua::Result<T>,
|
||||
{
|
||||
FILE_CACHE.init(Default::default());
|
||||
defer! { FILE_CACHE.drop(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ impl Actor for ToggleAll {
|
|||
const NAME: &str = "toggle_all";
|
||||
|
||||
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
|
||||
use yazi_shared::Either::*;
|
||||
use either::Either::*;
|
||||
let tab = cx.tab_mut();
|
||||
|
||||
let it = tab.current.files.iter().map(|f| &f.url);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use std::time::{Duration, Instant};
|
||||
use std::time::Instant;
|
||||
|
||||
use anyhow::Result;
|
||||
use yazi_core::notify::Message;
|
||||
use yazi_macro::succ;
|
||||
use yazi_dds::spark::SparkKind;
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_parser::notify::PushOpt;
|
||||
use yazi_proxy::NotifyProxy;
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_shared::{Source, data::Data};
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
|
|
@ -24,8 +24,15 @@ impl Actor for Push {
|
|||
|
||||
if cx.notify.messages.iter().all(|m| m != &msg) {
|
||||
cx.notify.messages.push(msg);
|
||||
NotifyProxy::tick(Duration::ZERO);
|
||||
act!(notify:tick, cx)?;
|
||||
}
|
||||
succ!();
|
||||
}
|
||||
|
||||
fn hook(cx: &Ctx, _: &Self::Options) -> Option<SparkKind> {
|
||||
match cx.source() {
|
||||
Source::Relay => Some(SparkKind::RelayNotifyPush),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use anyhow::Result;
|
|||
use ratatui::layout::Rect;
|
||||
use yazi_core::notify::Notify;
|
||||
use yazi_emulator::Dimension;
|
||||
use yazi_macro::succ;
|
||||
use yazi_macro::{render, render_partial, succ};
|
||||
use yazi_parser::notify::TickOpt;
|
||||
use yazi_proxy::NotifyProxy;
|
||||
use yazi_shared::data::Data;
|
||||
|
|
@ -52,13 +52,13 @@ impl Actor for Tick {
|
|||
} else if let Some(min) = timeouts.iter().min() {
|
||||
*min
|
||||
} else {
|
||||
succ!();
|
||||
succ!(render!());
|
||||
};
|
||||
|
||||
cx.notify.tick_handle = Some(tokio::spawn(async move {
|
||||
tokio::time::sleep(interval).await;
|
||||
NotifyProxy::tick(interval);
|
||||
}));
|
||||
succ!();
|
||||
succ!(render_partial!());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use yazi_shared::Either;
|
||||
|
||||
use crate::Adapter;
|
||||
|
||||
pub(super) struct Adapters(Vec<Adapter>);
|
||||
|
|
@ -17,12 +15,7 @@ impl DerefMut for Adapters {
|
|||
}
|
||||
|
||||
impl From<&yazi_emulator::Emulator> for Adapters {
|
||||
fn from(value: &yazi_emulator::Emulator) -> Self {
|
||||
match value.kind {
|
||||
Either::Left(b) => b.into(),
|
||||
Either::Right(u) => u.into(),
|
||||
}
|
||||
}
|
||||
fn from(value: &yazi_emulator::Emulator) -> Self { value.kind.either_into() }
|
||||
}
|
||||
|
||||
impl From<yazi_emulator::Brand> for Adapters {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ pub fn init() -> anyhow::Result<()> {
|
|||
|
||||
// Emulator detection
|
||||
let mut emulator = Emulator::detect().unwrap_or_default();
|
||||
TMUX.set(emulator.kind.is_left_and(|&b| b == Brand::Tmux));
|
||||
TMUX.set(emulator.kind.left() == Some(Brand::Tmux));
|
||||
|
||||
// Tmux support
|
||||
if TMUX.get() {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,19 @@ macro_rules! runtime_mut {
|
|||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! runtime_scope {
|
||||
($lua:ident, $id:expr, $block:expr) => {{
|
||||
let mut f = || {
|
||||
let blocking = $crate::runtime_mut!($lua)?.critical_push($id, true);
|
||||
let result = (|| $block)();
|
||||
$crate::runtime_mut!($lua)?.critical_pop(blocking)?;
|
||||
result
|
||||
};
|
||||
f()
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! deprecate {
|
||||
($lua:ident, $tt:tt) => {{
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ impl Actions {
|
|||
fn file1_output() -> String {
|
||||
use std::io::Write;
|
||||
|
||||
let p = env::temp_dir().join(format!("yazi-debug-{}", timestamp_us()));
|
||||
let p = env::temp_dir().join(format!(".yazi-debug-{}.tmp", timestamp_us()));
|
||||
std::fs::File::create_new(&p).map(|mut f| f.write_all(b"Hello, World!")).ok();
|
||||
|
||||
let cmd = env::var_os("YAZI_FILE_ONE").unwrap_or("file".into());
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ clap = { workspace = true }
|
|||
clap_complete = "4.5.65"
|
||||
clap_complete_fig = "4.5.2"
|
||||
clap_complete_nushell = "4.5.10"
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
vergen-gitcl = { version = "9.1.0", features = [ "build" ] }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::{borrow::Cow, ffi::OsString};
|
|||
|
||||
use anyhow::{Result, bail};
|
||||
use clap::{Parser, Subcommand};
|
||||
use yazi_shared::{Either, Id};
|
||||
use yazi_shared::Id;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "Ya", about, long_about = None)]
|
||||
|
|
@ -139,9 +139,16 @@ macro_rules! impl_emit_body {
|
|||
impl $name {
|
||||
#[allow(dead_code)]
|
||||
pub(super) fn body(self) -> Result<String> {
|
||||
let cmd: Vec<_> = [Either::Left(self.name)]
|
||||
#[derive(serde::Serialize)]
|
||||
#[serde(untagged)]
|
||||
enum Elem {
|
||||
Name(String),
|
||||
Arg(Vec<u8>),
|
||||
}
|
||||
|
||||
let cmd: Vec<_> = [Elem::Name(self.name)]
|
||||
.into_iter()
|
||||
.chain(self.args.into_iter().map(|s| Either::Right(s.into_encoded_bytes())))
|
||||
.chain(self.args.into_iter().map(|s| Elem::Arg(s.into_encoded_bytes())))
|
||||
.collect();
|
||||
Ok(serde_json::to_string(&cmd)?)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ pub enum SparkKind {
|
|||
KeyQuit,
|
||||
// which:activate
|
||||
IndWhichActivate,
|
||||
// notify:push
|
||||
RelayNotifyPush,
|
||||
}
|
||||
|
||||
impl AsRef<str> for SparkKind {
|
||||
|
|
@ -27,6 +29,8 @@ impl AsRef<str> for SparkKind {
|
|||
Self::KeyQuit => "key-quit",
|
||||
// which:activate
|
||||
Self::IndWhichActivate => "ind-which-activate",
|
||||
// notify:push
|
||||
Self::RelayNotifyPush => "relay-notify-push",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,6 +166,8 @@ impl<'a> Spark<'a> {
|
|||
KeyQuit => Self::Quit(<_>::from_lua(value, lua)?),
|
||||
// which:activate
|
||||
IndWhichActivate => Self::WhichActivate(<_>::from_lua(value, lua)?),
|
||||
// notify:push
|
||||
RelayNotifyPush => Self::NotifyPush(<_>::from_lua(value, lua)?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ yazi-tty = { path = "../yazi-tty", version = "26.1.22" }
|
|||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
crossterm = { workspace = true }
|
||||
either = { workspace = true }
|
||||
scopeguard = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ use std::{io::BufWriter, time::Duration};
|
|||
|
||||
use anyhow::Result;
|
||||
use crossterm::{cursor::{RestorePosition, SavePosition}, execute, style::Print, terminal::{disable_raw_mode, enable_raw_mode}};
|
||||
use either::Either;
|
||||
use scopeguard::defer;
|
||||
use tokio::time::sleep;
|
||||
use tracing::{debug, error, warn};
|
||||
use yazi_shared::{Either, RoCell};
|
||||
use yazi_shared::RoCell;
|
||||
use yazi_tty::{Handle, TTY};
|
||||
|
||||
use crate::{Brand, Dimension, Mux, TMUX, Unknown};
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ use anyhow::Result;
|
|||
use crossterm::{cursor::{MoveTo, SetCursorStyle, Show}, execute, queue, terminal::{BeginSynchronizedUpdate, EndSynchronizedUpdate}};
|
||||
use ratatui::{CompletedFrame, backend::{Backend, CrosstermBackend}, buffer::Buffer, layout::Position};
|
||||
use yazi_actor::{Ctx, lives::Lives};
|
||||
use yazi_binding::runtime_scope;
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_plugin::LUA;
|
||||
use yazi_shared::{data::Data, event::NEED_RENDER};
|
||||
use yazi_tty::TTY;
|
||||
use yazi_widgets::COLLISION;
|
||||
|
|
@ -26,7 +28,9 @@ impl App {
|
|||
let collision = COLLISION.swap(false, Ordering::Relaxed);
|
||||
let frame = term
|
||||
.draw(|f| {
|
||||
_ = Lives::scope(&self.core, || Ok(f.render_widget(Root::new(&self.core), f.area())));
|
||||
_ = Lives::scope(&self.core, || {
|
||||
runtime_scope!(LUA, "root", Ok(f.render_widget(Root::new(&self.core), f.area())))
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
|
|
@ -57,9 +61,11 @@ impl App {
|
|||
let frame = term
|
||||
.draw_partial(|f| {
|
||||
_ = Lives::scope(&self.core, || {
|
||||
f.render_widget(crate::tasks::Progress::new(&self.core), f.area());
|
||||
f.render_widget(crate::notify::Notify::new(&self.core), f.area());
|
||||
Ok(())
|
||||
runtime_scope!(LUA, "root", {
|
||||
f.render_widget(crate::tasks::Progress::new(&self.core), f.area());
|
||||
f.render_widget(crate::notify::Notify::new(&self.core), f.area());
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ anyhow = { workspace = true }
|
|||
arc-swap = "1.8.0"
|
||||
bitflags = { workspace = true }
|
||||
dirs = { workspace = true }
|
||||
either = { workspace = true }
|
||||
foldhash = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::{collections::VecDeque, future::poll_fn, io, mem, path::{Path, PathBuf}, pin::Pin, task::{Poll, ready}, time::{Duration, Instant}};
|
||||
|
||||
use either::Either;
|
||||
use tokio::task::JoinHandle;
|
||||
use yazi_shared::Either;
|
||||
|
||||
type Task = Either<PathBuf, std::fs::ReadDir>;
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ impl SizeCalculator {
|
|||
};
|
||||
}
|
||||
|
||||
let Some(next) = front.right_mut()?.next() else {
|
||||
let Some(next) = front.as_mut().right()?.next() else {
|
||||
pop_and_continue!();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -182,8 +182,8 @@ fn final_path(path: &Path) -> io::Result<PathBuf> {
|
|||
fn final_path(path: &Path) -> io::Result<PathBuf> {
|
||||
use std::{ffi::OsString, fs::File, os::windows::{ffi::OsStringExt, fs::OpenOptionsExt, io::AsRawHandle}};
|
||||
|
||||
use either::Either;
|
||||
use windows_sys::Win32::{Foundation::HANDLE, Storage::FileSystem::{FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT, GetFinalPathNameByHandleW, VOLUME_NAME_DOS}};
|
||||
use yazi_shared::Either;
|
||||
|
||||
let file = std::fs::OpenOptions::new()
|
||||
.access_mode(0)
|
||||
|
|
@ -214,7 +214,8 @@ fn final_path(path: &Path) -> io::Result<PathBuf> {
|
|||
match inner(&file, &mut [0u16; 512])? {
|
||||
Either::Left(path) => Ok(path),
|
||||
Either::Right(len) => inner(&file, &mut vec![0u16; len as usize])?
|
||||
.left_or_err(|| io::Error::new(io::ErrorKind::InvalidData, "path too long")),
|
||||
.left()
|
||||
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "path too long")),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::{str::FromStr, time::Duration};
|
|||
use anyhow::anyhow;
|
||||
use mlua::{FromLua, IntoLua, Lua, LuaSerdeExt, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::{DurationSeconds, serde_as};
|
||||
use serde_with::{DurationSecondsWithFrac, serde_as};
|
||||
use yazi_config::{Style, THEME};
|
||||
use yazi_shared::event::CmdCow;
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ pub struct PushOpt {
|
|||
pub title: String,
|
||||
pub content: String,
|
||||
pub level: PushLevel,
|
||||
#[serde_as(as = "DurationSeconds<f64>")] // FIXME
|
||||
#[serde_as(as = "DurationSecondsWithFrac<f64>")]
|
||||
pub timeout: Duration,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use anyhow::bail;
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use yazi_shared::event::CmdCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TickOpt {
|
||||
pub interval: Duration,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ impl Deref for Loader {
|
|||
impl Default for Loader {
|
||||
fn default() -> Self {
|
||||
let cache = HashMap::from_iter([
|
||||
// Plugins
|
||||
("archive".to_owned(), preset!("plugins/archive").into()),
|
||||
("code".to_owned(), preset!("plugins/code").into()),
|
||||
("dds".to_owned(), preset!("plugins/dds").into()),
|
||||
|
|
@ -51,6 +52,22 @@ impl Default for Loader {
|
|||
("vfs".to_owned(), preset!("plugins/vfs").into()),
|
||||
("video".to_owned(), preset!("plugins/video").into()),
|
||||
("zoxide".to_owned(), preset!("plugins/zoxide").into()),
|
||||
// Components
|
||||
("current".to_owned(), [][..].into()),
|
||||
("entity".to_owned(), [][..].into()),
|
||||
("header".to_owned(), [][..].into()),
|
||||
("linemode".to_owned(), [][..].into()),
|
||||
("marker".to_owned(), [][..].into()),
|
||||
("modal".to_owned(), [][..].into()),
|
||||
("parent".to_owned(), [][..].into()),
|
||||
("preview".to_owned(), [][..].into()),
|
||||
("progress".to_owned(), [][..].into()),
|
||||
("rail".to_owned(), [][..].into()),
|
||||
("root".to_owned(), [][..].into()),
|
||||
("status".to_owned(), [][..].into()),
|
||||
("tab".to_owned(), [][..].into()),
|
||||
("tabs".to_owned(), [][..].into()),
|
||||
("tasks".to_owned(), [][..].into()),
|
||||
]);
|
||||
Self { cache: RwLock::new(cache) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use anyhow::{Context, Result};
|
||||
use futures::executor::block_on;
|
||||
use mlua::Lua;
|
||||
use yazi_binding::{Runtime, runtime_mut};
|
||||
use yazi_binding::{Runtime, runtime_scope};
|
||||
use yazi_boot::BOOT;
|
||||
use yazi_macro::plugin_preset as preset;
|
||||
use yazi_shared::RoCell;
|
||||
|
|
@ -65,9 +65,7 @@ fn stage_2(lua: &'static Lua) -> mlua::Result<()> {
|
|||
lua.load(preset!("compat")).set_name("compat.lua").exec()?;
|
||||
|
||||
if let Ok(b) = std::fs::read(BOOT.config_dir.join("init.lua")) {
|
||||
let blocking = runtime_mut!(lua)?.critical_push("init", true);
|
||||
block_on(lua.load(b).set_name("init.lua").exec_async())?;
|
||||
runtime_mut!(lua)?.critical_pop(blocking)?;
|
||||
runtime_scope!(lua, "init", block_on(lua.load(b).set_name("init.lua").exec_async()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -1,89 +0,0 @@
|
|||
use serde::Serialize;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Either<L, R> {
|
||||
Left(L),
|
||||
Right(R),
|
||||
}
|
||||
|
||||
impl<L, R> Either<L, R> {
|
||||
pub fn left(&self) -> Option<&L> {
|
||||
match self {
|
||||
Self::Left(l) => Some(l),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn right(&self) -> Option<&R> {
|
||||
match self {
|
||||
Self::Right(r) => Some(r),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn left_mut(&mut self) -> Option<&mut L> {
|
||||
match self {
|
||||
Self::Left(l) => Some(l),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn right_mut(&mut self) -> Option<&mut R> {
|
||||
match self {
|
||||
Self::Right(r) => Some(r),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_left_and<F: FnOnce(&L) -> bool>(&self, f: F) -> bool {
|
||||
self.left().map(f).unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn is_right_and<F: FnOnce(&R) -> bool>(&self, f: F) -> bool {
|
||||
self.right().map(f).unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn into_left(self) -> Option<L> {
|
||||
match self {
|
||||
Self::Left(l) => Some(l),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_right(self) -> Option<R> {
|
||||
match self {
|
||||
Self::Right(r) => Some(r),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn left_or_err<E, F: FnOnce() -> E>(self, f: F) -> Result<L, E> {
|
||||
match self {
|
||||
Self::Left(l) => Ok(l),
|
||||
_ => Err(f()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn right_or_err<E, F: FnOnce() -> E>(self, f: F) -> Result<R, E> {
|
||||
match self {
|
||||
Self::Right(r) => Ok(r),
|
||||
_ => Err(f()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L, R> Serialize for Either<L, R>
|
||||
where
|
||||
L: Serialize,
|
||||
R: Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
match self {
|
||||
Self::Left(l) => l.serialize(serializer),
|
||||
Self::Right(r) => r.serialize(serializer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
yazi_macro::mod_pub!(data errors event loc path pool scheme shell strand translit url wtf8);
|
||||
|
||||
yazi_macro::mod_flat!(alias bytes chars completion_token condition debounce either env id layer localset natsort os predictor ro_cell source sync_cell terminal tests throttle time utf8);
|
||||
yazi_macro::mod_flat!(alias bytes chars completion_token condition debounce env id layer localset natsort os predictor ro_cell source sync_cell terminal tests throttle time utf8);
|
||||
|
||||
pub fn init() {
|
||||
LOCAL_SET.with(tokio::task::LocalSet::new);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ yazi-shared = { path = "../yazi-shared", version = "26.1.22" }
|
|||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
deadpool = { version = "0.12.3", default-features = false, features = [ "managed", "rt_tokio_1" ] }
|
||||
either = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use std::{collections::VecDeque, io, time::{Duration, Instant}};
|
||||
|
||||
use either::Either;
|
||||
use yazi_fs::provider::{DirReader, FileHolder};
|
||||
use yazi_shared::{Either, url::{AsUrl, UrlBuf}};
|
||||
use yazi_shared::url::{AsUrl, UrlBuf};
|
||||
|
||||
use super::ReadDir;
|
||||
|
||||
|
|
@ -66,7 +67,7 @@ impl SizeCalculator {
|
|||
};
|
||||
}
|
||||
|
||||
let Ok(Some(ent)) = front.right_mut()?.next().await else {
|
||||
let Ok(Some(ent)) = front.as_mut().right()?.next().await else {
|
||||
pop_and_continue!();
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue