mirror of
https://github.com/sxyazi/yazi.git
synced 2026-05-13 08:16:40 +00:00
feat: new cx.which API to access the which component state (#3617)
This commit is contained in:
parent
06c665a086
commit
592e70a1c9
31 changed files with 190 additions and 151 deletions
|
|
@ -14,7 +14,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
|
||||
### Added
|
||||
|
||||
- New `ind-which-show` DDS event to change the which component behavior ([#3608])
|
||||
- New `cx.which` API to access the which component state ([#3617])
|
||||
- New `ind-which-activate` DDS event to change the which component behavior ([#3608])
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
@ -1622,3 +1623,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
[#3594]: https://github.com/sxyazi/yazi/pull/3594
|
||||
[#3607]: https://github.com/sxyazi/yazi/pull/3607
|
||||
[#3608]: https://github.com/sxyazi/yazi/pull/3608
|
||||
[#3617]: https://github.com/sxyazi/yazi/pull/3617
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ impl Preflight {
|
|||
Ok(Lives::scope(cx.core, || {
|
||||
let mut body = opt.1.into_lua(&LUA)?;
|
||||
for (id, cb) in handlers {
|
||||
runtime_mut!(LUA)?.push(&id);
|
||||
let blocking = runtime_mut!(LUA)?.critical_push(&id, true);
|
||||
let result = cb.call::<Value>(&body);
|
||||
runtime_mut!(LUA)?.pop();
|
||||
runtime_mut!(LUA)?.critical_pop(blocking);
|
||||
|
||||
match result {
|
||||
Ok(Value::Nil) => {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, UserData, UserDataFields};
|
||||
use mlua::{AnyUserData, UserData, UserDataFields, Value};
|
||||
use yazi_binding::cached_field;
|
||||
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct Which {
|
||||
inner: PtrCell<yazi_core::which::Which>,
|
||||
|
||||
v_cands: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Which {
|
||||
|
|
@ -16,10 +19,18 @@ impl Deref for Which {
|
|||
|
||||
impl Which {
|
||||
pub(super) fn make(inner: &yazi_core::which::Which) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner: inner.into() })
|
||||
Lives::scoped_userdata(Self { inner: inner.into(), v_cands: None })
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Which {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {}
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("times", |_, me| Ok(me.inner.times));
|
||||
cached_field!(fields, cands, |lua, me| {
|
||||
lua.create_sequence_from(me.inner.cands.iter().cloned().map(yazi_binding::ChordCow))
|
||||
});
|
||||
|
||||
fields.add_field_method_get("active", |_, me| Ok(me.inner.active));
|
||||
fields.add_field_method_get("silent", |_, me| Ok(me.inner.silent));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,12 +87,7 @@ impl UpdateFiles {
|
|||
|
||||
fn update_hovered(cx: &mut Ctx, op: FilesOp) -> Result<Data> {
|
||||
let (id, url) = (cx.tab().id, op.cwd());
|
||||
let (_, folder) = cx
|
||||
.tab_mut()
|
||||
.history
|
||||
.raw_entry_mut()
|
||||
.from_key(url)
|
||||
.or_insert_with(|| (url.clone(), Folder::from(url)));
|
||||
let folder = cx.tab_mut().history.entry_ref(url).or_insert_with(|| Folder::from(url));
|
||||
|
||||
if folder.update_pub(id, op) {
|
||||
act!(mgr:peek, cx, true)?;
|
||||
|
|
@ -108,10 +103,8 @@ impl UpdateFiles {
|
|||
|
||||
tab
|
||||
.history
|
||||
.raw_entry_mut()
|
||||
.from_key(op.cwd())
|
||||
.or_insert_with(|| (op.cwd().clone(), Folder::from(op.cwd())))
|
||||
.1
|
||||
.entry_ref(op.cwd())
|
||||
.or_insert_with(|| Folder::from(op.cwd()))
|
||||
.update_pub(tab.id, op);
|
||||
|
||||
if leave {
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@ use anyhow::Result;
|
|||
use yazi_core::which::WhichSorter;
|
||||
use yazi_dds::spark::SparkKind;
|
||||
use yazi_macro::{render, succ};
|
||||
use yazi_parser::which::ShowOpt;
|
||||
use yazi_parser::which::ActivateOpt;
|
||||
use yazi_shared::{Source, data::Data};
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Show;
|
||||
pub struct Activate;
|
||||
|
||||
impl Actor for Show {
|
||||
type Options = ShowOpt;
|
||||
impl Actor for Activate {
|
||||
type Options = ActivateOpt;
|
||||
|
||||
const NAME: &str = "show";
|
||||
const NAME: &str = "activate";
|
||||
|
||||
fn act(cx: &mut Ctx, mut opt: Self::Options) -> Result<Data> {
|
||||
opt.cands.retain(|c| c.on.len() > opt.times);
|
||||
|
|
@ -26,14 +26,14 @@ impl Actor for Show {
|
|||
which.times = opt.times;
|
||||
which.cands = opt.cands;
|
||||
|
||||
which.visible = true;
|
||||
which.active = true;
|
||||
which.silent = opt.silent;
|
||||
succ!(render!());
|
||||
}
|
||||
|
||||
fn hook(cx: &Ctx, _opt: &Self::Options) -> Option<SparkKind> {
|
||||
match cx.source() {
|
||||
Source::Unknown => Some(SparkKind::IndWhichShow),
|
||||
Source::Unknown => Some(SparkKind::IndWhichActivate),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(callback show);
|
||||
yazi_macro::mod_flat!(activate callback);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use mlua::UserData;
|
||||
use yazi_codegen::FromLuaOwned;
|
||||
|
||||
#[derive(FromLuaOwned)]
|
||||
#[derive(Clone, FromLuaOwned)]
|
||||
pub struct ChordCow(pub yazi_config::keymap::ChordCow);
|
||||
|
||||
impl From<ChordCow> for yazi_config::keymap::ChordCow {
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@ impl UserData for Gauge {
|
|||
Ok(ud)
|
||||
});
|
||||
|
||||
methods.add_function_mut("gauge_style", |_, (ud, value): (AnyUserData, Value)| {
|
||||
ud.borrow_mut::<Self>()?.gauge_style = Style::try_from(value)?.0;
|
||||
methods.add_function_mut("gauge_style", |_, (ud, style): (AnyUserData, Style)| {
|
||||
ud.borrow_mut::<Self>()?.gauge_style = style.0;
|
||||
Ok(ud)
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,20 +127,20 @@ impl UserData for Table {
|
|||
Ok(ud)
|
||||
});
|
||||
|
||||
methods.add_function_mut("style", |_, (ud, value): (AnyUserData, Value)| {
|
||||
ud.borrow_mut::<Self>()?.style = Style::try_from(value)?.0;
|
||||
methods.add_function_mut("style", |_, (ud, style): (AnyUserData, Style)| {
|
||||
ud.borrow_mut::<Self>()?.style = style.0;
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function_mut("row_style", |_, (ud, value): (AnyUserData, Value)| {
|
||||
ud.borrow_mut::<Self>()?.row_highlight_style = Style::try_from(value)?.0;
|
||||
methods.add_function_mut("row_style", |_, (ud, style): (AnyUserData, Style)| {
|
||||
ud.borrow_mut::<Self>()?.row_highlight_style = style.0;
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function_mut("col_style", |_, (ud, value): (AnyUserData, Value)| {
|
||||
ud.borrow_mut::<Self>()?.column_highlight_style = Style::try_from(value)?.0;
|
||||
methods.add_function_mut("col_style", |_, (ud, style): (AnyUserData, Style)| {
|
||||
ud.borrow_mut::<Self>()?.column_highlight_style = style.0;
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function_mut("cell_style", |_, (ud, value): (AnyUserData, Value)| {
|
||||
ud.borrow_mut::<Self>()?.cell_highlight_style = Style::try_from(value)?.0;
|
||||
methods.add_function_mut("cell_style", |_, (ud, style): (AnyUserData, Style)| {
|
||||
ud.borrow_mut::<Self>()?.cell_highlight_style = style.0;
|
||||
Ok(ud)
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ macro_rules! impl_area_method {
|
|||
#[macro_export]
|
||||
macro_rules! impl_style_method {
|
||||
($methods:ident, $($field:tt).+) => {
|
||||
$methods.add_function_mut("style", |_, (ud, value): (mlua::AnyUserData, mlua::Value)| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+ = $crate::Style::try_from(value)?.0;
|
||||
$methods.add_function_mut("style", |_, (ud, style): (mlua::AnyUserData, $crate::Style)| {
|
||||
ud.borrow_mut::<Self>()?.$($field).+ = style.0;
|
||||
Ok(ud)
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::collections::VecDeque;
|
||||
use std::{collections::VecDeque, mem};
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use hashbrown::{HashMap, hash_map::EntryRef};
|
||||
use mlua::Function;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -12,8 +12,7 @@ pub struct Runtime {
|
|||
|
||||
#[derive(Debug)]
|
||||
struct RuntimeFrame {
|
||||
id: String,
|
||||
calls: usize,
|
||||
id: String,
|
||||
}
|
||||
|
||||
impl Runtime {
|
||||
|
|
@ -21,40 +20,45 @@ impl Runtime {
|
|||
|
||||
pub fn new_isolate(id: &str) -> Self {
|
||||
Self {
|
||||
frames: VecDeque::from([RuntimeFrame { id: id.to_owned(), calls: 0 }]),
|
||||
frames: VecDeque::from([RuntimeFrame { id: id.to_owned() }]),
|
||||
blocks: <_>::default(),
|
||||
blocking: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, id: &str) {
|
||||
self.frames.push_back(RuntimeFrame { id: id.to_owned(), calls: 0 });
|
||||
}
|
||||
pub fn push(&mut self, id: &str) { self.frames.push_back(RuntimeFrame { id: id.to_owned() }); }
|
||||
|
||||
pub fn pop(&mut self) { self.frames.pop_back(); }
|
||||
|
||||
pub fn critical_push(&mut self, id: &str, blocking: bool) -> bool {
|
||||
self.push(id);
|
||||
mem::replace(&mut self.blocking, blocking)
|
||||
}
|
||||
|
||||
pub fn critical_pop(&mut self, blocking: bool) {
|
||||
self.pop();
|
||||
self.blocking = blocking;
|
||||
}
|
||||
|
||||
pub fn current(&self) -> Option<&str> { self.frames.back().map(|f| f.id.as_str()) }
|
||||
|
||||
pub fn current_owned(&self) -> Option<String> { self.current().map(ToOwned::to_owned) }
|
||||
|
||||
pub fn next_block(&mut self) -> Option<usize> {
|
||||
self.frames.back_mut().map(|f| {
|
||||
f.calls += 1;
|
||||
f.calls - 1
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_block(&self, id: &str, calls: usize) -> Option<Function> {
|
||||
self.blocks.get(id).and_then(|v| v.get(calls)).cloned()
|
||||
}
|
||||
|
||||
pub fn put_block(&mut self, f: &Function) -> bool {
|
||||
let Some(cur) = self.frames.back() else { return false };
|
||||
if let Some(v) = self.blocks.get_mut(&cur.id) {
|
||||
v.push(f.clone());
|
||||
} else {
|
||||
self.blocks.insert(cur.id.clone(), vec![f.clone()]);
|
||||
}
|
||||
true
|
||||
pub fn put_block(&mut self, f: &Function) -> Option<usize> {
|
||||
let Some(cur) = self.frames.back() else { return None };
|
||||
Some(match self.blocks.entry_ref(&cur.id) {
|
||||
EntryRef::Occupied(mut oe) => {
|
||||
oe.get_mut().push(f.clone());
|
||||
oe.get().len() - 1
|
||||
}
|
||||
EntryRef::Vacant(ve) => {
|
||||
ve.insert(vec![f.clone()]);
|
||||
0
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{AnyUserData, ExternalError, IntoLua, Lua, LuaSerdeExt, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||
use mlua::{AnyUserData, ExternalError, FromLua, IntoLua, Lua, LuaSerdeExt, MetaMethod, Table, UserData, UserDataMethods, Value};
|
||||
|
||||
use crate::SER_OPT;
|
||||
|
||||
|
|
@ -7,7 +7,7 @@ pub struct Style(pub ratatui::style::Style);
|
|||
|
||||
impl Style {
|
||||
pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||
let new = lua.create_function(|_, (_, value): (Table, Value)| Self::try_from(value))?;
|
||||
let new = lua.create_function(|_, (_, style): (Table, Self)| Ok(style))?;
|
||||
|
||||
let style = lua.create_table()?;
|
||||
style.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?))?;
|
||||
|
|
@ -16,10 +16,12 @@ impl Style {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Value> for Style {
|
||||
type Error = mlua::Error;
|
||||
impl From<yazi_config::Style> for Style {
|
||||
fn from(value: yazi_config::Style) -> Self { Self(value.into()) }
|
||||
}
|
||||
|
||||
fn try_from(value: Value) -> Result<Self, Self::Error> {
|
||||
impl FromLua for Style {
|
||||
fn from_lua(value: Value, _: &Lua) -> mlua::Result<Self> {
|
||||
Ok(Self(match value {
|
||||
Value::Nil => Default::default(),
|
||||
Value::UserData(ud) => ud.borrow::<Self>()?.0,
|
||||
|
|
@ -28,10 +30,6 @@ impl TryFrom<Value> for Style {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<yazi_config::Style> for Style {
|
||||
fn from(value: yazi_config::Style) -> Self { Self(value.into()) }
|
||||
}
|
||||
|
||||
impl UserData for Style {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
crate::impl_style_shorthands!(methods, 0);
|
||||
|
|
@ -39,11 +37,9 @@ impl UserData for Style {
|
|||
methods
|
||||
.add_method("raw", |lua, me, ()| lua.to_value_with(&yazi_config::Style::from(me.0), SER_OPT));
|
||||
|
||||
methods.add_function_mut("patch", |_, (ud, value): (AnyUserData, Value)| {
|
||||
{
|
||||
let mut me = ud.borrow_mut::<Self>()?;
|
||||
me.0 = me.0.patch(Self::try_from(value)?.0);
|
||||
}
|
||||
methods.add_function_mut("patch", |_, (ud, style): (AnyUserData, Self)| {
|
||||
let mut me = ud.borrow_mut::<Self>()?;
|
||||
me.0 = me.0.patch(style.0);
|
||||
Ok(ud)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ impl Core {
|
|||
}
|
||||
|
||||
pub fn layer(&self) -> Layer {
|
||||
if self.which.visible {
|
||||
if self.which.active {
|
||||
Layer::Which
|
||||
} else if self.cmp.visible {
|
||||
Layer::Cmp
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ pub struct Which {
|
|||
pub times: usize,
|
||||
pub cands: Vec<ChordCow>,
|
||||
|
||||
// Visibility
|
||||
pub visible: bool,
|
||||
pub silent: bool,
|
||||
// Active state
|
||||
pub active: bool,
|
||||
pub silent: bool,
|
||||
}
|
||||
|
||||
impl Which {
|
||||
|
|
@ -33,7 +33,7 @@ impl Which {
|
|||
self.times = 0;
|
||||
self.cands.clear();
|
||||
|
||||
self.visible = false;
|
||||
self.active = false;
|
||||
self.silent = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ impl Sendable {
|
|||
Some(t) if t == TypeId::of::<yazi_parser::mgr::UpdateYankedIter>() => {
|
||||
Data::Any(Box::new(ud.take::<yazi_parser::mgr::UpdateYankedIter>()?.into_opt(lua)?))
|
||||
}
|
||||
Some(t) if t == TypeId::of::<yazi_binding::ChordCow>() => {
|
||||
Data::Any(Box::new(ud.take::<yazi_binding::ChordCow>()?))
|
||||
}
|
||||
_ => Err(format!("unsupported userdata included: {ud:?}").into_lua_err())?,
|
||||
},
|
||||
Value::Error(_) => Err("error is not supported".into_lua_err())?,
|
||||
|
|
@ -98,6 +101,7 @@ impl Sendable {
|
|||
|
||||
try_cast!(|v: yazi_fs::FilesOp| lua.create_any_userdata(v));
|
||||
try_cast!(|v: yazi_parser::mgr::UpdateYankedOpt| v.into_lua(lua));
|
||||
try_cast!(|v: yazi_binding::ChordCow| v.into_lua(lua));
|
||||
Err("unsupported DataAny included".into_lua_err())?
|
||||
}
|
||||
data => Self::data_to_value_ref(lua, &data)?,
|
||||
|
|
@ -130,14 +134,19 @@ impl Sendable {
|
|||
Data::Url(u) => yazi_binding::Url::new(u).into_lua(lua)?,
|
||||
Data::Path(u) => yazi_binding::Path::new(u).into_lua(lua)?,
|
||||
Data::Bytes(b) => Value::String(lua.create_string(b)?),
|
||||
Data::Any(a) => {
|
||||
if let Some(t) = a.as_any().downcast_ref::<yazi_fs::FilesOp>() {
|
||||
lua.create_any_userdata(t.clone())?.into_lua(lua)?
|
||||
} else if let Some(t) = a.as_any().downcast_ref::<yazi_parser::mgr::UpdateYankedOpt>() {
|
||||
t.clone().into_lua(lua)?
|
||||
} else {
|
||||
Err("unsupported DataAny included".into_lua_err())?
|
||||
Data::Any(b) => {
|
||||
macro_rules! try_cast {
|
||||
($f:expr) => {
|
||||
if let Some(v) = b.as_any().downcast_ref() {
|
||||
return $f(Clone::clone(v))?.into_lua(lua);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
try_cast!(|v: yazi_fs::FilesOp| lua.create_any_userdata(v));
|
||||
try_cast!(|v: yazi_parser::mgr::UpdateYankedOpt| v.into_lua(lua));
|
||||
try_cast!(|v: yazi_binding::ChordCow| v.into_lua(lua));
|
||||
Err("unsupported DataAny included".into_lua_err())?
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ pub enum SparkKind {
|
|||
RelayStash,
|
||||
// quit
|
||||
KeyQuit,
|
||||
// which:show
|
||||
IndWhichShow,
|
||||
// which:activate
|
||||
IndWhichActivate,
|
||||
}
|
||||
|
||||
impl AsRef<str> for SparkKind {
|
||||
|
|
@ -25,8 +25,8 @@ impl AsRef<str> for SparkKind {
|
|||
Self::RelayStash => "relay-stash",
|
||||
// quit
|
||||
Self::KeyQuit => "key-quit",
|
||||
// which:show
|
||||
Self::IndWhichShow => "ind-which-show",
|
||||
// which:activate
|
||||
Self::IndWhichActivate => "ind-which-activate",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ pub enum Spark<'a> {
|
|||
|
||||
// Which
|
||||
WhichCallback(yazi_parser::which::CallbackOpt),
|
||||
WhichShow(yazi_parser::which::ShowOpt),
|
||||
WhichActivate(yazi_parser::which::ActivateOpt),
|
||||
}
|
||||
|
||||
impl<'a> Spark<'a> {
|
||||
|
|
@ -148,8 +148,8 @@ impl<'a> Spark<'a> {
|
|||
RelayStash => Self::Stash(<_>::from_lua(value, lua)?),
|
||||
// quit
|
||||
KeyQuit => Self::Quit(<_>::from_lua(value, lua)?),
|
||||
// which:show
|
||||
IndWhichShow => Self::WhichShow(<_>::from_lua(value, lua)?),
|
||||
// which:activate
|
||||
IndWhichActivate => Self::WhichActivate(<_>::from_lua(value, lua)?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -285,7 +285,7 @@ impl<'a> IntoLua for Spark<'a> {
|
|||
|
||||
// Which
|
||||
Self::WhichCallback(b) => b.into_lua(lua),
|
||||
Self::WhichShow(b) => b.into_lua(lua),
|
||||
Self::WhichActivate(b) => b.into_lua(lua),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -378,4 +378,4 @@ try_from_spark!(spot::CopyOpt, spot:copy);
|
|||
try_from_spark!(tasks::ProcessOpenOpt, tasks:process_open);
|
||||
try_from_spark!(tasks::UpdateSucceedOpt, tasks:update_succeed);
|
||||
try_from_spark!(which::CallbackOpt, which:callback);
|
||||
try_from_spark!(which::ShowOpt, which:show);
|
||||
try_from_spark!(which::ActivateOpt, which:activate);
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ impl App {
|
|||
succ!(Lives::scope(&self.core, || {
|
||||
let body = payload.body.into_lua(&LUA)?;
|
||||
for (id, cb) in handlers {
|
||||
runtime_mut!(LUA)?.push(&id);
|
||||
let blocking = runtime_mut!(LUA)?.critical_push(&id, true);
|
||||
if let Err(e) = cb.call::<()>(body.clone()) {
|
||||
error!("Failed to run `{kind}` event handler in your `{id}` plugin: {e}");
|
||||
}
|
||||
runtime_mut!(LUA)?.pop();
|
||||
runtime_mut!(LUA)?.critical_pop(blocking);
|
||||
}
|
||||
Ok(())
|
||||
})?);
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ impl App {
|
|||
succ!(self.core.tasks.plugin_entry(opt));
|
||||
}
|
||||
|
||||
runtime_mut!(LUA)?.push(&opt.id);
|
||||
defer! { _ = runtime_mut!(LUA).map(|mut r| r.pop()) }
|
||||
let blocking = runtime_mut!(LUA)?.critical_push(&opt.id, true);
|
||||
defer! { _ = runtime_mut!(LUA).map(|mut r| r.critical_pop(blocking)) }
|
||||
|
||||
let plugin = match LOADER.load_with(&LUA, &opt.id, chunk) {
|
||||
Ok(t) => t,
|
||||
|
|
|
|||
|
|
@ -340,7 +340,7 @@ impl<'a> Executor<'a> {
|
|||
};
|
||||
}
|
||||
|
||||
on!(show);
|
||||
on!(activate);
|
||||
on!(callback);
|
||||
|
||||
succ!();
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ impl Widget for Root<'_> {
|
|||
cmp::Cmp::new(self.core).render(area, buf);
|
||||
}
|
||||
|
||||
if self.core.which.visible {
|
||||
if self.core.which.active {
|
||||
which::Which::new(self.core).render(area, buf);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ impl<'a> Router<'a> {
|
|||
|
||||
if on.len() > 1 {
|
||||
let cx = &mut Ctx::active(&mut self.app.core);
|
||||
act!(which:show, cx, (layer, key)).ok();
|
||||
act!(which:activate, cx, (layer, key)).ok();
|
||||
} else {
|
||||
emit!(Seq(ChordCow::from(chord).into_seq()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,31 @@
|
|||
use anyhow::bail;
|
||||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Table, Value};
|
||||
use yazi_config::{KEYMAP, keymap::{ChordCow, Key}};
|
||||
use yazi_shared::{Layer, event::CmdCow};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ShowOpt {
|
||||
pub struct ActivateOpt {
|
||||
pub cands: Vec<ChordCow>,
|
||||
pub silent: bool,
|
||||
pub times: usize,
|
||||
}
|
||||
|
||||
impl TryFrom<CmdCow> for ShowOpt {
|
||||
impl TryFrom<CmdCow> for ActivateOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
|
||||
match c.take_any2("opt") {
|
||||
Some(opt) => opt,
|
||||
None => bail!("missing 'opt' argument"),
|
||||
if let Some(opt) = c.take_any2("opt") {
|
||||
return opt;
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
cands: c.take_any_iter::<yazi_binding::ChordCow>().map(Into::into).collect(),
|
||||
silent: c.bool("silent"),
|
||||
times: c.get("times").unwrap_or(0),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(Layer, Key)> for ShowOpt {
|
||||
impl From<(Layer, Key)> for ActivateOpt {
|
||||
fn from((layer, key): (Layer, Key)) -> Self {
|
||||
Self {
|
||||
cands: KEYMAP
|
||||
|
|
@ -36,13 +40,13 @@ impl From<(Layer, Key)> for ShowOpt {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromLua for ShowOpt {
|
||||
impl FromLua for ActivateOpt {
|
||||
fn from_lua(value: Value, _: &Lua) -> mlua::Result<Self> {
|
||||
let Value::Table(t) = value else {
|
||||
return Err("expected a table".into_lua_err());
|
||||
};
|
||||
|
||||
Ok(ShowOpt {
|
||||
Ok(Self {
|
||||
cands: t
|
||||
.raw_get::<Table>("cands")?
|
||||
.sequence_values::<yazi_binding::ChordCow>()
|
||||
|
|
@ -54,7 +58,7 @@ impl FromLua for ShowOpt {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoLua for ShowOpt {
|
||||
impl IntoLua for ActivateOpt {
|
||||
#[rustfmt::skip]
|
||||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
|
||||
lua
|
||||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(callback show);
|
||||
yazi_macro::mod_flat!(activate callback);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use tokio_stream::wrappers::UnboundedReceiverStream;
|
|||
use yazi_binding::{elements::{Line, Pos, Text}, runtime};
|
||||
use yazi_config::{keymap::{Chord, ChordCow, Key}, popup::{ConfirmCfg, InputCfg}};
|
||||
use yazi_macro::relay;
|
||||
use yazi_parser::which::ShowOpt;
|
||||
use yazi_parser::which::ActivateOpt;
|
||||
use yazi_proxy::{AppProxy, ConfirmProxy, InputProxy, WhichProxy};
|
||||
use yazi_shared::Debounce;
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ impl Utils {
|
|||
.collect::<mlua::Result<_>>()?;
|
||||
|
||||
drop(tx);
|
||||
WhichProxy::show(ShowOpt { cands, times: 0, silent: t.raw_get("silent")? });
|
||||
WhichProxy::activate(ActivateOpt { cands, times: 0, silent: t.raw_get("silent")? });
|
||||
|
||||
Ok(rx.recv().await.map(|idx| idx + 1))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::mem;
|
||||
|
||||
use anyhow::Context;
|
||||
use futures::future::join_all;
|
||||
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, MultiValue, Table, Value, Variadic};
|
||||
|
|
@ -12,39 +14,34 @@ use super::Utils;
|
|||
use crate::{bindings::{MpscRx, MpscTx, MpscUnboundedRx, MpscUnboundedTx, OneshotRx, OneshotTx}, loader::LOADER};
|
||||
|
||||
impl Utils {
|
||||
pub(super) fn sync(lua: &Lua, isolate: bool) -> mlua::Result<Function> {
|
||||
if isolate {
|
||||
lua.create_function(|lua, ()| {
|
||||
let Some(block) = runtime_mut!(lua)?.next_block() else {
|
||||
return Err("`ya.sync()` must be called in a plugin").into_lua_err();
|
||||
};
|
||||
pub(super) fn sync(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, f: Function| {
|
||||
let Some(block) = runtime_mut!(lua)?.put_block(&f) else {
|
||||
return Err("`ya.sync()` must be called in a plugin").into_lua_err();
|
||||
};
|
||||
|
||||
lua.create_async_function(move |lua, args: MultiValue| async move {
|
||||
let Some(cur) = runtime!(lua)?.current_owned() else {
|
||||
lua.create_async_function(move |lua, mut args: MultiValue| {
|
||||
let f = f.clone();
|
||||
async move {
|
||||
let rt = runtime!(lua)?;
|
||||
let (Some(cur), blocking) = (rt.current_owned(), rt.blocking) else {
|
||||
return Err("`ya.sync()` block must be used within a plugin").into_lua_err();
|
||||
};
|
||||
drop(rt);
|
||||
|
||||
Self::retrieve(&lua, &cur, block, args)
|
||||
.await
|
||||
.and_then(|data| Sendable::list_to_values(&lua, data))
|
||||
.with_context(|| format!("Failed to execute sync block-{block} in `{cur}` plugin"))
|
||||
.into_lua_err()
|
||||
})
|
||||
})
|
||||
} else {
|
||||
lua.create_function(|lua, f: Function| {
|
||||
let mut rt = runtime_mut!(lua)?;
|
||||
if !rt.put_block(&f) {
|
||||
return Err("`ya.sync()` must be called in a plugin").into_lua_err();
|
||||
if blocking {
|
||||
args.push_front(Value::Table(LOADER.try_load(&lua, &cur)?));
|
||||
f.call::<MultiValue>(args)
|
||||
} else {
|
||||
Self::retrieve(&lua, &cur, block, args)
|
||||
.await
|
||||
.and_then(|data| Sendable::list_to_values(&lua, data))
|
||||
.with_context(|| format!("Failed to execute sync block-{block} in `{cur}` plugin"))
|
||||
.into_lua_err()
|
||||
}
|
||||
}
|
||||
|
||||
let cur = rt.current_owned().unwrap();
|
||||
lua.create_function(move |lua, mut args: MultiValue| {
|
||||
args.push_front(Value::Table(LOADER.try_load(lua, &cur)?));
|
||||
f.call::<MultiValue>(args)
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn r#async(lua: &Lua, isolate: bool) -> mlua::Result<Function> {
|
||||
|
|
@ -55,9 +52,21 @@ impl Utils {
|
|||
} else {
|
||||
lua.create_function(|lua, (f, args): (Function, MultiValue)| {
|
||||
let name = runtime!(lua)?.current_owned();
|
||||
let lua = lua.clone();
|
||||
|
||||
Ok(Handle::AsyncFn(LOCAL_SET.spawn_local(async move {
|
||||
let blocking = mem::replace(&mut runtime_mut!(lua)?.blocking, false);
|
||||
if let Some(s) = &name {
|
||||
runtime_mut!(lua)?.push(s); // make `current_owned` always return Some to eliminate the check
|
||||
}
|
||||
|
||||
let result = f.call_async::<MultiValue>(args).await;
|
||||
|
||||
runtime_mut!(lua)?.blocking = blocking;
|
||||
if name.is_some() {
|
||||
runtime_mut!(lua)?.pop();
|
||||
}
|
||||
|
||||
if let Err(ref e) = result {
|
||||
match name {
|
||||
Some(s) => tracing::error!("Failed to execute async block in `{s}` plugin: {e}"),
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ pub fn compose(
|
|||
b"spot_widgets" => Utils::spot_widgets(lua)?,
|
||||
|
||||
// Sync
|
||||
b"sync" => Utils::sync(lua, isolate)?,
|
||||
b"sync" => Utils::sync(lua)?,
|
||||
b"async" => Utils::r#async(lua, isolate)?,
|
||||
b"chan" => Utils::chan(lua)?,
|
||||
b"join" => Utils::join(lua)?,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use yazi_macro::{emit, relay};
|
||||
use yazi_parser::which::ShowOpt;
|
||||
use yazi_parser::which::ActivateOpt;
|
||||
|
||||
pub struct WhichProxy;
|
||||
|
||||
impl WhichProxy {
|
||||
pub fn show(opt: ShowOpt) {
|
||||
emit!(Call(relay!(which:show).with_any("opt", opt)));
|
||||
pub fn activate(opt: ActivateOpt) {
|
||||
emit!(Call(relay!(which:activate).with_any("opt", opt)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use hashbrown::{HashMap, hash_map::RawEntryMut};
|
||||
use hashbrown::{HashMap, hash_map::Entry};
|
||||
use ordered_float::OrderedFloat;
|
||||
use yazi_config::YAZI;
|
||||
use yazi_parser::app::TaskSummary;
|
||||
|
|
@ -24,8 +24,8 @@ impl Ongoing {
|
|||
}
|
||||
|
||||
pub(super) fn cancel(&mut self, id: Id) -> Option<TaskIn> {
|
||||
match self.inner.raw_entry_mut().from_key(&id) {
|
||||
RawEntryMut::Occupied(mut oe) => {
|
||||
match self.inner.entry(id) {
|
||||
Entry::Occupied(mut oe) => {
|
||||
let task = oe.get_mut();
|
||||
task.done.complete(false);
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ impl Ongoing {
|
|||
|
||||
oe.remove();
|
||||
}
|
||||
RawEntryMut::Vacant(_) => {}
|
||||
Entry::Vacant(_) => {}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,6 +185,10 @@ impl Cmd {
|
|||
self.args.remove(&name.into()).map(Data::into_any2)
|
||||
}
|
||||
|
||||
pub fn take_any_iter<T: 'static>(&mut self) -> impl Iterator<Item = T> {
|
||||
(0..self.len()).filter_map(|i| self.args.remove(&DataKey::from(i))?.into_any())
|
||||
}
|
||||
|
||||
// Parse
|
||||
pub fn parse_args<I>(words: I, last: Option<String>) -> Result<HashMap<DataKey, Data>>
|
||||
where
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::ops::Deref;
|
||||
use std::{iter, ops::Deref};
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
|
|
@ -92,4 +92,11 @@ impl CmdCow {
|
|||
Self::Borrowed(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take_any_iter<'a, T: 'static>(&'a mut self) -> Box<dyn Iterator<Item = T> + 'a> {
|
||||
match self {
|
||||
Self::Owned(c) => Box::new(c.take_any_iter()),
|
||||
Self::Borrowed(_) => Box::new(iter::empty()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue