mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 14:51:03 +00:00
feat: new input DDS event watching changes in input content (#4043)
This commit is contained in:
parent
b37be0529a
commit
f1e93d7f52
26 changed files with 220 additions and 50 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
|
@ -5565,6 +5565,7 @@ dependencies = [
|
|||
"indexmap 2.14.0",
|
||||
"libc",
|
||||
"mlua",
|
||||
"parking_lot",
|
||||
"paste",
|
||||
"ratatui",
|
||||
"scopeguard",
|
||||
|
|
@ -6001,8 +6002,10 @@ version = "26.5.6"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"yazi-config",
|
||||
"yazi-core",
|
||||
"yazi-dds",
|
||||
"yazi-macro",
|
||||
"yazi-scheduler",
|
||||
"yazi-shared",
|
||||
|
|
@ -6227,11 +6230,13 @@ version = "26.5.6"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"clipboard-win",
|
||||
"dyn-clone",
|
||||
"futures",
|
||||
"mlua",
|
||||
"parking_lot",
|
||||
"ratatui",
|
||||
"serde",
|
||||
"strum",
|
||||
"tokio",
|
||||
"unicode-width",
|
||||
"yazi-adapter",
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ futures = { workspace = true }
|
|||
hashbrown = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
ratatui = { workspace = true }
|
||||
scopeguard = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ impl Actor for Close {
|
|||
};
|
||||
|
||||
guard.ticket.next();
|
||||
if let Some(tx) = guard.tx.take() {
|
||||
if let Some(cb) = guard.cb.take() {
|
||||
let value = guard.snap().value.clone();
|
||||
_ = tx.send(if form.submit { InputEvent::Submit(value) } else { InputEvent::Cancel(value) });
|
||||
cb(if form.submit { InputEvent::Submit(value) } else { InputEvent::Cancel(value) });
|
||||
}
|
||||
|
||||
drop(guard);
|
||||
|
|
|
|||
|
|
@ -14,8 +14,9 @@ pub(super) struct Core {
|
|||
c_tabs: Option<Value>,
|
||||
c_tasks: Option<Value>,
|
||||
c_yanked: Option<Value>,
|
||||
c_layer: Option<Value>,
|
||||
c_input: Option<Value>,
|
||||
c_which: Option<Value>,
|
||||
c_layer: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Core {
|
||||
|
|
@ -33,8 +34,9 @@ impl Core {
|
|||
c_tabs: None,
|
||||
c_tasks: None,
|
||||
c_yanked: None,
|
||||
c_layer: None,
|
||||
c_input: None,
|
||||
c_which: None,
|
||||
c_layer: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -59,10 +61,11 @@ impl UserData for Core {
|
|||
b"tabs" => reuse!(tabs, super::Tabs::make(&me.mgr.tabs)),
|
||||
b"tasks" => reuse!(tasks, super::Tasks::make(&me.tasks)),
|
||||
b"yanked" => reuse!(yanked, super::Yanked::make(&me.mgr.yanked)),
|
||||
b"input" => reuse!(input, super::Input::make(&me.input)),
|
||||
b"which" => reuse!(which, super::Which::make(&me.which)),
|
||||
b"layer" => {
|
||||
reuse!(layer, Ok::<_, mlua::Error>(yazi_binding::Layer::from(me.layer())))
|
||||
}
|
||||
b"which" => reuse!(which, super::Which::make(&me.which)),
|
||||
_ => Value::Nil,
|
||||
})
|
||||
});
|
||||
|
|
|
|||
29
yazi-actor/src/lives/input.rs
Normal file
29
yazi-actor/src/lives/input.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, UserData, UserDataFields};
|
||||
use yazi_shim::mlua::UserDataFieldsExt;
|
||||
|
||||
use super::{Lives, PtrCell};
|
||||
use crate::lives::InputAlt;
|
||||
|
||||
pub(super) struct Input {
|
||||
inner: PtrCell<yazi_core::input::Input>,
|
||||
}
|
||||
|
||||
impl Deref for Input {
|
||||
type Target = yazi_core::input::Input;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Input {
|
||||
pub(super) fn make(inner: &yazi_core::input::Input) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner: inner.into() })
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Input {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_cached_field("alt", |_, me| me.alt.as_ref().map(InputAlt::make).transpose());
|
||||
}
|
||||
}
|
||||
27
yazi-actor/src/lives/input_alt.rs
Normal file
27
yazi-actor/src/lives/input_alt.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use mlua::{AnyUserData, UserData, UserDataFields};
|
||||
use parking_lot::Mutex;
|
||||
use yazi_shim::mlua::UserDataFieldsExt;
|
||||
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct InputAlt(PtrCell<Arc<Mutex<yazi_widgets::input::Input>>>);
|
||||
|
||||
impl Deref for InputAlt {
|
||||
type Target = Arc<Mutex<yazi_widgets::input::Input>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.0 }
|
||||
}
|
||||
|
||||
impl InputAlt {
|
||||
pub(super) fn make(inner: &Arc<Mutex<yazi_widgets::input::Input>>) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self(inner.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for InputAlt {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_cached_field("value", |lua, me| lua.create_string(me.lock().value()));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
yazi_macro::mod_flat!(behavior core file files filter finder folder lives mode mut_cell preference preview ptr selected tab tabs task tasks which yanked);
|
||||
yazi_macro::mod_flat!(behavior core file files filter finder folder input input_alt lives mode mut_cell preference preview ptr selected tab tabs task tasks which yanked);
|
||||
|
||||
pub(super) fn init() {
|
||||
unsafe { FILE_CACHE.get().write(std::mem::MaybeUninit::new(<_>::default())) };
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ pub struct Border {
|
|||
pub edge: Edge,
|
||||
pub r#type: ratatui::widgets::BorderType,
|
||||
pub style: ratatui::style::Style,
|
||||
pub merge: ratatui::symbols::merge::MergeStrategy,
|
||||
|
||||
pub titles: Vec<(ratatui::widgets::TitlePosition, ratatui::text::Line<'static>)>,
|
||||
}
|
||||
|
|
@ -64,7 +65,8 @@ impl Widget for Border {
|
|||
let mut block = ratatui::widgets::Block::default()
|
||||
.borders(self.edge.0)
|
||||
.border_type(self.r#type)
|
||||
.border_style(self.style);
|
||||
.border_style(self.style)
|
||||
.merge_borders(self.merge);
|
||||
|
||||
for title in self.titles {
|
||||
block = match title {
|
||||
|
|
@ -116,5 +118,13 @@ impl UserData for Border {
|
|||
ud.borrow_mut::<Self>()?.edge = edge;
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function("merge", |_, (ud, exact): (AnyUserData, bool)| {
|
||||
ud.borrow_mut::<Self>()?.merge = if exact {
|
||||
ratatui::symbols::merge::MergeStrategy::Exact
|
||||
} else {
|
||||
ratatui::symbols::merge::MergeStrategy::Fuzzy
|
||||
};
|
||||
Ok(ud)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ impl TryFrom<Table> for Input {
|
|||
realtime: false,
|
||||
completion: false,
|
||||
},
|
||||
tx: None,
|
||||
cb: None,
|
||||
})?;
|
||||
|
||||
Ok(Self { inner: Arc::new(Mutex::new(input)), ..Default::default() })
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use anyhow::{Result, bail};
|
|||
use mlua::{ExternalResult, IntoLua, Lua, Value};
|
||||
use yazi_shared::Id;
|
||||
|
||||
use super::{EmberBulkRename, EmberBye, EmberCd, EmberCustom, EmberDelete, EmberDownload, EmberDuplicate, EmberHey, EmberHi, EmberHover, EmberLoad, EmberMount, EmberMove, EmberRename, EmberTab, EmberTrash, EmberYank};
|
||||
use super::{EmberBulkRename, EmberBye, EmberCd, EmberCustom, EmberDelete, EmberDownload, EmberDuplicate, EmberHey, EmberHi, EmberHover, EmberInput, EmberLoad, EmberMount, EmberMove, EmberRename, EmberTab, EmberTrash, EmberYank};
|
||||
use crate::Payload;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -22,6 +22,7 @@ pub enum Ember<'a> {
|
|||
Trash(EmberTrash<'a>),
|
||||
Delete(EmberDelete<'a>),
|
||||
Download(EmberDownload<'a>),
|
||||
Input(EmberInput<'a>),
|
||||
Mount(EmberMount),
|
||||
Custom(EmberCustom),
|
||||
}
|
||||
|
|
@ -44,6 +45,7 @@ impl Ember<'static> {
|
|||
"trash" => Self::Trash(serde_json::from_str(body)?),
|
||||
"delete" => Self::Delete(serde_json::from_str(body)?),
|
||||
"download" => Self::Download(serde_json::from_str(body)?),
|
||||
"input" => Self::Input(serde_json::from_str(body)?),
|
||||
"mount" => Self::Mount(serde_json::from_str(body)?),
|
||||
_ => EmberCustom::from_str(kind, body)?,
|
||||
})
|
||||
|
|
@ -72,6 +74,7 @@ impl Ember<'static> {
|
|||
| "trash"
|
||||
| "delete"
|
||||
| "download"
|
||||
| "input"
|
||||
| "mount"
|
||||
) || kind.starts_with("key-")
|
||||
|| kind.starts_with("ind-")
|
||||
|
|
@ -111,6 +114,7 @@ impl<'a> Ember<'a> {
|
|||
Self::Trash(_) => "trash",
|
||||
Self::Delete(_) => "delete",
|
||||
Self::Download(_) => "download",
|
||||
Self::Input(_) => "input",
|
||||
Self::Mount(_) => "mount",
|
||||
Self::Custom(b) => b.kind.as_str(),
|
||||
}
|
||||
|
|
@ -139,6 +143,7 @@ impl<'a> IntoLua for Ember<'a> {
|
|||
Self::Trash(b) => b.into_lua(lua),
|
||||
Self::Delete(b) => b.into_lua(lua),
|
||||
Self::Download(b) => b.into_lua(lua),
|
||||
Self::Input(b) => b.into_lua(lua),
|
||||
Self::Mount(b) => b.into_lua(lua),
|
||||
Self::Custom(b) => b.into_lua(lua),
|
||||
}
|
||||
|
|
|
|||
34
yazi-dds/src/ember/input.rs
Normal file
34
yazi-dds/src/ember/input.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use mlua::{IntoLua, Lua, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::Ember;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct EmberInput<'a> {
|
||||
pub r#type: Cow<'a, str>,
|
||||
pub value: Cow<'a, str>,
|
||||
}
|
||||
|
||||
impl<'a> EmberInput<'a> {
|
||||
pub fn borrowed(r#type: &'a str, value: &'a str) -> Ember<'a> {
|
||||
Self { r#type: r#type.into(), value: value.into() }.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl EmberInput<'static> {
|
||||
pub fn owned(r#type: &'static str, value: &str) -> Ember<'static> {
|
||||
Self { r#type: r#type.into(), value: value.to_owned().into() }.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<EmberInput<'a>> for Ember<'a> {
|
||||
fn from(value: EmberInput<'a>) -> Self { Self::Input(value) }
|
||||
}
|
||||
|
||||
impl IntoLua for EmberInput<'_> {
|
||||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
|
||||
lua.create_table_from([("type", self.r#type), ("value", self.value)])?.into_lua(lua)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
yazi_macro::mod_flat!(
|
||||
bulk_rename bye cd custom delete download duplicate ember hey hi hover load mount r#move rename tab trash yank
|
||||
bulk_rename bye cd custom delete download duplicate ember hey hi hover input load mount r#move rename tab trash yank
|
||||
);
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ impl Display for Payload<'_> {
|
|||
Ember::Trash(b) => serde_json::to_string(b),
|
||||
Ember::Delete(b) => serde_json::to_string(b),
|
||||
Ember::Download(b) => serde_json::to_string(b),
|
||||
Ember::Input(b) => serde_json::to_string(b),
|
||||
Ember::Mount(b) => serde_json::to_string(b),
|
||||
Ember::Custom(b) => serde_json::to_string(b),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -174,5 +174,7 @@ impl Pubsub {
|
|||
|
||||
pub_after!(download(urls: Vec<UrlBuf>), (&urls), (urls));
|
||||
|
||||
pub_after!(input(r#type: &'static str, value: &str), (r#type, value));
|
||||
|
||||
pub_after!(mount(), ());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -249,12 +249,12 @@ impl<'a> Executor<'a> {
|
|||
}
|
||||
|
||||
fn input(&mut self, action: ActionCow) -> Result<Data> {
|
||||
let Some(mut guard) = self.app.core.input.lock_mut() else { succ!() };
|
||||
|
||||
let mut guard;
|
||||
macro_rules! on {
|
||||
($name:ident) => {
|
||||
if action.name == stringify!($name) {
|
||||
on!(input:$name, action);
|
||||
let cx = &mut Ctx::new(&action, &mut self.app.core, &mut self.app.term)?;
|
||||
return act!(input:$name, cx, action);
|
||||
}
|
||||
};
|
||||
($layer:ident : $name:ident, $opt:expr) => {{
|
||||
|
|
@ -268,6 +268,11 @@ impl<'a> Executor<'a> {
|
|||
on!(show);
|
||||
on!(close);
|
||||
|
||||
guard = match self.app.core.input.lock_mut() {
|
||||
Some(g) => g,
|
||||
None => succ!(),
|
||||
};
|
||||
|
||||
match guard.mode() {
|
||||
InputMode::Normal => match action.name.as_ref() {
|
||||
"help" => on!(help:toggle, Layer::Input),
|
||||
|
|
@ -275,9 +280,10 @@ impl<'a> Executor<'a> {
|
|||
"lua" => on!(app:lua, action),
|
||||
_ => {}
|
||||
},
|
||||
InputMode::Insert => {
|
||||
on!(complete);
|
||||
}
|
||||
InputMode::Insert => match action.name.as_ref() {
|
||||
"complete" => on!(input:complete, action),
|
||||
_ => {}
|
||||
},
|
||||
InputMode::Replace => {}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,17 @@
|
|||
#[macro_export]
|
||||
macro_rules! input {
|
||||
($cx:ident, $cfg:expr) => {{
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_shim::strum::IntoStr;
|
||||
use yazi_widgets::input::{InputCallback, InputEvent, InputOpt};
|
||||
|
||||
let (tx, rx) = ::tokio::sync::mpsc::unbounded_channel();
|
||||
match $crate::act!(input:show, $cx, yazi_widgets::input::InputOpt { cfg: $cfg, tx: Some(tx) }) {
|
||||
let cb: Box<dyn InputCallback> = Box::new(move |event| {
|
||||
$crate::err!(Pubsub::pub_after_input((&event).into_str(), event.value()));
|
||||
tx.send(event).ok();
|
||||
});
|
||||
|
||||
match $crate::act!(input:show, $cx, InputOpt { cfg: $cfg, cb: Some(cb) }) {
|
||||
Ok(_) => Ok(rx),
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ impl Utils {
|
|||
edge: Edge(ratatui::widgets::Borders::ALL),
|
||||
r#type: ratatui::widgets::BorderType::Rounded,
|
||||
style: THEME.spot.border.get().into(),
|
||||
merge: Default::default(),
|
||||
titles: vec![(
|
||||
ratatui::widgets::TitlePosition::Top,
|
||||
ratatui::text::Line::raw("Spot").centered().style(THEME.spot.title.get()),
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ yazi-config = { path = "../yazi-config", version = "26.5.6" }
|
|||
yazi-core = { path = "../yazi-core", version = "26.5.6" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "26.5.6" }
|
||||
yazi-scheduler = { path = "../yazi-scheduler", version = "26.5.6" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "26.5.6" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "26.5.6" }
|
||||
yazi-shim = { path = "../yazi-shim", version = "26.5.6" }
|
||||
yazi-widgets = { path = "../yazi-widgets", version = "26.5.6" }
|
||||
|
|
@ -24,3 +25,4 @@ yazi-widgets = { path = "../yazi-widgets", version = "26.5.6" }
|
|||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,14 +1,21 @@
|
|||
use tokio::sync::mpsc;
|
||||
use yazi_config::popup::InputCfg;
|
||||
use yazi_macro::{emit, relay};
|
||||
use yazi_widgets::input::InputEvent;
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_macro::{emit, err, relay};
|
||||
use yazi_shim::strum::IntoStr;
|
||||
use yazi_widgets::input::{InputCallback, InputEvent};
|
||||
|
||||
pub struct InputProxy;
|
||||
|
||||
impl InputProxy {
|
||||
pub fn show(cfg: InputCfg) -> mpsc::UnboundedReceiver<InputEvent> {
|
||||
let (tx, rx) = mpsc::unbounded_channel();
|
||||
emit!(Call(relay!(input:show).with_any("tx", tx).with_any("cfg", cfg)));
|
||||
let cb: Box<dyn InputCallback> = Box::new(move |event| {
|
||||
err!(Pubsub::pub_after_input((&event).into_str(), event.value()));
|
||||
tx.send(event).ok();
|
||||
});
|
||||
|
||||
emit!(Call(relay!(input:show).with_any("cb", cb).with_any("cfg", cfg)));
|
||||
rx
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,11 +27,13 @@ yazi-tty = { path = "../yazi-tty", version = "26.5.9" }
|
|||
|
||||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
dyn-clone = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
ratatui = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
strum = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
unicode-width = { workspace = true }
|
||||
|
||||
|
|
|
|||
22
yazi-widgets/src/input/callback.rs
Normal file
22
yazi-widgets/src/input/callback.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
use std::fmt;
|
||||
|
||||
use dyn_clone::DynClone;
|
||||
use yazi_macro::impl_data_any;
|
||||
|
||||
use crate::input::InputEvent;
|
||||
|
||||
pub trait InputCallback: Fn(InputEvent) + Send + Sync + DynClone + 'static {}
|
||||
|
||||
impl<T: Fn(InputEvent) + Send + Sync + Clone + 'static> InputCallback for T {}
|
||||
|
||||
impl Clone for Box<dyn InputCallback> {
|
||||
fn clone(&self) -> Self { dyn_clone::clone_box(&**self) }
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn InputCallback {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("InputCallback").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl_data_any!(Box<dyn InputCallback>);
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
use strum::IntoStaticStr;
|
||||
use yazi_shared::Id;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, IntoStaticStr)]
|
||||
pub enum InputEvent {
|
||||
Submit(String),
|
||||
Cancel(String),
|
||||
|
|
@ -10,5 +11,11 @@ pub enum InputEvent {
|
|||
}
|
||||
|
||||
impl InputEvent {
|
||||
pub fn value(&self) -> &str {
|
||||
match self {
|
||||
Self::Submit(v) | Self::Cancel(v) | Self::Type(v) | Self::Trigger(v, _) => v.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_submit(&self) -> bool { matches!(self, Self::Submit(_)) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use std::{borrow::Cow, ops::Range};
|
||||
|
||||
use anyhow::Result;
|
||||
use tokio::sync::mpsc;
|
||||
use yazi_config::{YAZI, popup::Position};
|
||||
use yazi_macro::act;
|
||||
use yazi_shared::Ids;
|
||||
|
|
@ -9,7 +8,7 @@ use yazi_shim::path::CROSS_SEPARATOR;
|
|||
use yazi_term::CursorStyle;
|
||||
|
||||
use super::{InputSnap, InputSnaps, mode::InputMode, op::InputOp};
|
||||
use crate::{CLIPBOARD, input::{InputEvent, InputOpt}};
|
||||
use crate::{CLIPBOARD, input::{InputCallback, InputEvent, InputOpt}};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Input {
|
||||
|
|
@ -19,7 +18,7 @@ pub struct Input {
|
|||
pub realtime: bool,
|
||||
pub completion: bool,
|
||||
|
||||
pub tx: Option<mpsc::UnboundedSender<InputEvent>>,
|
||||
pub cb: Option<Box<dyn InputCallback>>,
|
||||
pub ticket: Ids,
|
||||
}
|
||||
|
||||
|
|
@ -33,7 +32,7 @@ impl Input {
|
|||
realtime: opt.cfg.realtime,
|
||||
completion: opt.cfg.completion,
|
||||
|
||||
tx: opt.tx,
|
||||
cb: opt.cb,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
|
@ -93,20 +92,19 @@ impl Input {
|
|||
|
||||
pub(super) fn flush_type(&mut self) {
|
||||
self.ticket.next();
|
||||
if let Some(tx) = self.tx.as_ref().filter(|_| self.realtime) {
|
||||
tx.send(InputEvent::Type(self.value().to_owned())).ok();
|
||||
if let Some(cb) = self.cb.as_ref().filter(|_| self.realtime) {
|
||||
cb(InputEvent::Type(self.value().to_owned()));
|
||||
}
|
||||
|
||||
self.flush_trigger(true);
|
||||
}
|
||||
|
||||
pub(super) fn flush_trigger(&self, force: bool) {
|
||||
if let Some(tx) = self.tx.as_ref().filter(|_| self.completion) {
|
||||
tx.send(InputEvent::Trigger(
|
||||
if let Some(cb) = self.cb.as_ref().filter(|_| self.completion) {
|
||||
cb(InputEvent::Trigger(
|
||||
self.partition().0.to_owned(),
|
||||
(!force).then_some(self.ticket.current()),
|
||||
))
|
||||
.ok();
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
yazi_macro::mod_pub!(actor parser);
|
||||
|
||||
yazi_macro::mod_flat!(chars event gait input mode op option snap snaps widget);
|
||||
yazi_macro::mod_flat!(callback chars event gait input mode op option snap snaps widget);
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
use anyhow::bail;
|
||||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use tokio::sync::mpsc;
|
||||
use yazi_config::popup::InputCfg;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
use crate::input::InputEvent;
|
||||
use crate::input::InputCallback;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InputOpt {
|
||||
pub cfg: InputCfg,
|
||||
pub tx: Option<mpsc::UnboundedSender<InputEvent>>,
|
||||
pub cb: Option<Box<dyn InputCallback>>,
|
||||
}
|
||||
|
||||
impl TryFrom<ActionCow> for InputOpt {
|
||||
|
|
@ -20,7 +19,7 @@ impl TryFrom<ActionCow> for InputOpt {
|
|||
bail!("invalid 'cfg' in InputOpt");
|
||||
};
|
||||
|
||||
Ok(Self { cfg, tx: a.take_any("tx") })
|
||||
Ok(Self { cfg, cb: a.take_any("cb") })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue