diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c7ce80d..1e0d9d0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): - Custom tab name ([#3666]) - New `--in` for `search` action to set search directory ([#3696]) +- Hover cursor over the new file after copying/cutting/linking/hardlinking ([#3846]) - Multi-file spotter ([#3733]) - Vim-like `lua` action that runs an inline Lua snippet ([#3813]) - Certificate authentication for SFTP VFS provider ([#3716]) @@ -1694,3 +1695,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): [#3792]: https://github.com/sxyazi/yazi/pull/3792 [#3804]: https://github.com/sxyazi/yazi/pull/3804 [#3813]: https://github.com/sxyazi/yazi/pull/3813 +[#3846]: https://github.com/sxyazi/yazi/pull/3846 diff --git a/Cargo.toml b/Cargo.toml index daccf54f..b8221aa1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ debug = false [workspace.dependencies] ansi-to-tui = "8.0.1" anyhow = "1.0.102" +arc-swap = "1.9.0" base64 = "0.22.1" bitflags = { version = "2.11.0", features = [ "serde" ] } chrono = "0.4.44" diff --git a/yazi-actor/src/app/deprecate.rs b/yazi-actor/src/app/deprecate.rs index afac183e..9c543172 100644 --- a/yazi-actor/src/app/deprecate.rs +++ b/yazi-actor/src/app/deprecate.rs @@ -13,10 +13,10 @@ impl Actor for Deprecate { const NAME: &str = "deprecate"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { act!(notify:push, cx, MessageOpt { title: "Deprecated API".to_owned(), - content: opt.content.into_owned(), + content: form.content.into_owned(), level: MessageLevel::Warn, timeout: std::time::Duration::from_secs(20), }) diff --git a/yazi-actor/src/app/lua.rs b/yazi-actor/src/app/lua.rs index 4543fcf6..65a50abf 100644 --- a/yazi-actor/src/app/lua.rs +++ b/yazi-actor/src/app/lua.rs @@ -15,8 +15,8 @@ impl Actor for Lua { const NAME: &str = "lua"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - let chunk = LUA.load(&*opt.code).set_name("anonymous"); + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + let chunk = LUA.load(&*form.code).set_name("anonymous"); let result = Lives::scope(cx.core, || { runtime_scope!(LUA, "inline", Sendable::value_to_data(&LUA, chunk.eval()?)) }); diff --git a/yazi-actor/src/app/mouse.rs b/yazi-actor/src/app/mouse.rs index 8f1a92ae..c7717806 100644 --- a/yazi-actor/src/app/mouse.rs +++ b/yazi-actor/src/app/mouse.rs @@ -19,8 +19,8 @@ impl Actor for Mouse { const NAME: &str = "mouse"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - let event = yazi_binding::MouseEvent::from(opt.event); + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + let event = yazi_binding::MouseEvent::from(form.event); let Some(size) = cx.term.as_ref().and_then(|t| t.size().ok()) else { succ!() }; let area = yazi_binding::elements::Rect::from(size); diff --git a/yazi-actor/src/app/reflow.rs b/yazi-actor/src/app/reflow.rs index df496856..cd4390a1 100644 --- a/yazi-actor/src/app/reflow.rs +++ b/yazi-actor/src/app/reflow.rs @@ -17,12 +17,12 @@ impl Actor for Reflow { const NAME: &str = "reflow"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let Some(size) = cx.term.as_ref().and_then(|t| t.size().ok()) else { succ!() }; let mut layout = LAYOUT.get(); let result = Lives::scope(cx.core, || { - let comps = (opt.reflow)((Position::ORIGIN, size).into())?; + let comps = (form.reflow)((Position::ORIGIN, size).into())?; for v in comps.sequence_values::() { let Value::Table(t) = v? else { diff --git a/yazi-actor/src/app/resize.rs b/yazi-actor/src/app/resize.rs index 037f62ab..b6e21abe 100644 --- a/yazi-actor/src/app/resize.rs +++ b/yazi-actor/src/app/resize.rs @@ -13,8 +13,8 @@ impl Actor for Resize { const NAME: &str = "resize"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - act!(app:reflow, cx, opt)?; + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + act!(app:reflow, cx, form)?; cx.current_mut().arrow(0); cx.parent_mut().map(|f| f.arrow(0)); diff --git a/yazi-actor/src/app/resume.rs b/yazi-actor/src/app/resume.rs index 502eaaf7..94608eb2 100644 --- a/yazi-actor/src/app/resume.rs +++ b/yazi-actor/src/app/resume.rs @@ -13,15 +13,15 @@ impl Actor for Resume { const NAME: &str = "resume"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { cx.active_mut().preview.reset(); *cx.term = Some(Term::start()?); // While the app resumes, it's possible that the terminal size has changed. // We need to trigger a resize, and render the UI based on the resized area. - act!(app:resize, cx, opt.reflow)?; + act!(app:resize, cx, form.reflow)?; - opt.tx.send((true, opt.token))?; + form.tx.send((true, form.replier))?; act!(app:title, cx).ok(); succ!(render!()); diff --git a/yazi-actor/src/app/stop.rs b/yazi-actor/src/app/stop.rs index 69e1af0e..ee67d1a9 100644 --- a/yazi-actor/src/app/stop.rs +++ b/yazi-actor/src/app/stop.rs @@ -12,7 +12,7 @@ impl Actor for Stop { const NAME: &str = "stop"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { cx.active_mut().preview.reset_image(); // We need to destroy the `term` first before stopping the `signals` @@ -20,7 +20,7 @@ impl Actor for Stop { // while the app is being suspended. *cx.term = None; - opt.tx.send((false, opt.token))?; + form.tx.send((false, form.replier))?; succ!(); } diff --git a/yazi-actor/src/app/title.rs b/yazi-actor/src/app/title.rs index 6b5587b5..555e11c7 100644 --- a/yazi-actor/src/app/title.rs +++ b/yazi-actor/src/app/title.rs @@ -16,15 +16,15 @@ impl Actor for Title { const NAME: &str = "title"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - let s = opt.value.unwrap_or_else(|| format!("Yazi: {}", cx.tab().name()).into()); + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + let s = form.value.unwrap_or_else(|| format!("Yazi: {}", cx.tab().name()).into()); execute!(TTY.writer(), SetTitle(&s))?; yazi_term::STATE.set(TermState { title: !s.is_empty(), ..yazi_term::STATE.get() }); succ!() } - fn hook(cx: &Ctx, _opt: &Self::Form) -> Option { + fn hook(cx: &Ctx, _form: &Self::Form) -> Option { match cx.source() { Source::Ind => Some(SparkKind::IndAppTitle), _ => None, diff --git a/yazi-actor/src/app/update_progress.rs b/yazi-actor/src/app/update_progress.rs index 7d4d4b05..800a4d4b 100644 --- a/yazi-actor/src/app/update_progress.rs +++ b/yazi-actor/src/app/update_progress.rs @@ -13,11 +13,11 @@ impl Actor for UpdateProgress { const NAME: &str = "update_progress"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { // Update the progress of all tasks. let tasks = &mut cx.tasks; - let progressed = tasks.summary != opt.summary; - tasks.summary = opt.summary; + let progressed = tasks.summary != form.summary; + tasks.summary = form.summary; // If the task manager is visible, update the snaps with a full render. if tasks.visible { diff --git a/yazi-actor/src/cmp/arrow.rs b/yazi-actor/src/cmp/arrow.rs index 5f0d4139..322441f1 100644 --- a/yazi-actor/src/cmp/arrow.rs +++ b/yazi-actor/src/cmp/arrow.rs @@ -13,7 +13,7 @@ impl Actor for Arrow { const NAME: &str = "arrow"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - succ!(render!(cx.cmp.scroll(opt.step))); + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + succ!(render!(cx.cmp.scroll(form.step))); } } diff --git a/yazi-actor/src/cmp/close.rs b/yazi-actor/src/cmp/close.rs index 633a95d6..11851ac7 100644 --- a/yazi-actor/src/cmp/close.rs +++ b/yazi-actor/src/cmp/close.rs @@ -15,9 +15,9 @@ impl Actor for Close { const NAME: &str = "close"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let cmp = &mut cx.cmp; - if let Some(item) = cmp.selected().filter(|_| opt.submit).cloned() { + if let Some(item) = cmp.selected().filter(|_| form.submit).cloned() { return act!(input:complete, cx, CompleteOpt { name: item.name, is_dir: item.is_dir, ticket: cmp.ticket }); } diff --git a/yazi-actor/src/cmp/trigger.rs b/yazi-actor/src/cmp/trigger.rs index 5f32022d..ce9a3468 100644 --- a/yazi-actor/src/cmp/trigger.rs +++ b/yazi-actor/src/cmp/trigger.rs @@ -18,15 +18,15 @@ impl Actor for Trigger { const NAME: &str = "trigger"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - if opt.ticket.is_some_and(|t| t != cx.cmp.ticket) { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + if form.ticket.is_some_and(|t| t != cx.cmp.ticket) { succ!(); - } else if opt.ticket.is_none() { + } else if form.ticket.is_none() { cx.cmp.ticket = cx.input.ticket.current(); } cx.cmp.handle.take().map(|h| h.abort()); - let Some((parent, word)) = Self::split_url(&opt.word) else { + let Some((parent, word)) = Self::split_url(&form.word) else { return act!(cmp:close, cx, false); }; diff --git a/yazi-actor/src/confirm/arrow.rs b/yazi-actor/src/confirm/arrow.rs index a892dd51..3318b3fc 100644 --- a/yazi-actor/src/confirm/arrow.rs +++ b/yazi-actor/src/confirm/arrow.rs @@ -12,14 +12,14 @@ impl Actor for Arrow { const NAME: &str = "arrow"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let confirm = &mut cx.core.confirm; let area = cx.core.mgr.area(confirm.position); let len = confirm.list.line_count(area.width); let old = confirm.offset; - confirm.offset = opt.step.add(confirm.offset, len, area.height as _); + confirm.offset = form.step.add(confirm.offset, len, area.height as _); succ!(render!(old != confirm.offset)); } diff --git a/yazi-actor/src/confirm/close.rs b/yazi-actor/src/confirm/close.rs index fa3001d8..d767c6ee 100644 --- a/yazi-actor/src/confirm/close.rs +++ b/yazi-actor/src/confirm/close.rs @@ -12,8 +12,8 @@ impl Actor for Close { const NAME: &str = "close"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - cx.confirm.token.complete(opt.submit); + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + cx.confirm.token.complete(form.submit); cx.confirm.visible = false; succ!(render!()); } diff --git a/yazi-actor/src/confirm/show.rs b/yazi-actor/src/confirm/show.rs index 800d4625..6a4dd7f9 100644 --- a/yazi-actor/src/confirm/show.rs +++ b/yazi-actor/src/confirm/show.rs @@ -12,18 +12,18 @@ impl Actor for Show { const NAME: &str = "show"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { act!(confirm:close, cx)?; let confirm = &mut cx.confirm; - confirm.title = opt.cfg.title; - confirm.body = opt.cfg.body; - confirm.list = opt.cfg.list; + confirm.title = form.cfg.title; + confirm.body = form.cfg.body; + confirm.list = form.cfg.list; - confirm.position = opt.cfg.position; + confirm.position = form.cfg.position; confirm.offset = 0; - confirm.token = opt.token; + confirm.token = form.token; confirm.visible = true; succ!(render!()); diff --git a/yazi-actor/src/help/arrow.rs b/yazi-actor/src/help/arrow.rs index 3f58c03d..ff50c861 100644 --- a/yazi-actor/src/help/arrow.rs +++ b/yazi-actor/src/help/arrow.rs @@ -13,7 +13,7 @@ impl Actor for Arrow { const NAME: &str = "arrow"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - succ!(render!(cx.help.scroll(opt.step))); + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + succ!(render!(cx.help.scroll(form.step))); } } diff --git a/yazi-actor/src/help/toggle.rs b/yazi-actor/src/help/toggle.rs index c3abf422..2a55080d 100644 --- a/yazi-actor/src/help/toggle.rs +++ b/yazi-actor/src/help/toggle.rs @@ -12,11 +12,11 @@ impl Actor for Toggle { const NAME: &str = "toggle"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let help = &mut cx.help; help.visible = !help.visible; - help.layer = opt.layer; + help.layer = form.layer; help.keyword = String::new(); help.in_filter = None; diff --git a/yazi-actor/src/input/close.rs b/yazi-actor/src/input/close.rs index 5077cfc2..0c0a8eb5 100644 --- a/yazi-actor/src/input/close.rs +++ b/yazi-actor/src/input/close.rs @@ -13,14 +13,14 @@ impl Actor for Close { const NAME: &str = "close"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let input = &mut cx.input; input.visible = false; input.ticket.next(); if let Some(tx) = input.tx.take() { let value = input.snap().value.clone(); - _ = tx.send(if opt.submit { InputEvent::Submit(value) } else { InputEvent::Cancel(value) }); + _ = tx.send(if form.submit { InputEvent::Submit(value) } else { InputEvent::Cancel(value) }); } act!(cmp:close, cx)?; diff --git a/yazi-actor/src/input/complete.rs b/yazi-actor/src/input/complete.rs index faa9e341..5380618d 100644 --- a/yazi-actor/src/input/complete.rs +++ b/yazi-actor/src/input/complete.rs @@ -12,12 +12,12 @@ impl Actor for Complete { const NAME: &str = "complete"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let input = &mut cx.input; - if !input.visible || input.ticket.current() != opt.ticket { + if !input.visible || input.ticket.current() != form.ticket { succ!(); } - act!(complete, input, opt) + act!(complete, input, form) } } diff --git a/yazi-actor/src/input/show.rs b/yazi-actor/src/input/show.rs index beec471e..9b3ee137 100644 --- a/yazi-actor/src/input/show.rs +++ b/yazi-actor/src/input/show.rs @@ -14,14 +14,14 @@ impl Actor for Show { const NAME: &str = "show"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { act!(input:close, cx)?; let input = &mut cx.input; input.visible = true; - input.title = opt.cfg.title.clone(); - input.position = opt.cfg.position; - *input.deref_mut() = yazi_widgets::input::Input::new(opt)?; + input.title = form.cfg.title.clone(); + input.position = form.cfg.position; + *input.deref_mut() = yazi_widgets::input::Input::new(form)?; succ!(render!()); } diff --git a/yazi-actor/src/mgr/arrow.rs b/yazi-actor/src/mgr/arrow.rs index be7ba2c7..cfcdd272 100644 --- a/yazi-actor/src/mgr/arrow.rs +++ b/yazi-actor/src/mgr/arrow.rs @@ -12,12 +12,15 @@ impl Actor for Arrow { const NAME: &str = "arrow"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let tab = cx.tab_mut(); - if !tab.current.arrow(opt.step) { + if !tab.current.arrow(form.step) { succ!(); } + // Retrace + tab.current.retrace(); + // Visual selection if let Some((start, items)) = tab.mode.visual_mut() { let end = tab.current.cursor; @@ -28,7 +31,7 @@ impl Actor for Arrow { act!(mgr:peek, cx)?; act!(mgr:watch, cx)?; - // cx.tasks.scheduler.batch.next(); // FIXME: clear user action + cx.tasks.scheduler.behavior.reset(); succ!(render!()); } } diff --git a/yazi-actor/src/mgr/bulk_exit.rs b/yazi-actor/src/mgr/bulk_exit.rs index 84dc5dc6..49935d50 100644 --- a/yazi-actor/src/mgr/bulk_exit.rs +++ b/yazi-actor/src/mgr/bulk_exit.rs @@ -12,8 +12,8 @@ impl Actor for BulkExit { const NAME: &str = "bulk_exit"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - cx.mgr.batcher.decide(opt.target, opt.accept); + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + cx.mgr.batcher.decide(form.target, form.accept); succ!(); } } diff --git a/yazi-actor/src/mgr/cd.rs b/yazi-actor/src/mgr/cd.rs index 41e82528..e52a1143 100644 --- a/yazi-actor/src/mgr/cd.rs +++ b/yazi-actor/src/mgr/cd.rs @@ -22,14 +22,14 @@ impl Actor for Cd { const NAME: &str = "cd"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { act!(mgr:escape_visual, cx)?; - if opt.interactive { + if form.interactive { return Self::cd_interactive(cx); } let tab = cx.tab_mut(); - if opt.target == *tab.cwd() { + if form.target == *tab.cwd() { succ!(); } @@ -39,12 +39,12 @@ impl Actor for Cd { } // Current - let rep = tab.history.remove_or(&opt.target); + let rep = tab.history.remove_or(&form.target); let rep = mem::replace(&mut tab.current, rep); tab.history.insert(rep.url.clone(), rep); // Parent - if let Some(parent) = opt.target.parent() { + if let Some(parent) = form.target.parent() { tab.parent = Some(tab.history.remove_or(parent)); } @@ -54,7 +54,7 @@ impl Actor for Cd { act!(mgr:sort, cx).ok(); act!(mgr:hover, cx)?; act!(mgr:refresh, cx)?; - act!(mgr:stash, cx, opt).ok(); + act!(mgr:stash, cx, form).ok(); act!(app:title, cx).ok(); succ!(render!()); } diff --git a/yazi-actor/src/mgr/copy.rs b/yazi-actor/src/mgr/copy.rs index 8d3527f4..f2b06391 100644 --- a/yazi-actor/src/mgr/copy.rs +++ b/yazi-actor/src/mgr/copy.rs @@ -13,11 +13,11 @@ impl Actor for Copy { const NAME: &str = "copy"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { act!(mgr:escape_visual, cx)?; let mut s = Vec::::new(); - let mut it = if opt.hovered { + let mut it = if form.hovered { Box::new(cx.hovered().map(|h| &h.url).into_iter()) } else { cx.tab().selected_or_hovered() @@ -25,23 +25,23 @@ impl Actor for Copy { .peekable(); while let Some(u) = it.next() { - match opt.r#type.as_ref() { + match form.r#type.as_ref() { // TODO: rename to "url" "path" => { - s.extend_from_slice(&opt.separator.transform(&u.to_strand())); + s.extend_from_slice(&form.separator.transform(&u.to_strand())); } "dirname" => { if let Some(p) = u.parent() { - s.extend_from_slice(&opt.separator.transform(&p.to_strand())); + s.extend_from_slice(&form.separator.transform(&p.to_strand())); } } "filename" => { - s.extend_from_slice(&opt.separator.transform(&u.name().unwrap_or_default())); + s.extend_from_slice(&form.separator.transform(&u.name().unwrap_or_default())); } "name_without_ext" => { - s.extend_from_slice(&opt.separator.transform(&u.stem().unwrap_or_default())); + s.extend_from_slice(&form.separator.transform(&u.stem().unwrap_or_default())); } - _ => bail!("Unknown copy type: {}", opt.r#type), + _ => bail!("Unknown copy type: {}", form.r#type), }; if it.peek().is_some() { s.push(b'\n'); @@ -49,8 +49,8 @@ impl Actor for Copy { } // Copy the CWD path regardless even if the directory is empty - if s.is_empty() && opt.r#type == "dirname" { - s.extend_from_slice(&opt.separator.transform(&cx.cwd().to_strand())); + if s.is_empty() && form.r#type == "dirname" { + s.extend_from_slice(&form.separator.transform(&cx.cwd().to_strand())); } futures::executor::block_on(CLIPBOARD.set(s)); diff --git a/yazi-actor/src/mgr/create.rs b/yazi-actor/src/mgr/create.rs index 58654c5e..ce76d537 100644 --- a/yazi-actor/src/mgr/create.rs +++ b/yazi-actor/src/mgr/create.rs @@ -18,9 +18,9 @@ impl Actor for Create { const NAME: &str = "create"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let cwd = cx.cwd().to_owned(); - let mut input = InputProxy::show(InputCfg::create(opt.dir)); + let mut input = InputProxy::show(InputCfg::create(form.dir)); tokio::spawn(async move { let Some(InputEvent::Submit(name)) = input.recv().await else { return }; @@ -32,14 +32,14 @@ impl Actor for Create { return; }; - if !opt.force + if !form.force && maybe_exists(&new).await && !ConfirmProxy::show(ConfirmCfg::overwrite(&new)).await { return; } - _ = Self::r#do(new, opt.dir || name.ends_with('/') || name.ends_with('\\')).await; + _ = Self::r#do(new, form.dir || name.ends_with('/') || name.ends_with('\\')).await; }); succ!(); } diff --git a/yazi-actor/src/mgr/download.rs b/yazi-actor/src/mgr/download.rs index c583f612..ab94dbdb 100644 --- a/yazi-actor/src/mgr/download.rs +++ b/yazi-actor/src/mgr/download.rs @@ -20,15 +20,15 @@ impl Actor for Download { const NAME: &str = "download"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let cwd = cx.cwd().clone(); let scheduler = cx.tasks.scheduler.clone(); tokio::spawn(async move { - Self::prepare(&opt.urls).await; + Self::prepare(&form.urls).await; let mut wg1 = FuturesUnordered::new(); - for url in opt.urls { + for url in form.urls { let done = scheduler.file_download(url.to_owned()); wg1.push(async move { (done.future().await, url) }); } @@ -58,7 +58,7 @@ impl Actor for Download { if futures::future::join_all(wg2).await.into_iter().any(|b| !b) { return; } - if opt.open && !urls.is_empty() { + if form.open && !urls.is_empty() { MgrProxy::open(OpenOpt { cwd: Some(cwd.into()), targets: urls, diff --git a/yazi-actor/src/mgr/escape.rs b/yazi-actor/src/mgr/escape.rs index ea0ab495..85ce7b85 100644 --- a/yazi-actor/src/mgr/escape.rs +++ b/yazi-actor/src/mgr/escape.rs @@ -13,8 +13,8 @@ impl Actor for Escape { const NAME: &str = "escape"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - if opt.is_empty() { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + if form.is_empty() { _ = act!(mgr:escape_find, cx)? != false || act!(mgr:escape_visual, cx)? != false || act!(mgr:escape_filter, cx)? != false @@ -23,19 +23,19 @@ impl Actor for Escape { succ!(); } - if opt.contains(EscapeForm::FIND) { + if form.contains(EscapeForm::FIND) { act!(mgr:escape_find, cx)?; } - if opt.contains(EscapeForm::VISUAL) { + if form.contains(EscapeForm::VISUAL) { act!(mgr:escape_visual, cx)?; } - if opt.contains(EscapeForm::FILTER) { + if form.contains(EscapeForm::FILTER) { act!(mgr:escape_filter, cx)?; } - if opt.contains(EscapeForm::SELECT) { + if form.contains(EscapeForm::SELECT) { act!(mgr:escape_select, cx)?; } - if opt.contains(EscapeForm::SEARCH) { + if form.contains(EscapeForm::SEARCH) { act!(mgr:escape_search, cx)?; } succ!(); diff --git a/yazi-actor/src/mgr/find.rs b/yazi-actor/src/mgr/find.rs index efb567c2..e211a4d1 100644 --- a/yazi-actor/src/mgr/find.rs +++ b/yazi-actor/src/mgr/find.rs @@ -20,15 +20,15 @@ impl Actor for Find { const NAME: &str = "find"; - fn act(_: &mut Ctx, opt: Self::Form) -> Result { - let input = InputProxy::show(InputCfg::find(opt.prev)); + fn act(_: &mut Ctx, form: Self::Form) -> Result { + let input = InputProxy::show(InputCfg::find(form.prev)); tokio::spawn(async move { let rx = Debounce::new(UnboundedReceiverStream::new(input), Duration::from_millis(50)); pin!(rx); while let Some(InputEvent::Submit(s) | InputEvent::Type(s)) = rx.next().await { - MgrProxy::find_do(FindDoOpt { query: s.into(), prev: opt.prev, case: opt.case }); + MgrProxy::find_do(FindDoOpt { query: s.into(), prev: form.prev, case: form.case }); } }); succ!(); diff --git a/yazi-actor/src/mgr/find_arrow.rs b/yazi-actor/src/mgr/find_arrow.rs index 13826762..815567ba 100644 --- a/yazi-actor/src/mgr/find_arrow.rs +++ b/yazi-actor/src/mgr/find_arrow.rs @@ -12,12 +12,12 @@ impl Actor for FindArrow { const NAME: &str = "find_arrow"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let tab = cx.tab_mut(); let Some(finder) = &mut tab.finder else { succ!() }; render!(finder.catchup(&tab.current)); - let offset = if opt.prev { + let offset = if form.prev { finder.prev(&tab.current.files, tab.current.cursor, false) } else { finder.next(&tab.current.files, tab.current.cursor, false) diff --git a/yazi-actor/src/mgr/hardlink.rs b/yazi-actor/src/mgr/hardlink.rs index 48008c8b..cbe5a6c1 100644 --- a/yazi-actor/src/mgr/hardlink.rs +++ b/yazi-actor/src/mgr/hardlink.rs @@ -12,12 +12,12 @@ impl Actor for Hardlink { const NAME: &str = "hardlink"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let mgr = &mut cx.core.mgr; let tab = &mgr.tabs[cx.tab]; if !mgr.yanked.cut { - cx.core.tasks.file_hardlink(&mgr.yanked, tab.cwd(), opt.force, opt.follow); + cx.core.tasks.file_hardlink(&mgr.yanked, tab.cwd(), form.force, form.follow); } succ!(); diff --git a/yazi-actor/src/mgr/hidden.rs b/yazi-actor/src/mgr/hidden.rs index 5ed09ab9..66edccd3 100644 --- a/yazi-actor/src/mgr/hidden.rs +++ b/yazi-actor/src/mgr/hidden.rs @@ -14,8 +14,8 @@ impl Actor for Hidden { const NAME: &str = "hidden"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - let state = opt.state.bool(cx.tab().pref.show_hidden); + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + let state = form.state.bool(cx.tab().pref.show_hidden); cx.tab_mut().pref.show_hidden = state; let hovered = cx.hovered().map(|f| f.urn().to_owned()); diff --git a/yazi-actor/src/mgr/hover.rs b/yazi-actor/src/mgr/hover.rs index add8ce89..ecfab58f 100644 --- a/yazi-actor/src/mgr/hover.rs +++ b/yazi-actor/src/mgr/hover.rs @@ -13,7 +13,7 @@ impl Actor for Hover { const NAME: &str = "hover"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let tab = tab!(cx); // Parent should always track CWD @@ -22,16 +22,16 @@ impl Actor for Hover { } // Repos CWD - render!(tab.current.repos(opt.urn.as_ref().map(Into::into))); + render!(tab.current.repos(form.urn.as_ref().map(Into::into))); // Turn on tracing - if let (Some(h), Some(u)) = (tab.hovered(), opt.urn) + if let (Some(h), Some(u)) = (tab.hovered(), form.urn) && h.urn() == u { // `hover(Some)` occurs after user actions, such as create, rename, reveal, etc. // At this point, it's intuitive to track the file location regardless. tab.current.trace = Some(u.clone()); - // cx.tasks.scheduler.batch.next();// FIXME: clear user action + cx.tasks.scheduler.behavior.reset(); } // Publish through DDS diff --git a/yazi-actor/src/mgr/linemode.rs b/yazi-actor/src/mgr/linemode.rs index 0bbf7222..e78635f8 100644 --- a/yazi-actor/src/mgr/linemode.rs +++ b/yazi-actor/src/mgr/linemode.rs @@ -12,11 +12,11 @@ impl Actor for Linemode { const NAME: &str = "linemode"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let tab = cx.tab_mut(); - if opt.new != tab.pref.linemode { - tab.pref.linemode = opt.new.into_owned(); + if form.new != tab.pref.linemode { + tab.pref.linemode = form.new.into_owned(); render!(); } diff --git a/yazi-actor/src/mgr/link.rs b/yazi-actor/src/mgr/link.rs index 1e304cf3..49df7c29 100644 --- a/yazi-actor/src/mgr/link.rs +++ b/yazi-actor/src/mgr/link.rs @@ -12,12 +12,12 @@ impl Actor for Link { const NAME: &str = "link"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let mgr = &mut cx.core.mgr; let tab = &mgr.tabs[cx.tab]; if !mgr.yanked.cut { - cx.core.tasks.file_link(&mgr.yanked, tab.cwd(), opt.relative, opt.force); + cx.core.tasks.file_link(&mgr.yanked, tab.cwd(), form.relative, form.force); } succ!(); diff --git a/yazi-actor/src/mgr/paste.rs b/yazi-actor/src/mgr/paste.rs index 92d4d7ea..b030474a 100644 --- a/yazi-actor/src/mgr/paste.rs +++ b/yazi-actor/src/mgr/paste.rs @@ -12,18 +12,18 @@ impl Actor for Paste { const NAME: &str = "paste"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let mgr = &mut cx.core.mgr; let tab = &mgr.tabs[cx.tab]; let dest = tab.cwd(); if mgr.yanked.cut { - cx.core.tasks.file_cut(&mgr.yanked, dest, opt.force); + cx.core.tasks.file_cut(&mgr.yanked, dest, form.force); mgr.tabs.iter_mut().for_each(|t| _ = t.selected.remove_many(&*mgr.yanked)); act!(mgr:unyank, cx) } else { - succ!(cx.core.tasks.file_copy(&mgr.yanked, dest, opt.force, opt.follow)); + succ!(cx.core.tasks.file_copy(&mgr.yanked, dest, form.force, form.follow)); } } } diff --git a/yazi-actor/src/mgr/peek.rs b/yazi-actor/src/mgr/peek.rs index bbcfa6bc..c1d41d28 100644 --- a/yazi-actor/src/mgr/peek.rs +++ b/yazi-actor/src/mgr/peek.rs @@ -12,7 +12,7 @@ impl Actor for Peek { const NAME: &str = "peek"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let Some(hovered) = cx.hovered().cloned() else { succ!(cx.tab_mut().preview.reset()); }; @@ -33,13 +33,13 @@ impl Actor for Peek { cx.tab_mut().preview.folder_lock = None; } - if matches!(opt.only_if, Some(u) if u != hovered.url) { + if matches!(form.only_if, Some(u) if u != hovered.url) { succ!(); } - if let Some(skip) = opt.skip { + if let Some(skip) = form.skip { let preview = &mut cx.tab_mut().preview; - if opt.upper_bound { + if form.upper_bound { preview.skip = preview.skip.min(skip); } else { preview.skip = skip; @@ -47,9 +47,9 @@ impl Actor for Peek { } if hovered.is_dir() { - cx.tab_mut().preview.go_folder(hovered, folder.map(|(_, cha)| cha), mime, opt.force); + cx.tab_mut().preview.go_folder(hovered, folder.map(|(_, cha)| cha), mime, form.force); } else { - cx.tab_mut().preview.go(hovered, mime, opt.force); + cx.tab_mut().preview.go(hovered, mime, form.force); } succ!(); } diff --git a/yazi-actor/src/mgr/quit.rs b/yazi-actor/src/mgr/quit.rs index 43f8dcd2..ff56727d 100644 --- a/yazi-actor/src/mgr/quit.rs +++ b/yazi-actor/src/mgr/quit.rs @@ -58,7 +58,7 @@ impl Actor for Quit { succ!(); } - fn hook(cx: &Ctx, _opt: &Self::Form) -> Option { + fn hook(cx: &Ctx, _form: &Self::Form) -> Option { Some(SparkKind::KeyQuit).filter(|_| cx.source().is_key()) } } diff --git a/yazi-actor/src/mgr/remove.rs b/yazi-actor/src/mgr/remove.rs index b62f7dbd..5d771591 100644 --- a/yazi-actor/src/mgr/remove.rs +++ b/yazi-actor/src/mgr/remove.rs @@ -14,30 +14,30 @@ impl Actor for Remove { const NAME: &str = "remove"; - fn act(cx: &mut Ctx, mut opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, mut form: Self::Form) -> Result { act!(mgr:escape_visual, cx)?; - opt.targets = if opt.hovered { + form.targets = if form.hovered { cx.hovered().map_or(vec![], |h| vec![h.url.clone()]) } else { cx.tab().selected_or_hovered().cloned().collect() }; - if opt.targets.is_empty() { + if form.targets.is_empty() { succ!(); - } else if opt.force { - return act!(mgr:remove_do, cx, opt); + } else if form.force { + return act!(mgr:remove_do, cx, form); } - let confirm = ConfirmProxy::show(if opt.permanently { - ConfirmCfg::delete(&opt.targets) + let confirm = ConfirmProxy::show(if form.permanently { + ConfirmCfg::delete(&form.targets) } else { - ConfirmCfg::trash(&opt.targets) + ConfirmCfg::trash(&form.targets) }); tokio::spawn(async move { if confirm.await { - MgrProxy::remove_do(opt.targets, opt.permanently); + MgrProxy::remove_do(form.targets, form.permanently); } }); succ!(); @@ -52,17 +52,17 @@ impl Actor for RemoveDo { const NAME: &str = "remove_do"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let mgr = &mut cx.mgr; mgr.tabs.iter_mut().for_each(|t| { - t.selected.remove_many(&opt.targets); + t.selected.remove_many(&form.targets); }); - mgr.yanked.remove_many(&opt.targets); + mgr.yanked.remove_many(&form.targets); mgr.yanked.catchup_revision(false); - cx.tasks.file_remove(opt.targets, opt.permanently); + cx.tasks.file_remove(form.targets, form.permanently); succ!(); } } diff --git a/yazi-actor/src/mgr/rename.rs b/yazi-actor/src/mgr/rename.rs index a91e5552..53c612c6 100644 --- a/yazi-actor/src/mgr/rename.rs +++ b/yazi-actor/src/mgr/rename.rs @@ -19,17 +19,17 @@ impl Actor for Rename { const NAME: &str = "rename"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { act!(mgr:escape_visual, cx)?; - if !opt.hovered && !cx.tab().selected.is_empty() { + if !form.hovered && !cx.tab().selected.is_empty() { return act!(mgr:bulk_rename, cx); } let Some(hovered) = cx.hovered() else { succ!() }; - let name = Self::empty_url_part(&hovered.url, &opt.empty); - let cursor = match opt.cursor.as_ref() { + let name = Self::empty_url_part(&hovered.url, &form.empty); + let cursor = match form.cursor.as_ref() { "start" => Some(0), "before_ext" => name .chars() @@ -54,7 +54,7 @@ impl Actor for Rename { return; }; - if opt.force || !maybe_exists(&new).await || provider::must_identical(&old, &new).await { + if form.force || !maybe_exists(&new).await || provider::must_identical(&old, &new).await { Self::r#do(tab, old, new).await.ok(); } else if ConfirmProxy::show(ConfirmCfg::overwrite(&new)).await { Self::r#do(tab, old, new).await.ok(); diff --git a/yazi-actor/src/mgr/reveal.rs b/yazi-actor/src/mgr/reveal.rs index 35a3bf4f..bc83fdfd 100644 --- a/yazi-actor/src/mgr/reveal.rs +++ b/yazi-actor/src/mgr/reveal.rs @@ -13,11 +13,11 @@ impl Actor for Reveal { const NAME: &str = "reveal"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - let Some((parent, child)) = opt.target.pair() else { succ!() }; + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + let Some((parent, child)) = form.target.pair() else { succ!() }; // Cd to the parent directory - act!(mgr:cd, cx, (parent, opt.source))?; + act!(mgr:cd, cx, (parent, form.source))?; // Try to hover over the child file let tab = cx.tab_mut(); @@ -25,8 +25,8 @@ impl Actor for Reveal { // If the child is not hovered, which means it doesn't exist, // create a dummy file - if !opt.no_dummy && tab.hovered().is_none_or(|f| child != f.urn()) { - let op = FilesOp::Creating(parent.into(), vec![File::from_dummy(&opt.target, None)]); + if !form.no_dummy && tab.hovered().is_none_or(|f| child != f.urn()) { + let op = FilesOp::Creating(parent.into(), vec![File::from_dummy(&form.target, None)]); tab.current.update_pub(tab.id, op); } diff --git a/yazi-actor/src/mgr/seek.rs b/yazi-actor/src/mgr/seek.rs index f5cddbf1..3aab0b02 100644 --- a/yazi-actor/src/mgr/seek.rs +++ b/yazi-actor/src/mgr/seek.rs @@ -15,7 +15,7 @@ impl Actor for Seek { const NAME: &str = "seek"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let Some(hovered) = cx.hovered() else { succ!(cx.tab_mut().preview.reset()); }; @@ -28,7 +28,7 @@ impl Actor for Seek { succ!(cx.tab_mut().preview.reset()); }; - let job = SeekJob { file: hovered.clone(), units: opt.units }; + let job = SeekJob { file: hovered.clone(), units: form.units }; let opt = PluginOpt::new_callback(&*previewer.run.name, move |_, plugin| { plugin.call_method("seek", job) }); diff --git a/yazi-actor/src/mgr/shell.rs b/yazi-actor/src/mgr/shell.rs index 30900820..eb4a02c6 100644 --- a/yazi-actor/src/mgr/shell.rs +++ b/yazi-actor/src/mgr/shell.rs @@ -18,33 +18,33 @@ impl Actor for Shell { const NAME: &str = "shell"; - fn act(cx: &mut Ctx, mut opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, mut form: Self::Form) -> Result { act!(mgr:escape_visual, cx)?; - let cwd = opt.cwd.take().unwrap_or(cx.cwd().into()).into_owned(); + let cwd = form.cwd.take().unwrap_or(cx.cwd().into()).into_owned(); let selected: Vec<_> = cx.tab().hovered_and_selected().cloned().map(Into::into).collect(); - let input = opt.interactive.then(|| { - InputProxy::show(InputCfg::shell(opt.block).with_value(&*opt.run).with_cursor(opt.cursor)) + let input = form.interactive.then(|| { + InputProxy::show(InputCfg::shell(form.block).with_value(&*form.run).with_cursor(form.cursor)) }); tokio::spawn(async move { if let Some(mut rx) = input { match rx.recv().await { - Some(InputEvent::Submit(e)) => opt.run = Cow::Owned(e), + Some(InputEvent::Submit(e)) => form.run = Cow::Owned(e), _ => return, } } - if opt.run.is_empty() { + if form.run.is_empty() { return; } TasksProxy::open_shell_compat(ProcessOpt { cwd: cwd.into(), - cmd: opt.run.to_string().into(), + cmd: form.run.to_string().into(), args: selected, - block: opt.block, - orphan: opt.orphan, + block: form.block, + orphan: form.orphan, spread: true, }); }); diff --git a/yazi-actor/src/mgr/sort.rs b/yazi-actor/src/mgr/sort.rs index d4e28374..3e99eef7 100644 --- a/yazi-actor/src/mgr/sort.rs +++ b/yazi-actor/src/mgr/sort.rs @@ -14,14 +14,14 @@ impl Actor for Sort { const NAME: &str = "sort"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let pref = &mut cx.tab_mut().pref; - pref.sort_by = opt.by.unwrap_or(pref.sort_by); - pref.sort_reverse = opt.reverse.unwrap_or(pref.sort_reverse); - pref.sort_dir_first = opt.dir_first.unwrap_or(pref.sort_dir_first); - pref.sort_sensitive = opt.sensitive.unwrap_or(pref.sort_sensitive); - pref.sort_translit = opt.translit.unwrap_or(pref.sort_translit); - pref.sort_fallback = opt.fallback.unwrap_or(pref.sort_fallback); + pref.sort_by = form.by.unwrap_or(pref.sort_by); + pref.sort_reverse = form.reverse.unwrap_or(pref.sort_reverse); + pref.sort_dir_first = form.dir_first.unwrap_or(pref.sort_dir_first); + pref.sort_sensitive = form.sensitive.unwrap_or(pref.sort_sensitive); + pref.sort_translit = form.translit.unwrap_or(pref.sort_translit); + pref.sort_fallback = form.fallback.unwrap_or(pref.sort_fallback); let sorter = FilesSorter::from(&*pref); let hovered = cx.hovered().map(|f| f.urn().to_owned()); diff --git a/yazi-actor/src/mgr/spot.rs b/yazi-actor/src/mgr/spot.rs index 61271f46..fe745d4d 100644 --- a/yazi-actor/src/mgr/spot.rs +++ b/yazi-actor/src/mgr/spot.rs @@ -12,7 +12,7 @@ impl Actor for Spot { const NAME: &str = "spot"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { act!(mgr:escape_visual, cx)?; let Some(hovered) = cx.hovered().cloned() else { succ!() }; @@ -26,7 +26,7 @@ impl Actor for Spot { // self.active_mut().spot.reset(); // } - if let Some(skip) = opt.skip { + if let Some(skip) = form.skip { cx.tab_mut().spot.skip = skip; } else if !cx.tab().spot.same_url(&hovered.url) { cx.tab_mut().spot.skip = 0; diff --git a/yazi-actor/src/mgr/stash.rs b/yazi-actor/src/mgr/stash.rs index 3de22742..89b68a7f 100644 --- a/yazi-actor/src/mgr/stash.rs +++ b/yazi-actor/src/mgr/stash.rs @@ -12,15 +12,15 @@ impl Actor for Stash { const NAME: &str = "stash"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - if opt.target.is_absolute() && opt.target.is_internal() { - cx.tab_mut().backstack.push(opt.target.as_url()); + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + if form.target.is_absolute() && form.target.is_internal() { + cx.tab_mut().backstack.push(form.target.as_url()); } succ!() } - fn hook(cx: &Ctx, _opt: &Self::Form) -> Option { + fn hook(cx: &Ctx, _form: &Self::Form) -> Option { match cx.source() { Source::Ind => Some(SparkKind::IndStash), Source::Relay => Some(SparkKind::RelayStash), diff --git a/yazi-actor/src/mgr/tab_close.rs b/yazi-actor/src/mgr/tab_close.rs index cc4ad9d9..7da8d460 100644 --- a/yazi-actor/src/mgr/tab_close.rs +++ b/yazi-actor/src/mgr/tab_close.rs @@ -12,16 +12,16 @@ impl Actor for TabClose { const NAME: &str = "tab_close"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let len = cx.tabs().len(); - if len < 2 || opt.idx >= len { + if len < 2 || form.idx >= len { succ!(); } let tabs = cx.tabs_mut(); - tabs.remove(opt.idx).shutdown(); + tabs.remove(form.idx).shutdown(); - if opt.idx > tabs.cursor { + if form.idx > tabs.cursor { tabs.set_idx(tabs.cursor); } else { tabs.set_idx(usize::min(tabs.cursor + 1, tabs.len() - 1)); diff --git a/yazi-actor/src/mgr/tab_create.rs b/yazi-actor/src/mgr/tab_create.rs index 1d807170..349578c3 100644 --- a/yazi-actor/src/mgr/tab_create.rs +++ b/yazi-actor/src/mgr/tab_create.rs @@ -16,7 +16,7 @@ impl Actor for TabCreate { const NAME: &str = "tab_create"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { if cx.tabs().len() >= MAX_TABS { succ!(NotifyProxy::push_warn( "Too many tabs", @@ -25,7 +25,7 @@ impl Actor for TabCreate { } let mut tab = Tab::default(); - let (cd, url) = if let Some(wd) = opt.url { + let (cd, url) = if let Some(wd) = form.url { (true, wd.into_owned()) } else if let Some(h) = cx.hovered() { tab.pref = cx.tab().pref.clone(); diff --git a/yazi-actor/src/mgr/tab_rename.rs b/yazi-actor/src/mgr/tab_rename.rs index d2a32e56..38540915 100644 --- a/yazi-actor/src/mgr/tab_rename.rs +++ b/yazi-actor/src/mgr/tab_rename.rs @@ -17,18 +17,18 @@ impl Actor for TabRename { const NAME: &str = "tab_rename"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let tab = cx.tab().id; let pref = &mut cx.tab_mut().pref; - if !opt.interactive { - pref.name = opt.name.unwrap_or_default().into_owned(); + if !form.interactive { + pref.name = form.name.unwrap_or_default().into_owned(); act!(app:title, cx).ok(); succ!(render!()); } let mut input = InputProxy::show( - InputCfg::tab_rename().with_value(opt.name.unwrap_or(Cow::Borrowed(&pref.name))), + InputCfg::tab_rename().with_value(form.name.unwrap_or(Cow::Borrowed(&pref.name))), ); tokio::spawn(async move { if let Some(InputEvent::Submit(name)) = input.recv().await { diff --git a/yazi-actor/src/mgr/tab_swap.rs b/yazi-actor/src/mgr/tab_swap.rs index 73df8bc7..f2a37e81 100644 --- a/yazi-actor/src/mgr/tab_swap.rs +++ b/yazi-actor/src/mgr/tab_swap.rs @@ -13,10 +13,10 @@ impl Actor for TabSwap { const NAME: &str = "tab_swap"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let tabs = cx.tabs_mut(); - let new = opt.step.add(tabs.cursor, tabs.len(), 0); + let new = form.step.add(tabs.cursor, tabs.len(), 0); if new == tabs.cursor { succ!(); } diff --git a/yazi-actor/src/mgr/tab_switch.rs b/yazi-actor/src/mgr/tab_switch.rs index 9230b727..28ea84e6 100644 --- a/yazi-actor/src/mgr/tab_switch.rs +++ b/yazi-actor/src/mgr/tab_switch.rs @@ -12,12 +12,12 @@ impl Actor for TabSwitch { const NAME: &str = "tab_switch"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let tabs = cx.tabs_mut(); - let idx = if opt.relative { - opt.step.saturating_add_unsigned(tabs.cursor).rem_euclid(tabs.len() as _) as _ + let idx = if form.relative { + form.step.saturating_add_unsigned(tabs.cursor).rem_euclid(tabs.len() as _) as _ } else { - opt.step as usize + form.step as usize }; if idx == tabs.cursor || idx >= tabs.len() { diff --git a/yazi-actor/src/mgr/toggle.rs b/yazi-actor/src/mgr/toggle.rs index ec08d508..59f7a455 100644 --- a/yazi-actor/src/mgr/toggle.rs +++ b/yazi-actor/src/mgr/toggle.rs @@ -13,13 +13,13 @@ impl Actor for Toggle { const NAME: &str = "toggle"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let tab = cx.tab_mut(); - let Some(url) = opt.url.or(tab.current.hovered().map(|h| UrlCow::from(&h.url))) else { + let Some(url) = form.url.or(tab.current.hovered().map(|h| UrlCow::from(&h.url))) else { succ!(); }; - let b = match opt.state { + let b = match form.state { Some(true) => render_and!(tab.selected.add(&url)), Some(false) => render_and!(tab.selected.remove(&url)) | true, None => render_and!(tab.selected.remove(&url) || tab.selected.add(&url)), diff --git a/yazi-actor/src/mgr/toggle_all.rs b/yazi-actor/src/mgr/toggle_all.rs index 239f7003..1364abe5 100644 --- a/yazi-actor/src/mgr/toggle_all.rs +++ b/yazi-actor/src/mgr/toggle_all.rs @@ -13,18 +13,18 @@ impl Actor for ToggleAll { const NAME: &str = "toggle_all"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { use either::Either::*; let tab = cx.tab_mut(); let it = tab.current.files.iter().map(|f| &f.url); - let either = match opt.state { - Some(true) if opt.urls.is_empty() => Left((vec![], it.collect())), - Some(true) => Right((vec![], opt.urls)), - Some(false) if opt.urls.is_empty() => Left((it.collect(), vec![])), - Some(false) => Right((opt.urls, vec![])), - None if opt.urls.is_empty() => Left(it.partition(|&u| tab.selected.contains(u))), - None => Right(opt.urls.into_iter().partition(|u| tab.selected.contains(u))), + let either = match form.state { + Some(true) if form.urls.is_empty() => Left((vec![], it.collect())), + Some(true) => Right((vec![], form.urls)), + Some(false) if form.urls.is_empty() => Left((it.collect(), vec![])), + Some(false) => Right((form.urls, vec![])), + None if form.urls.is_empty() => Left(it.partition(|&u| tab.selected.contains(u))), + None => Right(form.urls.into_iter().partition(|u| tab.selected.contains(u))), }; let warn = match either { diff --git a/yazi-actor/src/mgr/update_files.rs b/yazi-actor/src/mgr/update_files.rs index f4918eef..d710f1aa 100644 --- a/yazi-actor/src/mgr/update_files.rs +++ b/yazi-actor/src/mgr/update_files.rs @@ -15,11 +15,11 @@ impl Actor for UpdateFiles { const NAME: &str = "update_files"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let revision = cx.current().files.revision; - let linked: Vec<_> = LINKED.read().from_dir(opt.op.cwd()).map(|u| opt.op.chdir(u)).collect(); + let linked: Vec<_> = LINKED.read().from_dir(form.op.cwd()).map(|u| form.op.chdir(u)).collect(); - for op in [opt.op].into_iter().chain(linked) { + for op in [form.op].into_iter().chain(linked) { cx.mgr.yanked.apply_op(&op); Self::update_tab(cx, op).ok(); } diff --git a/yazi-actor/src/mgr/update_mimes.rs b/yazi-actor/src/mgr/update_mimes.rs index abda4e1b..92857478 100644 --- a/yazi-actor/src/mgr/update_mimes.rs +++ b/yazi-actor/src/mgr/update_mimes.rs @@ -14,9 +14,9 @@ impl Actor for UpdateMimes { const NAME: &str = "update_mimes"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let linked = LINKED.read(); - let updates = opt + let updates = form .updates .into_iter() .filter(|(url, mime)| cx.mgr.mimetype.get(url) != Some(mime)) diff --git a/yazi-actor/src/mgr/update_paged.rs b/yazi-actor/src/mgr/update_paged.rs index adff2853..a740782e 100644 --- a/yazi-actor/src/mgr/update_paged.rs +++ b/yazi-actor/src/mgr/update_paged.rs @@ -12,12 +12,12 @@ impl Actor for UpdatePaged { const NAME: &str = "update_paged"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - if opt.only_if.is_some_and(|u| u != *cx.cwd()) { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + if form.only_if.is_some_and(|u| u != *cx.cwd()) { succ!(); } - let targets = cx.current().paginate(opt.page.unwrap_or(cx.current().page)); + let targets = cx.current().paginate(form.page.unwrap_or(cx.current().page)); if !targets.is_empty() { cx.tasks.fetch_paged(targets, &cx.mgr.mimetype); cx.tasks.preload_paged(targets, &cx.mgr.mimetype); diff --git a/yazi-actor/src/mgr/update_yanked.rs b/yazi-actor/src/mgr/update_yanked.rs index d2485d46..60a0148a 100644 --- a/yazi-actor/src/mgr/update_yanked.rs +++ b/yazi-actor/src/mgr/update_yanked.rs @@ -13,12 +13,12 @@ impl Actor for UpdateYanked { const NAME: &str = "update_yanked"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - if opt.urls.is_empty() && cx.mgr.yanked.is_empty() { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + if form.urls.is_empty() && cx.mgr.yanked.is_empty() { succ!(); } - cx.mgr.yanked = Yanked::new(opt.cut, opt.0.urls.into_owned()); + cx.mgr.yanked = Yanked::new(form.cut, form.0.urls.into_owned()); succ!(render!()); } } diff --git a/yazi-actor/src/mgr/upload.rs b/yazi-actor/src/mgr/upload.rs index 93cd8fd5..d44fe224 100644 --- a/yazi-actor/src/mgr/upload.rs +++ b/yazi-actor/src/mgr/upload.rs @@ -12,8 +12,8 @@ impl Actor for Upload { const NAME: &str = "upload"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - for url in opt.urls { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + for url in form.urls { cx.tasks.scheduler.file_upload(url.into_owned()); } succ!(); diff --git a/yazi-actor/src/mgr/visual_mode.rs b/yazi-actor/src/mgr/visual_mode.rs index e30a4b65..0fe8a524 100644 --- a/yazi-actor/src/mgr/visual_mode.rs +++ b/yazi-actor/src/mgr/visual_mode.rs @@ -15,11 +15,11 @@ impl Actor for VisualMode { const NAME: &str = "visual_mode"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let tab = cx.tab_mut(); let idx = tab.current.cursor; - if opt.unset { + if form.unset { tab.mode = Mode::Unset(idx, BTreeSet::from([idx])); } else { tab.mode = Mode::Select(idx, BTreeSet::from([idx])); diff --git a/yazi-actor/src/mgr/yank.rs b/yazi-actor/src/mgr/yank.rs index 21c9ca1e..99ac6a6b 100644 --- a/yazi-actor/src/mgr/yank.rs +++ b/yazi-actor/src/mgr/yank.rs @@ -13,11 +13,11 @@ impl Actor for Yank { const NAME: &str = "yank"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { act!(mgr:escape_visual, cx)?; cx.mgr.yanked = - Yanked::new(opt.cut, cx.tab().selected_or_hovered().cloned().map(UrlBufCov).collect()); + Yanked::new(form.cut, cx.tab().selected_or_hovered().cloned().map(UrlBufCov).collect()); render!(cx.mgr.yanked.catchup_revision(true)); act!(mgr:escape_select, cx) diff --git a/yazi-actor/src/notify/tick.rs b/yazi-actor/src/notify/tick.rs index 950555c2..1fa64854 100644 --- a/yazi-actor/src/notify/tick.rs +++ b/yazi-actor/src/notify/tick.rs @@ -18,7 +18,7 @@ impl Actor for Tick { const NAME: &str = "tick"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { cx.notify.ticker.take().map(|h| h.abort()); let Dimension { rows, columns, .. } = Dimension::available(); @@ -35,7 +35,7 @@ impl Actor for Tick { } else if m.percent < 100 { m.percent += 20; } else { - m.timeout = m.timeout.saturating_sub(opt.interval); + m.timeout = m.timeout.saturating_sub(form.interval); } } diff --git a/yazi-actor/src/pick/arrow.rs b/yazi-actor/src/pick/arrow.rs index bb88b165..54000660 100644 --- a/yazi-actor/src/pick/arrow.rs +++ b/yazi-actor/src/pick/arrow.rs @@ -13,7 +13,7 @@ impl Actor for Arrow { const NAME: &str = "arrow"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - succ!(render!(cx.pick.scroll(opt.step))); + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + succ!(render!(cx.pick.scroll(form.step))); } } diff --git a/yazi-actor/src/pick/close.rs b/yazi-actor/src/pick/close.rs index 7c02a0e0..e426bfd0 100644 --- a/yazi-actor/src/pick/close.rs +++ b/yazi-actor/src/pick/close.rs @@ -12,10 +12,10 @@ impl Actor for Close { const NAME: &str = "close"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let pick = &mut cx.pick; if let Some(cb) = pick.callback.take() { - _ = cb.send(if opt.submit { Some(pick.cursor) } else { None }); + _ = cb.send(if form.submit { Some(pick.cursor) } else { None }); } pick.cursor = 0; diff --git a/yazi-actor/src/pick/show.rs b/yazi-actor/src/pick/show.rs index b509acbf..d028ac91 100644 --- a/yazi-actor/src/pick/show.rs +++ b/yazi-actor/src/pick/show.rs @@ -12,15 +12,15 @@ impl Actor for Show { const NAME: &str = "show"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { act!(pick:close, cx)?; let pick = &mut cx.pick; - pick.title = opt.cfg.title; - pick.items = opt.cfg.items; - pick.position = opt.cfg.position; + pick.title = form.cfg.title; + pick.items = form.cfg.items; + pick.position = form.cfg.position; - pick.callback = Some(opt.tx); + pick.callback = Some(form.tx); pick.visible = true; succ!(render!()); } diff --git a/yazi-actor/src/spot/arrow.rs b/yazi-actor/src/spot/arrow.rs index e1eb0b51..d7f85903 100644 --- a/yazi-actor/src/spot/arrow.rs +++ b/yazi-actor/src/spot/arrow.rs @@ -12,11 +12,11 @@ impl Actor for Arrow { const NAME: &str = "arrow"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let spot = &mut cx.tab_mut().spot; let Some(lock) = &mut spot.lock else { succ!() }; - let new = opt.step.add(spot.skip, lock.len().unwrap_or(u16::MAX as _), 0); + let new = form.step.add(spot.skip, lock.len().unwrap_or(u16::MAX as _), 0); let Some(old) = lock.selected() else { return act!(mgr:spot, cx, new); }; diff --git a/yazi-actor/src/spot/copy.rs b/yazi-actor/src/spot/copy.rs index c04294b7..ca6e69eb 100644 --- a/yazi-actor/src/spot/copy.rs +++ b/yazi-actor/src/spot/copy.rs @@ -13,13 +13,13 @@ impl Actor for Copy { const NAME: &str = "copy"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let spot = &cx.tab().spot; let Some(lock) = &spot.lock else { succ!() }; let Some(table) = lock.table() else { succ!() }; let mut s = String::new(); - match opt.r#type.as_ref() { + match form.r#type.as_ref() { "cell" => { let Some(cell) = table.selected_cell() else { succ!() }; s = cell.to_string(); diff --git a/yazi-actor/src/spot/swipe.rs b/yazi-actor/src/spot/swipe.rs index 5bf195cf..c4fec09e 100644 --- a/yazi-actor/src/spot/swipe.rs +++ b/yazi-actor/src/spot/swipe.rs @@ -12,8 +12,8 @@ impl Actor for Swipe { const NAME: &str = "swipe"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - act!(mgr:arrow, cx, opt)?; + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + act!(mgr:arrow, cx, form)?; act!(mgr:spot, cx) } } diff --git a/yazi-actor/src/tasks/arrow.rs b/yazi-actor/src/tasks/arrow.rs index 6687ced3..ebcf200e 100644 --- a/yazi-actor/src/tasks/arrow.rs +++ b/yazi-actor/src/tasks/arrow.rs @@ -13,11 +13,11 @@ impl Actor for Arrow { const NAME: &str = "arrow"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { let tasks = &mut cx.tasks; let old = tasks.cursor; - tasks.cursor = opt.step.add(tasks.cursor, tasks.snaps.len(), Tasks::limit()); + tasks.cursor = form.step.add(tasks.cursor, tasks.snaps.len(), Tasks::limit()); succ!(render!(tasks.cursor != old)); } diff --git a/yazi-actor/src/tasks/update_succeed.rs b/yazi-actor/src/tasks/update_succeed.rs index 2bd31d43..0b286951 100644 --- a/yazi-actor/src/tasks/update_succeed.rs +++ b/yazi-actor/src/tasks/update_succeed.rs @@ -1,7 +1,7 @@ use anyhow::Result; -use yazi_macro::succ; +use yazi_macro::{act, succ}; use yazi_parser::tasks::UpdateSucceedForm; -use yazi_shared::data::Data; +use yazi_shared::{data::Data, url::UrlLike}; use crate::{Actor, Ctx}; @@ -12,23 +12,21 @@ impl Actor for UpdateSucceed { const NAME: &str = "update_succeed"; - fn act(cx: &mut Ctx, opt: Self::Form) -> Result { - if opt.urls.is_empty() { + fn act(cx: &mut Ctx, form: Self::Form) -> Result { + if form.urls.is_empty() { succ!(); } - // FIXME: todo!(); - // if opt.track - // && opt.batch == cx.tasks.scheduler.batch.current() - // && let Some((parent, urn)) = opt.urls[0].pair() - // && parent == *cx.cwd() - // { - // cx.tasks.scheduler.batch.next(); - // cx.current_mut().trace = Some(urn.into()); - // act!(mgr:hover, cx)?; - // } + if form.track + && form.id == cx.tasks.scheduler.behavior.first_id() + && let Some((parent, urn)) = form.urls[0].pair() + && parent == *cx.cwd() + { + cx.current_mut().trace = Some(urn.into()); + act!(mgr:hover, cx)?; + } - cx.mgr.watcher.report(opt.urls); + cx.mgr.watcher.report(form.urls); succ!(); } } diff --git a/yazi-actor/src/which/activate.rs b/yazi-actor/src/which/activate.rs index 4cf42b3d..cd6f8f05 100644 --- a/yazi-actor/src/which/activate.rs +++ b/yazi-actor/src/which/activate.rs @@ -31,7 +31,7 @@ impl Actor for Activate { succ!(render!()); } - fn hook(cx: &Ctx, _opt: &Self::Form) -> Option { + fn hook(cx: &Ctx, _form: &Self::Form) -> Option { match cx.source() { Source::Unknown => Some(SparkKind::IndWhichActivate), _ => None, diff --git a/yazi-core/src/tab/folder.rs b/yazi-core/src/tab/folder.rs index b6c402a3..6f2acea0 100644 --- a/yazi-core/src/tab/folder.rs +++ b/yazi-core/src/tab/folder.rs @@ -63,6 +63,7 @@ impl Folder { _ => {} } + let mut deleted = vec![]; match op { FilesOp::Full(_, files, _) => self.files.update_full(files), FilesOp::Part(_, files, ticket) => self.files.update_part(files, ticket), @@ -71,16 +72,13 @@ impl Folder { FilesOp::IOErr(..) => self.files.update_ioerr(), FilesOp::Creating(_, files) => self.files.update_creating(files), - FilesOp::Deleting(_, urns) => { - let deleted = self.files.update_deleting(urns); - let delta = deleted.into_iter().filter(|&i| i < self.cursor).count() as isize; - self.arrow(-delta); - } + FilesOp::Deleting(_, urns) => deleted = self.files.update_deleting(urns), FilesOp::Updating(_, files) => _ = self.files.update_updating(files), FilesOp::Upserting(_, files) => self.files.update_upserting(files), - } + }; self.trace.take_if(|_| self.files.is_empty() && !self.stage.is_loading()); + self.arrow(-(deleted.into_iter().filter(|&i| i < self.cursor).count() as isize)); self.repos(None); (&stage, revision) != (&self.stage, self.files.revision) @@ -101,9 +99,7 @@ impl Folder { self.scroll(step) }; - self.trace = self.hovered().filter(|_| b).map(|h| h.urn().into()).or(self.trace.take()); b |= self.squeeze_offset(); - self.sync_page(false); b } @@ -114,19 +110,28 @@ impl Folder { } let new = self.files.position(urn).unwrap_or(self.cursor) as isize; - self.arrow(new - self.cursor as isize) + let b = self.arrow(new - self.cursor as isize); + + self.retrace(); + b } pub fn repos(&mut self, urn: Option) -> bool { if let Some(u) = urn { self.hover(u) - } else if let Some(u) = &self.trace { - self.hover(u.clone().as_path()) + } else if let Some(u) = self.trace.take() { + let b = self.hover(u.as_path()); + self.trace = Some(u); + b } else { self.arrow(0) } } + pub fn retrace(&mut self) { + self.trace = self.hovered().map(|h| h.urn().into()).or(self.trace.take()); + } + pub fn sync_page(&mut self, force: bool) { let limit = LAYOUT.get().folder_limit(); if limit == 0 { diff --git a/yazi-core/src/tasks/file.rs b/yazi-core/src/tasks/file.rs index e6f6bcb8..a737e4d3 100644 --- a/yazi-core/src/tasks/file.rs +++ b/yazi-core/src/tasks/file.rs @@ -7,6 +7,8 @@ use crate::mgr::Yanked; impl Tasks { pub fn file_cut(&self, src: &Yanked, dest: &UrlBuf, force: bool) { + self.scheduler.behavior.reset(); + for u in src.iter() { let Some(Ok(to)) = u.name().map(|n| dest.try_join(n)) else { debug!("file_cut: cannot join {u:?} with {dest:?}"); @@ -21,6 +23,8 @@ impl Tasks { } pub fn file_copy(&self, src: &Yanked, dest: &UrlBuf, force: bool, follow: bool) { + self.scheduler.behavior.reset(); + for u in src.iter() { let Some(Ok(to)) = u.name().map(|n| dest.try_join(n)) else { debug!("file_copy: cannot join {u:?} with {dest:?}"); @@ -35,6 +39,8 @@ impl Tasks { } pub fn file_link(&self, src: &IndexSet, dest: &UrlBuf, relative: bool, force: bool) { + self.scheduler.behavior.reset(); + for u in src { let Some(Ok(to)) = u.name().map(|n| dest.try_join(n)) else { debug!("file_link: cannot join {u:?} with {dest:?}"); @@ -49,6 +55,8 @@ impl Tasks { } pub fn file_hardlink(&self, src: &IndexSet, dest: &UrlBuf, force: bool, follow: bool) { + self.scheduler.behavior.reset(); + for u in src { let Some(Ok(to)) = u.name().map(|n| dest.try_join(n)) else { debug!("file_hardlink: cannot join {u:?} with {dest:?}"); diff --git a/yazi-fm/src/executor.rs b/yazi-fm/src/executor.rs index 06ac8071..224a19f4 100644 --- a/yazi-fm/src/executor.rs +++ b/yazi-fm/src/executor.rs @@ -53,12 +53,12 @@ impl<'a> Executor<'a> { "resize" => act!(app:resize, cx, crate::Root::reflow as fn(_) -> _), "resume" => act!(app:resume, cx, yazi_parser::app::ResumeForm { tx: self.app.signals.tx.clone(), - token: action.take_any("token").context("Invalid 'token' in ResumeForm")?, reflow: crate::Root::reflow, + replier: action.take_replier().context("Missing replier in ResumeForm")?, }), "stop" => act!(app:stop, cx, yazi_parser::app::StopForm { tx: self.app.signals.tx.clone(), - token: action.take_any("token").context("Invalid 'token' in StopForm")?, + replier: action.take_replier().context("Missing replier in StopForm")?, }), _ => succ!(), } diff --git a/yazi-fm/src/signals.rs b/yazi-fm/src/signals.rs index 75bc9e5e..b01d1a74 100644 --- a/yazi-fm/src/signals.rs +++ b/yazi-fm/src/signals.rs @@ -3,10 +3,10 @@ use crossterm::event::{Event as CrosstermEvent, EventStream, KeyEvent, KeyEventK use futures::StreamExt; use tokio::{select, sync::mpsc}; use yazi_config::YAZI; -use yazi_shared::{CompletionToken, event::Event}; +use yazi_shared::event::{Event, Replier}; pub(super) struct Signals { - pub(super) tx: mpsc::UnboundedSender<(bool, CompletionToken)>, + pub(super) tx: mpsc::UnboundedSender<(bool, Replier)>, } impl Signals { @@ -65,7 +65,7 @@ impl Signals { } } - fn spawn(mut rx: mpsc::UnboundedReceiver<(bool, CompletionToken)>) -> Result<()> { + fn spawn(mut rx: mpsc::UnboundedReceiver<(bool, Replier)>) -> Result<()> { #[cfg(unix)] use libc::{SIGCONT, SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGTSTP}; @@ -90,9 +90,9 @@ impl Signals { if let Some(t) = &mut term { select! { biased; - Some((state, token)) = rx.recv() => { + Some((state, replier)) = rx.recv() => { term = term.filter(|_| state); - token.complete(true); + replier.send(Ok(().into())).ok(); }, Some(n) = sys.next() => if !Self::handle_sys(n) { return }, Some(Ok(e)) = t.next() => Self::handle_term(e) @@ -100,9 +100,9 @@ impl Signals { } else { select! { biased; - Some((state, token)) = rx.recv() => { + Some((state, replier)) = rx.recv() => { term = state.then(EventStream::new); - token.complete(true); + replier.send(Ok(().into())).ok(); }, Some(n) = sys.next() => if !Self::handle_sys(n) { return }, } diff --git a/yazi-fs/Cargo.toml b/yazi-fs/Cargo.toml index 51d858ad..d0ca5567 100644 --- a/yazi-fs/Cargo.toml +++ b/yazi-fs/Cargo.toml @@ -20,7 +20,7 @@ yazi-shim = { path = "../yazi-shim", version = "26.2.2" } # External dependencies anyhow = { workspace = true } -arc-swap = "1.9.0" +arc-swap = { workspace = true } bitflags = { workspace = true } dirs = { workspace = true } either = { workspace = true } diff --git a/yazi-parser/src/app/resume.rs b/yazi-parser/src/app/resume.rs index 53ba6581..8eafc84f 100644 --- a/yazi-parser/src/app/resume.rs +++ b/yazi-parser/src/app/resume.rs @@ -1,13 +1,13 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Table, Value}; use ratatui::layout::Rect; use tokio::sync::mpsc; -use yazi_shared::CompletionToken; +use yazi_shared::event::Replier; #[derive(Debug)] pub struct ResumeForm { - pub tx: mpsc::UnboundedSender<(bool, CompletionToken)>, - pub token: CompletionToken, - pub reflow: fn(Rect) -> mlua::Result, + pub tx: mpsc::UnboundedSender<(bool, Replier)>, + pub reflow: fn(Rect) -> mlua::Result
, + pub replier: Replier, } impl FromLua for ResumeForm { diff --git a/yazi-parser/src/app/stop.rs b/yazi-parser/src/app/stop.rs index 0f39207d..bf8a3c18 100644 --- a/yazi-parser/src/app/stop.rs +++ b/yazi-parser/src/app/stop.rs @@ -1,11 +1,11 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; use tokio::sync::mpsc; -use yazi_shared::CompletionToken; +use yazi_shared::event::Replier; #[derive(Debug)] pub struct StopForm { - pub tx: mpsc::UnboundedSender<(bool, CompletionToken)>, - pub token: CompletionToken, + pub tx: mpsc::UnboundedSender<(bool, Replier)>, + pub replier: Replier, } impl FromLua for StopForm { diff --git a/yazi-parser/src/cmp/show.rs b/yazi-parser/src/cmp/show.rs index 682816c4..82685582 100644 --- a/yazi-parser/src/cmp/show.rs +++ b/yazi-parser/src/cmp/show.rs @@ -1,4 +1,4 @@ -use anyhow::bail; +use anyhow::anyhow; use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; use yazi_core::cmp::CmpOpt; use yazi_shared::event::ActionCow; @@ -16,11 +16,7 @@ impl TryFrom for ShowForm { type Error = anyhow::Error; fn try_from(mut a: ActionCow) -> Result { - if let Some(opt) = a.take_any2("opt") { - opt - } else { - bail!("Invalid 'opt' in ShowForm"); - } + Ok(Self { opt: a.take_any("opt").ok_or_else(|| anyhow!("Invalid 'opt' in ShowForm"))? }) } } diff --git a/yazi-parser/src/mgr/stash.rs b/yazi-parser/src/mgr/stash.rs index cc20694f..8d725809 100644 --- a/yazi-parser/src/mgr/stash.rs +++ b/yazi-parser/src/mgr/stash.rs @@ -19,7 +19,7 @@ impl TryFrom for StashForm { } impl From for StashForm { - fn from(opt: CdForm) -> Self { Self { target: opt.target, source: opt.source } } + fn from(form: CdForm) -> Self { Self { target: form.target, source: form.source } } } impl FromLua for StashForm { diff --git a/yazi-parser/src/tasks/process_open.rs b/yazi-parser/src/tasks/process_open.rs index 75a3ebb2..5d2c6e2a 100644 --- a/yazi-parser/src/tasks/process_open.rs +++ b/yazi-parser/src/tasks/process_open.rs @@ -1,13 +1,12 @@ use anyhow::anyhow; use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; -use tokio::sync::mpsc; use yazi_scheduler::process::ProcessOpt; -use yazi_shared::{data::Data, event::ActionCow}; +use yazi_shared::event::{ActionCow, Replier}; #[derive(Clone, Debug)] pub struct ProcessOpenForm { pub opt: ProcessOpt, - pub replier: Option>>, + pub replier: Option, } impl TryFrom for ProcessOpenForm { diff --git a/yazi-plugin/src/elements/elements.rs b/yazi-plugin/src/elements/elements.rs index bbcf8131..84e06003 100644 --- a/yazi-plugin/src/elements/elements.rs +++ b/yazi-plugin/src/elements/elements.rs @@ -78,7 +78,7 @@ pub(super) fn lines(lua: &Lua) -> mlua::Result { parsed = s.to_text().into_lua_err()?.lines; LineIter::parsed(&parsed, tab_size) } else { - LineIter::source(&s, tab_size) + LineIter::source(s, tab_size) }; if let Some(wrap) = *opts.raw_get::("wrap")? { diff --git a/yazi-plugin/src/slim.rs b/yazi-plugin/src/slim.rs index e76608b1..8d618749 100644 --- a/yazi-plugin/src/slim.rs +++ b/yazi-plugin/src/slim.rs @@ -8,16 +8,16 @@ pub fn slim_lua(lua: &Lua) -> mlua::Result<()> { globals.raw_set("ya", crate::utils::compose(true))?; globals.raw_set("fs", crate::fs::compose())?; globals.raw_set("rt", crate::runtime::compose())?; - globals.raw_set("th", crate::theme::compose().into_lua(&lua)?)?; + globals.raw_set("th", crate::theme::compose().into_lua(lua)?)?; - yazi_binding::Cha::install(&lua)?; - yazi_binding::File::install(&lua)?; - yazi_binding::Url::install(&lua)?; - yazi_binding::Path::install(&lua)?; + yazi_binding::Cha::install(lua)?; + yazi_binding::File::install(lua)?; + yazi_binding::Url::install(lua)?; + yazi_binding::Path::install(lua)?; - yazi_binding::Error::install(&lua)?; - yazi_binding::process::install(&lua)?; - yazi_runner::loader::install(&lua)?; + yazi_binding::Error::install(lua)?; + yazi_binding::process::install(lua)?; + yazi_runner::loader::install(lua)?; // Addons lua.load(preset!("ya")).set_name("ya.lua").exec()?; diff --git a/yazi-runner/src/fetcher/job.rs b/yazi-runner/src/fetcher/job.rs index e10516e4..284add4c 100644 --- a/yazi-runner/src/fetcher/job.rs +++ b/yazi-runner/src/fetcher/job.rs @@ -12,8 +12,8 @@ impl IntoLua for FetchJob { fn into_lua(self, lua: &mlua::Lua) -> mlua::Result { lua .create_table_from([ - ("args", Sendable::args_to_table_ref(&lua, &self.action.args)?.into_lua(&lua)?), - ("files", lua.create_sequence_from(self.files.into_iter().map(File::new))?.into_lua(&lua)?), + ("args", Sendable::args_to_table_ref(lua, &self.action.args)?.into_lua(lua)?), + ("files", lua.create_sequence_from(self.files.into_iter().map(File::new))?.into_lua(lua)?), ])? .into_lua(lua) } diff --git a/yazi-runner/src/previewer/job.rs b/yazi-runner/src/previewer/job.rs index a428d019..a4a171a5 100644 --- a/yazi-runner/src/previewer/job.rs +++ b/yazi-runner/src/previewer/job.rs @@ -16,11 +16,11 @@ impl IntoLua for PeekJob { fn into_lua(self, lua: &Lua) -> mlua::Result { lua .create_table_from([ - ("area", Rect::from(LAYOUT.get().preview).into_lua(&lua)?), - ("args", Sendable::args_to_table_ref(&lua, &self.action.args)?.into_lua(&lua)?), - ("file", File::new(self.file).into_lua(&lua)?), - ("mime", self.mime.into_lua(&lua)?), - ("skip", self.skip.into_lua(&lua)?), + ("area", Rect::from(LAYOUT.get().preview).into_lua(lua)?), + ("args", Sendable::args_to_table_ref(lua, &self.action.args)?.into_lua(lua)?), + ("file", File::new(self.file).into_lua(lua)?), + ("mime", self.mime.into_lua(lua)?), + ("skip", self.skip.into_lua(lua)?), ])? .into_lua(lua) } @@ -37,9 +37,9 @@ impl IntoLua for SeekJob { fn into_lua(self, lua: &Lua) -> mlua::Result { lua .create_table_from([ - ("area", Rect::from(LAYOUT.get().preview).into_lua(&lua)?), - ("file", File::new(self.file).into_lua(&lua)?), - ("units", self.units.into_lua(&lua)?), + ("area", Rect::from(LAYOUT.get().preview).into_lua(lua)?), + ("file", File::new(self.file).into_lua(lua)?), + ("units", self.units.into_lua(lua)?), ])? .into_lua(lua) } diff --git a/yazi-scheduler/src/behavior.rs b/yazi-scheduler/src/behavior.rs new file mode 100644 index 00000000..d10e6f6c --- /dev/null +++ b/yazi-scheduler/src/behavior.rs @@ -0,0 +1,19 @@ +use std::sync::atomic::{AtomicU64, Ordering}; + +use yazi_shared::Id; + +pub struct Behavior { + first_id: AtomicU64, +} + +impl Behavior { + pub(super) fn new() -> Self { Self { first_id: AtomicU64::new(0) } } + + pub(super) fn update(&self, id: Id) { + self.first_id.compare_exchange(0, id.get(), Ordering::Relaxed, Ordering::Relaxed).ok(); + } + + pub fn reset(&self) { self.first_id.store(0, Ordering::Relaxed); } + + pub fn first_id(&self) -> Id { self.first_id.load(Ordering::Relaxed).into() } +} diff --git a/yazi-scheduler/src/fetch/in.rs b/yazi-scheduler/src/fetch/in.rs index f7411d9d..d0ca06c4 100644 --- a/yazi-scheduler/src/fetch/in.rs +++ b/yazi-scheduler/src/fetch/in.rs @@ -10,7 +10,7 @@ pub(crate) struct FetchIn { } impl From for FetchJob { - fn from(value: FetchIn) -> Self { FetchJob { action: &value.plugin.run, files: value.targets } } + fn from(value: FetchIn) -> Self { Self { action: &value.plugin.run, files: value.targets } } } impl FetchIn { diff --git a/yazi-scheduler/src/hook/hook.rs b/yazi-scheduler/src/hook/hook.rs index be8e9460..90b2cc55 100644 --- a/yazi-scheduler/src/hook/hook.rs +++ b/yazi-scheduler/src/hook/hook.rs @@ -30,7 +30,7 @@ impl Hook { } let result = ok_or_not_found(provider::remove_dir_clean(&task.from).await); - TasksProxy::update_succeed(task.id, [&task.to, &task.from], false); + TasksProxy::update_succeed(task.id, [&task.to, &task.from], true); Pump::push_move(task.from, task.to); self.ops.out(task.id, FileOutCut::Clean(result)); @@ -38,7 +38,7 @@ impl Hook { pub(crate) async fn copy(&self, task: HookInOutCopy) { if self.ongoing.lock().intact(task.id) { - TasksProxy::update_succeed(task.id, [&task.to], false); + TasksProxy::update_succeed(task.id, [&task.to], true); Pump::push_duplicate(task.from, task.to); } diff --git a/yazi-scheduler/src/lib.rs b/yazi-scheduler/src/lib.rs index 77959f39..9ea9dfc7 100644 --- a/yazi-scheduler/src/lib.rs +++ b/yazi-scheduler/src/lib.rs @@ -2,7 +2,7 @@ mod macros; yazi_macro::mod_pub!(fetch file hook plugin preload process size); -yazi_macro::mod_flat!(ongoing op out progress proxy scheduler snap summary task worker); +yazi_macro::mod_flat!(behavior ongoing op out progress proxy scheduler snap summary task worker); const LOW: u8 = yazi_config::Priority::Low as u8; const NORMAL: u8 = yazi_config::Priority::Normal as u8; diff --git a/yazi-scheduler/src/proxy.rs b/yazi-scheduler/src/proxy.rs index 0ffd3429..67c43dd5 100644 --- a/yazi-scheduler/src/proxy.rs +++ b/yazi-scheduler/src/proxy.rs @@ -1,21 +1,20 @@ +use tokio::sync::mpsc; use yazi_macro::{emit, relay}; -use yazi_shared::{CompletionToken, Id, SStr, url::UrlBuf}; +use yazi_shared::{Id, SStr, url::UrlBuf}; pub struct AppProxy; impl AppProxy { - // FIXME: use replier instead of token pub async fn stop() { - let token = CompletionToken::default(); - emit!(Call(relay!(app:stop).with_any("token", token.clone()))); - token.future().await; + let (tx, mut rx) = mpsc::unbounded_channel(); + emit!(Call(relay!(app:stop).with_replier(tx))); + rx.recv().await; } - // FIXME: use replier instead of token pub async fn resume() { - let token = CompletionToken::default(); - emit!(Call(relay!(app:resume).with_any("token", token.clone()))); - token.future().await; + let (tx, mut rx) = mpsc::unbounded_channel(); + emit!(Call(relay!(app:resume).with_replier(tx))); + rx.recv().await; } } diff --git a/yazi-scheduler/src/scheduler.rs b/yazi-scheduler/src/scheduler.rs index 31065327..91607df6 100644 --- a/yazi-scheduler/src/scheduler.rs +++ b/yazi-scheduler/src/scheduler.rs @@ -1,16 +1,16 @@ -use std::{ops::Deref, sync::{Arc, atomic::{AtomicU64, Ordering}}, time::Duration}; +use std::{ops::Deref, sync::Arc, time::Duration}; use tokio::task::JoinHandle; use yazi_config::{YAZI, plugin::{Fetcher, Preloader}}; use yazi_runner::plugin::PluginOpt; use yazi_shared::{CompletionToken, Id, Throttle, url::{UrlBuf, UrlLike}}; -use crate::{HIGH, LOW, NORMAL, Worker, Task, TaskProg, fetch::{FetchIn, FetchProg}, file::{FileInCopy, FileInCut, FileInDelete, FileInDownload, FileInHardlink, FileInLink, FileInTrash, FileInUpload, FileOutCopy, FileOutCut, FileOutDownload, FileOutHardlink, FileOutUpload, FileProgCopy, FileProgCut, FileProgDelete, FileProgDownload, FileProgHardlink, FileProgLink, FileProgTrash, FileProgUpload}, hook::{HookIn, HookInDelete, HookInDownload, HookInTrash, HookInUpload}, plugin::{PluginInEntry, PluginProgEntry}, preload::{PreloadIn, PreloadProg}, process::{ProcessInBg, ProcessInBlock, ProcessInOrphan, ProcessOpt, ProcessProgBg, ProcessProgBlock, ProcessProgOrphan}, size::{SizeIn, SizeProg}}; +use crate::{Behavior, HIGH, LOW, NORMAL, Task, TaskProg, Worker, fetch::{FetchIn, FetchProg}, file::{FileInCopy, FileInCut, FileInDelete, FileInDownload, FileInHardlink, FileInLink, FileInTrash, FileInUpload, FileOutCopy, FileOutCut, FileOutDownload, FileOutHardlink, FileOutUpload, FileProgCopy, FileProgCut, FileProgDelete, FileProgDownload, FileProgHardlink, FileProgLink, FileProgTrash, FileProgUpload}, hook::{HookIn, HookInDelete, HookInDownload, HookInTrash, HookInUpload}, plugin::{PluginInEntry, PluginProgEntry}, preload::{PreloadIn, PreloadProg}, process::{ProcessInBg, ProcessInBlock, ProcessInOrphan, ProcessOpt, ProcessProgBg, ProcessProgBlock, ProcessProgOrphan}, size::{SizeIn, SizeProg}}; pub struct Scheduler { - pub worker: Worker, - pub user_action: AtomicU64, - handles: Vec>, + pub worker: Worker, + pub behavior: Behavior, + handles: Vec>, } impl Deref for Scheduler { @@ -22,7 +22,7 @@ impl Deref for Scheduler { impl Scheduler { pub fn serve() -> Self { let (worker, handles) = Worker::make(); - Self { worker, user_action: AtomicU64::new(0), handles } + Self { worker, behavior: Behavior::new(), handles } } fn add(&self, name: String, map: impl FnOnce(&mut Task) -> R) -> R @@ -30,14 +30,11 @@ impl Scheduler { T: Into + Default, { let prog = T::default().into(); - let is_user = prog.is_user(); let mut ongoing = self.ongoing.lock(); let task = ongoing.add(name, prog); - if is_user { - self.user_action.store(task.id.get(), Ordering::Relaxed); - } + self.behavior.update(task.id); map(task) } diff --git a/yazi-scheduler/src/summary.rs b/yazi-scheduler/src/summary.rs index 78f26b05..703b293f 100644 --- a/yazi-scheduler/src/summary.rs +++ b/yazi-scheduler/src/summary.rs @@ -18,7 +18,7 @@ impl From<&Ongoing> for TaskSummary { let mut percent_count = 0; for task in value.values() { - let s: TaskSummary = task.prog.into(); + let s: Self = task.prog.into(); if s.total == 0 && !task.prog.failed() { continue; } diff --git a/yazi-shared/src/data/de_owned.rs b/yazi-shared/src/data/de_owned.rs index 205bda49..1db52c22 100644 --- a/yazi-shared/src/data/de_owned.rs +++ b/yazi-shared/src/data/de_owned.rs @@ -12,19 +12,19 @@ impl<'de> Deserializer<'de> for Data { V: de::Visitor<'de>, { match self { - Data::Nil => visitor.visit_unit(), - Data::Boolean(b) => visitor.visit_bool(b), - Data::Integer(i) => visitor.visit_i64(i), - Data::Number(n) => visitor.visit_f64(n), - Data::String(Cow::Borrowed(s)) => visitor.visit_borrowed_str(s), - Data::String(Cow::Owned(s)) => visitor.visit_string(s), - Data::List(l) => visitor.visit_seq(SeqDeserializer { iter: l.into_iter() }), - Data::Dict(d) => visitor.visit_map(MapDeserializer { iter: d.into_iter(), value: None }), - Data::Id(i) => visitor.visit_u64(i.get()), - Data::Url(u) => u.into_deserializer().deserialize_any(visitor), - Data::Path(_) => Err(Error::custom("path not supported")), - Data::Bytes(b) => BytesDeserializer(b.into()).deserialize_any(visitor), - Data::Any(_) => Err(Error::custom("any not supported")), + Self::Nil => visitor.visit_unit(), + Self::Boolean(b) => visitor.visit_bool(b), + Self::Integer(i) => visitor.visit_i64(i), + Self::Number(n) => visitor.visit_f64(n), + Self::String(Cow::Borrowed(s)) => visitor.visit_borrowed_str(s), + Self::String(Cow::Owned(s)) => visitor.visit_string(s), + Self::List(l) => visitor.visit_seq(SeqDeserializer { iter: l.into_iter() }), + Self::Dict(d) => visitor.visit_map(MapDeserializer { iter: d.into_iter(), value: None }), + Self::Id(i) => visitor.visit_u64(i.get()), + Self::Url(u) => u.into_deserializer().deserialize_any(visitor), + Self::Path(_) => Err(Error::custom("path not supported")), + Self::Bytes(b) => BytesDeserializer(b.into()).deserialize_any(visitor), + Self::Any(_) => Err(Error::custom("any not supported")), } } @@ -122,9 +122,9 @@ impl<'de> Deserializer<'de> for Data { V: de::Visitor<'de>, { match self { - Data::String(Cow::Borrowed(s)) => visitor.visit_borrowed_str(s), - Data::String(Cow::Owned(s)) => visitor.visit_string(s), - Data::Url(u) => visitor.visit_newtype_struct(u.into_deserializer()), + Self::String(Cow::Borrowed(s)) => visitor.visit_borrowed_str(s), + Self::String(Cow::Owned(s)) => visitor.visit_string(s), + Self::Url(u) => visitor.visit_newtype_struct(u.into_deserializer()), _ => Err(Error::custom("not a string")), } } @@ -141,7 +141,7 @@ impl<'de> Deserializer<'de> for Data { V: de::Visitor<'de>, { match self { - Data::Bytes(b) => BytesDeserializer(b.into()).deserialize_bytes(visitor), + Self::Bytes(b) => BytesDeserializer(b.into()).deserialize_bytes(visitor), _ => Err(Error::custom("not bytes")), } } @@ -158,7 +158,7 @@ impl<'de> Deserializer<'de> for Data { V: de::Visitor<'de>, { match self { - Data::Nil => visitor.visit_none(), + Self::Nil => visitor.visit_none(), other => visitor.visit_some(other), } } @@ -168,7 +168,7 @@ impl<'de> Deserializer<'de> for Data { V: de::Visitor<'de>, { match self { - Data::Nil => visitor.visit_unit(), + Self::Nil => visitor.visit_unit(), _ => Err(Error::custom("expected unit")), } } @@ -182,7 +182,7 @@ impl<'de> Deserializer<'de> for Data { V: de::Visitor<'de>, { match self { - Data::Nil => visitor.visit_unit(), + Self::Nil => visitor.visit_unit(), _ => Err(Error::custom("expected unit struct")), } } @@ -203,8 +203,8 @@ impl<'de> Deserializer<'de> for Data { V: de::Visitor<'de>, { match self { - Data::List(l) => visitor.visit_seq(SeqDeserializer { iter: l.into_iter() }), - Data::Bytes(b) => BytesDeserializer(b.into()).deserialize_seq(visitor), + Self::List(l) => visitor.visit_seq(SeqDeserializer { iter: l.into_iter() }), + Self::Bytes(b) => BytesDeserializer(b.into()).deserialize_seq(visitor), _ => Err(Error::custom("not a sequence")), } } @@ -233,8 +233,8 @@ impl<'de> Deserializer<'de> for Data { V: de::Visitor<'de>, { match self { - Data::Dict(d) => visitor.visit_map(MapDeserializer { iter: d.into_iter(), value: None }), - Data::Url(u) => Deserializer::deserialize_map(u.into_deserializer(), visitor), + Self::Dict(d) => visitor.visit_map(MapDeserializer { iter: d.into_iter(), value: None }), + Self::Url(u) => Deserializer::deserialize_map(u.into_deserializer(), visitor), _ => Err(Error::custom("not a map")), } } @@ -261,7 +261,7 @@ impl<'de> Deserializer<'de> for Data { V: de::Visitor<'de>, { match self { - Data::String(s) => visitor.visit_enum(s.into_deserializer()), + Self::String(s) => visitor.visit_enum(s.into_deserializer()), _ => Err(Error::custom("not an enum")), } } diff --git a/yazi-shared/src/event/action.rs b/yazi-shared/src/event/action.rs index d405b27a..349b3998 100644 --- a/yazi-shared/src/event/action.rs +++ b/yazi-shared/src/event/action.rs @@ -3,9 +3,8 @@ use std::{borrow::Cow, fmt::{self, Display}, mem, str::FromStr}; use anyhow::{Result, anyhow, bail}; use hashbrown::HashMap; use serde::{Deserialize, de}; -use tokio::sync::mpsc; -use crate::{Layer, SStr, Source, data::{Data, DataAny, DataKey}}; +use crate::{Layer, SStr, Source, data::{Data, DataAny, DataKey}, event::Replier}; #[derive(Clone, Debug, Default)] pub struct Action { @@ -89,7 +88,7 @@ impl Action { self } - pub fn with_replier(mut self, tx: mpsc::UnboundedSender>) -> Self { + pub fn with_replier(mut self, tx: Replier) -> Self { self.args.insert("replier".into(), Data::Any(Box::new(tx))); self } @@ -115,9 +114,7 @@ impl Action { self.args.get(&name.into())?.as_any() } - pub fn replier(&self) -> Option<&mpsc::UnboundedSender>> { - self.any("replier") - } + pub fn replier(&self) -> Option<&Replier> { self.any("replier") } pub fn first<'a, T>(&'a self) -> Result where @@ -210,9 +207,7 @@ impl Action { (0..self.len()).filter_map(|i| self.args.remove(&DataKey::from(i))?.into_any()) } - pub fn take_replier(&mut self) -> Option>> { - self.take_any("replier") - } + pub fn take_replier(&mut self) -> Option { self.take_any("replier") } // Parse pub fn parse_args(words: I, last: Option) -> Result> diff --git a/yazi-shared/src/event/cow.rs b/yazi-shared/src/event/cow.rs index e59b1449..7133ac8c 100644 --- a/yazi-shared/src/event/cow.rs +++ b/yazi-shared/src/event/cow.rs @@ -2,10 +2,9 @@ use std::{iter, ops::Deref}; use anyhow::Result; use serde::de::DeserializeOwned; -use tokio::sync::mpsc; use super::Action; -use crate::data::{Data, DataKey}; +use crate::{data::{Data, DataKey}, event::Replier}; #[derive(Debug)] pub enum ActionCow { @@ -116,7 +115,7 @@ impl ActionCow { } } - pub fn take_replier(&mut self) -> Option>> { + pub fn take_replier(&mut self) -> Option { match self { Self::Owned(c) => c.take_replier(), Self::Borrowed(_) => None, diff --git a/yazi-shared/src/event/mod.rs b/yazi-shared/src/event/mod.rs index 437bef17..29abc267 100644 --- a/yazi-shared/src/event/mod.rs +++ b/yazi-shared/src/event/mod.rs @@ -1,3 +1,5 @@ yazi_macro::mod_flat!(action cow de de_owned event); +pub type Replier = tokio::sync::mpsc::UnboundedSender>; + pub static NEED_RENDER: std::sync::atomic::AtomicU8 = std::sync::atomic::AtomicU8::new(0);