From 292d37ccde5fb09dc7318247caf552213d16ec36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20misaki=20masa?= Date: Fri, 8 Aug 2025 02:41:41 +0800 Subject: [PATCH] refactor: simplify cursor repositioning (#3040) --- yazi-actor/src/context.rs | 5 +++ yazi-actor/src/mgr/arrow.rs | 2 +- yazi-actor/src/mgr/cd.rs | 2 ++ yazi-actor/src/mgr/filter_do.rs | 8 ++--- yazi-actor/src/mgr/hidden.rs | 46 ++++++++++++++++++------- yazi-actor/src/mgr/hover.rs | 50 +++++++++++---------------- yazi-actor/src/mgr/refresh.rs | 4 +-- yazi-actor/src/mgr/reveal.rs | 4 +-- yazi-actor/src/mgr/search.rs | 14 +++++--- yazi-actor/src/mgr/sort.rs | 55 +++++++++++++++++++++--------- yazi-actor/src/mgr/tab_create.rs | 2 -- yazi-actor/src/mgr/tab_swap.rs | 10 +++--- yazi-actor/src/mgr/update_files.rs | 5 +-- yazi-actor/src/mgr/update_mimes.rs | 2 +- yazi-core/src/tab/folder.rs | 15 ++++++-- yazi-core/src/tab/tab.rs | 39 +++++---------------- yazi-dds/src/spark/spark.rs | 3 -- yazi-fs/src/files.rs | 6 +++- yazi-fs/src/sorter.rs | 2 +- yazi-macro/src/context.rs | 7 ++++ yazi-macro/src/lib.rs | 1 + yazi-parser/src/mgr/hidden.rs | 49 ++++++++++++++++++++------ yazi-parser/src/mgr/hover.rs | 30 +++------------- yazi-parser/src/mgr/sort.rs | 2 +- yazi-shared/src/url/urn.rs | 10 ++++++ 25 files changed, 209 insertions(+), 164 deletions(-) create mode 100644 yazi-macro/src/context.rs diff --git a/yazi-actor/src/context.rs b/yazi-actor/src/context.rs index d418e18b..82d87fe3 100644 --- a/yazi-actor/src/context.rs +++ b/yazi-actor/src/context.rs @@ -88,6 +88,11 @@ impl<'a> Ctx<'a> { #[inline] pub fn hovered_folder(&self) -> Option<&Folder> { self.tab().hovered_folder() } + #[inline] + pub fn hovered_folder_mut(&mut self) -> Option<&mut Folder> { + self.tab_mut().hovered_folder_mut() + } + #[inline] pub fn tasks(&self) -> &Tasks { &self.tasks } diff --git a/yazi-actor/src/mgr/arrow.rs b/yazi-actor/src/mgr/arrow.rs index fd69f36d..b2b3b71c 100644 --- a/yazi-actor/src/mgr/arrow.rs +++ b/yazi-actor/src/mgr/arrow.rs @@ -24,7 +24,7 @@ impl Actor for Arrow { *items = (start.min(end)..=end.max(start)).collect(); } - act!(mgr:hover, cx, None)?; + act!(mgr:hover, cx)?; act!(mgr:peek, cx)?; act!(mgr:watch, cx)?; diff --git a/yazi-actor/src/mgr/cd.rs b/yazi-actor/src/mgr/cd.rs index b1819ca3..c94fb35b 100644 --- a/yazi-actor/src/mgr/cd.rs +++ b/yazi-actor/src/mgr/cd.rs @@ -59,6 +59,8 @@ impl Actor for Cd { } err!(Pubsub::pub_after_cd(tab.id, tab.cwd())); + act!(mgr:hidden, cx)?; + act!(mgr:sort, cx)?; act!(mgr:hover, cx)?; act!(mgr:refresh, cx)?; succ!(render!()); diff --git a/yazi-actor/src/mgr/filter_do.rs b/yazi-actor/src/mgr/filter_do.rs index 41c3b557..5ac1886b 100644 --- a/yazi-actor/src/mgr/filter_do.rs +++ b/yazi-actor/src/mgr/filter_do.rs @@ -17,12 +17,10 @@ impl Actor for FilterDo { let filter = if opt.query.is_empty() { None } else { Some(Filter::new(&opt.query, opt.case)?) }; let hovered = cx.hovered().map(|f| f.urn_owned()); - if cx.current_mut().files.set_filter(filter) { - cx.current_mut().repos(hovered.as_ref()); - } + cx.current_mut().files.set_filter(filter); - if cx.hovered().map(|f| f.urn()) != hovered.as_ref().map(|u| u.as_urn()) { - act!(mgr:hover, cx)?; + if cx.hovered().map(|f| f.urn()) != hovered.as_deref() { + act!(mgr:hover, cx, hovered)?; act!(mgr:peek, cx)?; act!(mgr:watch, cx)?; } diff --git a/yazi-actor/src/mgr/hidden.rs b/yazi-actor/src/mgr/hidden.rs index 0dc85ed7..427e1293 100644 --- a/yazi-actor/src/mgr/hidden.rs +++ b/yazi-actor/src/mgr/hidden.rs @@ -1,5 +1,7 @@ use anyhow::Result; -use yazi_macro::{act, succ}; +use yazi_core::tab::Folder; +use yazi_fs::FolderStage; +use yazi_macro::{act, render, render_and, succ}; use yazi_parser::mgr::HiddenOpt; use yazi_shared::event::Data; @@ -13,21 +15,39 @@ impl Actor for Hidden { const NAME: &str = "hidden"; fn act(cx: &mut Ctx, opt: Self::Options) -> Result { - let tab = cx.tab_mut(); - tab.pref.show_hidden = opt.state.unwrap_or(!tab.pref.show_hidden); + let state = opt.state.bool(cx.tab().pref.show_hidden); + cx.tab_mut().pref.show_hidden = state; - let hovered = tab.hovered().map(|f| f.url_owned()); - tab.apply_files_attrs(); + let hovered = cx.hovered().map(|f| f.urn_owned()); + let apply = |f: &mut Folder| { + if f.stage == FolderStage::Loading { + render!(); + false + } else { + f.files.set_show_hidden(state); + render_and!(f.files.catchup_revision()) + } + }; - if hovered.as_ref() != tab.hovered().map(|f| &f.url) { - act!(mgr:hover, cx, hovered)?; - act!(mgr:peek, cx)?; - act!(mgr:watch, cx)?; - } else if tab.hovered().is_some_and(|f| f.is_dir()) { - act!(mgr:peek, cx, true)?; + // Apply to CWD and parent + if let (a, Some(b)) = (apply(cx.current_mut()), cx.parent_mut().map(apply)) + && (a | b) + { + act!(mgr:hover, cx)?; + act!(mgr:update_paged, cx)?; } - act!(mgr:update_paged, cx)?; - succ!(); + // Apply to hovered + if let Some(h) = cx.hovered_folder_mut() + && apply(h) + { + render!(h.repos(None)); + act!(mgr:peek, cx, true)?; + } else if hovered.as_deref() != cx.hovered().map(|f| f.urn()) { + act!(mgr:peek, cx)?; + act!(mgr:watch, cx)?; + } + + succ!() } } diff --git a/yazi-actor/src/mgr/hover.rs b/yazi-actor/src/mgr/hover.rs index 0d7afab7..f4eb1d2f 100644 --- a/yazi-actor/src/mgr/hover.rs +++ b/yazi-actor/src/mgr/hover.rs @@ -1,7 +1,7 @@ use anyhow::Result; use yazi_dds::Pubsub; -use yazi_macro::{act, err, render, succ}; -use yazi_parser::mgr::{HoverDoOpt, HoverOpt}; +use yazi_macro::{err, render, succ, tab}; +use yazi_parser::mgr::HoverOpt; use yazi_shared::event::Data; use crate::{Actor, Ctx}; @@ -14,39 +14,27 @@ impl Actor for Hover { const NAME: &str = "hover"; fn act(cx: &mut Ctx, opt: Self::Options) -> Result { - if let Some(u) = opt.url { - act!(mgr:hover_do, cx, u)?; - } else { - cx.current_mut().arrow(0); + let tab = tab!(cx); + + // Parent should always track CWD + if let Some(p) = &mut tab.parent { + render!(p.repos(tab.current.url.strip_prefix(&p.url))); + } + + // Repos CWD + tab.current.repos(opt.urn.as_deref()); + + // Turn on tracing + if let (Some(h), Some(u)) = (tab.hovered(), opt.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 location of the file regardless. + tab.current.trace = Some(u.to_owned()); } // Publish through DDS - let tab = cx.tab(); err!(Pubsub::pub_after_hover(tab.id, tab.hovered().map(|h| &h.url))); succ!(); } } - -// --- Do -pub struct HoverDo; - -impl Actor for HoverDo { - type Options = HoverDoOpt; - - const NAME: &str = "hover_do"; - - fn act(cx: &mut Ctx, opt: Self::Options) -> Result { - // Hover on the file - if let Some(u) = opt.url.strip_prefix(cx.cwd()) { - render!(cx.current_mut().hover(u)); - } - - // Turn on tracing - if cx.hovered().is_some_and(|h| h.url == opt.url) { - // `hover(Some)` occurs after user actions, such as create, rename, reveal, etc. - // At this point, it's intuitive to track the location of the file regardless. - cx.current_mut().trace = Some(opt.url.urn_owned()); - } - succ!(); - } -} diff --git a/yazi-actor/src/mgr/refresh.rs b/yazi-actor/src/mgr/refresh.rs index cb8ec856..69b79196 100644 --- a/yazi-actor/src/mgr/refresh.rs +++ b/yazi-actor/src/mgr/refresh.rs @@ -21,15 +21,13 @@ impl Actor for Refresh { execute!(TTY.writer(), SetTitle(s)).ok(); } - cx.tab_mut().apply_files_attrs(); - if let Some(p) = cx.parent() { cx.mgr.watcher.trigger_dirs(&[cx.current(), p]); } else { cx.mgr.watcher.trigger_dirs(&[cx.current()]); } - act!(mgr:peek, cx, false)?; + act!(mgr:peek, cx)?; act!(mgr:watch, cx)?; act!(mgr:update_paged, cx)?; diff --git a/yazi-actor/src/mgr/reveal.rs b/yazi-actor/src/mgr/reveal.rs index 6db7b019..820e7506 100644 --- a/yazi-actor/src/mgr/reveal.rs +++ b/yazi-actor/src/mgr/reveal.rs @@ -26,12 +26,12 @@ 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, vec![File::from_dummy(opt.target.clone(), None)]); + let op = FilesOp::Creating(parent, vec![File::from_dummy(opt.target, None)]); tab.current.update_pub(tab.id, op); } // Now, we can safely hover on the target - act!(mgr:hover, cx, Some(opt.target))?; + act!(mgr:hover, cx, Some(child))?; act!(mgr:peek, cx)?; act!(mgr:watch, cx)?; diff --git a/yazi-actor/src/mgr/search.rs b/yazi-actor/src/mgr/search.rs index a377b7f0..33bd30ea 100644 --- a/yazi-actor/src/mgr/search.rs +++ b/yazi-actor/src/mgr/search.rs @@ -107,11 +107,15 @@ impl Actor for SearchStop { handle.abort(); } - if tab.cwd().is_search() { - let rep = tab.history.remove_or(&tab.cwd().to_regular()); - drop(mem::replace(&mut tab.current, rep)); - act!(mgr:refresh, cx)?; + if !tab.cwd().is_search() { + succ!(); } - succ!(); + + let rep = tab.history.remove_or(&tab.cwd().to_regular()); + drop(mem::replace(&mut tab.current, rep)); + + act!(mgr:hidden, cx)?; + act!(mgr:sort, cx)?; + act!(mgr:refresh, cx) } } diff --git a/yazi-actor/src/mgr/sort.rs b/yazi-actor/src/mgr/sort.rs index b8d3c097..7bc46638 100644 --- a/yazi-actor/src/mgr/sort.rs +++ b/yazi-actor/src/mgr/sort.rs @@ -1,5 +1,7 @@ use anyhow::Result; -use yazi_macro::{act, succ}; +use yazi_core::tab::Folder; +use yazi_fs::{FilesSorter, FolderStage}; +use yazi_macro::{act, render, render_and, succ}; use yazi_parser::mgr::SortOpt; use yazi_shared::event::Data; @@ -13,25 +15,44 @@ impl Actor for Sort { const NAME: &str = "sort"; fn act(cx: &mut Ctx, opt: Self::Options) -> Result { - let mut new = cx.tab().pref.clone(); - new.sort_by = opt.by.unwrap_or(new.sort_by); - new.sort_reverse = opt.reverse.unwrap_or(new.sort_reverse); - new.sort_dir_first = opt.dir_first.unwrap_or(new.sort_dir_first); - new.sort_sensitive = opt.sensitive.unwrap_or(new.sort_sensitive); - new.sort_translit = opt.translit.unwrap_or(new.sort_translit); + 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); - if new == cx.tab().pref { - succ!(); + let sorter = FilesSorter::from(&*pref); + let hovered = cx.hovered().map(|f| f.urn_owned()); + let apply = |f: &mut Folder| { + if f.stage == FolderStage::Loading { + render!(); + false + } else { + f.files.set_sorter(sorter); + render_and!(f.files.catchup_revision()) + } + }; + + // Apply to CWD and parent + if let (a, Some(b)) = (apply(cx.current_mut()), cx.parent_mut().map(apply)) + && (a | b) + { + act!(mgr:hover, cx)?; + act!(mgr:update_paged, cx)?; + cx.tasks.prework_sorted(&cx.mgr.tabs[cx.tab].current.files); } - cx.tab_mut().pref = new; - cx.tab_mut().apply_files_attrs(); - act!(mgr:hover, cx)?; - - cx.tasks.prework_sorted(&cx.mgr.tabs[cx.tab].current.files); - act!(mgr:peek, cx)?; - act!(mgr:watch, cx)?; - act!(mgr:update_paged, cx)?; + // Apply to hovered + if let Some(h) = cx.hovered_folder_mut() + && apply(h) + { + render!(h.repos(None)); + act!(mgr:peek, cx, true)?; + } else if hovered.as_deref() != cx.hovered().map(|f| f.urn()) { + act!(mgr:peek, cx)?; + act!(mgr:watch, cx)?; + } succ!(); } diff --git a/yazi-actor/src/mgr/tab_create.rs b/yazi-actor/src/mgr/tab_create.rs index 7ca89f64..7401e06c 100644 --- a/yazi-actor/src/mgr/tab_create.rs +++ b/yazi-actor/src/mgr/tab_create.rs @@ -29,11 +29,9 @@ impl Actor for TabCreate { (true, wd) } else if let Some(h) = cx.hovered() { tab.pref = cx.tab().pref.clone(); - tab.apply_files_attrs(); (false, h.url.to_regular()) } else { tab.pref = cx.tab().pref.clone(); - tab.apply_files_attrs(); (true, cx.cwd().to_regular()) }; diff --git a/yazi-actor/src/mgr/tab_swap.rs b/yazi-actor/src/mgr/tab_swap.rs index 8d181b57..8f728946 100644 --- a/yazi-actor/src/mgr/tab_swap.rs +++ b/yazi-actor/src/mgr/tab_swap.rs @@ -1,5 +1,6 @@ use anyhow::Result; -use yazi_macro::{act, render, succ}; +use yazi_dds::Pubsub; +use yazi_macro::{err, render, succ}; use yazi_parser::ArrowOpt; use yazi_shared::event::Data; @@ -21,12 +22,9 @@ impl Actor for TabSwap { } tabs.items.swap(tabs.cursor, new); - tabs.set_idx(new); - - let cx = &mut Ctx::renew(cx); - act!(mgr:refresh, cx)?; - act!(mgr:peek, cx, true)?; + tabs.cursor = new; + err!(Pubsub::pub_after_tab(cx.active().id)); succ!(render!()); } } diff --git a/yazi-actor/src/mgr/update_files.rs b/yazi-actor/src/mgr/update_files.rs index c3e66c79..a1abf60a 100644 --- a/yazi-actor/src/mgr/update_files.rs +++ b/yazi-actor/src/mgr/update_files.rs @@ -23,11 +23,12 @@ impl Actor for UpdateFiles { } render!(cx.mgr.yanked.catchup_revision(false)); - cx.tab_mut().apply_files_attrs(); + act!(mgr:hidden, cx)?; + act!(mgr:sort, cx)?; if revision != cx.current().files.revision { act!(mgr:hover, cx)?; - act!(mgr:peek, cx, false)?; + act!(mgr:peek, cx)?; act!(mgr:watch, cx)?; act!(mgr:update_paged, cx)?; } diff --git a/yazi-actor/src/mgr/update_mimes.rs b/yazi-actor/src/mgr/update_mimes.rs index 73d885bb..2ec0addc 100644 --- a/yazi-actor/src/mgr/update_mimes.rs +++ b/yazi-actor/src/mgr/update_mimes.rs @@ -47,7 +47,7 @@ impl Actor for UpdateMimes { cx.mgr.mimetype.extend(updates); if repeek { - act!(mgr:peek, cx, false)?; + act!(mgr:peek, cx)?; } cx.tasks.fetch_paged(&affected, &cx.mgr.mimetype); cx.tasks.preload_paged(&affected, &cx.mgr.mimetype); diff --git a/yazi-core/src/tab/folder.rs b/yazi-core/src/tab/folder.rs index 7b0343c0..a038b83d 100644 --- a/yazi-core/src/tab/folder.rs +++ b/yazi-core/src/tab/folder.rs @@ -81,7 +81,7 @@ impl Folder { } self.trace = self.trace.take_if(|_| !self.files.is_empty() || self.stage.is_loading()); - self.repos(self.trace.clone()); + self.repos(None); (stage, revision) != (self.stage, self.files.revision) } @@ -120,8 +120,14 @@ impl Folder { } #[inline] - pub fn repos(&mut self, urn: Option>) -> bool { - if let Some(u) = urn { self.hover(u.as_ref()) } else { self.arrow(0) } + pub fn repos(&mut self, urn: Option<&Urn>) -> bool { + if let Some(u) = urn { + self.hover(u) + } else if let Some(u) = &self.trace { + self.hover(u.clone().as_ref()) + } else { + self.arrow(0) + } } pub fn sync_page(&mut self, force: bool) { @@ -157,6 +163,9 @@ impl Folder { #[inline] pub fn hovered(&self) -> Option<&File> { self.files.get(self.cursor) } + #[inline] + pub fn hovered_mut(&mut self) -> Option<&mut File> { self.files.get_mut(self.cursor) } + pub fn paginate(&self, page: usize) -> &[File] { let len = self.files.len(); let limit = LAYOUT.get().limit(); diff --git a/yazi-core/src/tab/tab.rs b/yazi-core/src/tab/tab.rs index 87de1323..e0e16df3 100644 --- a/yazi-core/src/tab/tab.rs +++ b/yazi-core/src/tab/tab.rs @@ -5,9 +5,8 @@ use ratatui::layout::Rect; use tokio::task::JoinHandle; use yazi_adapter::Dimension; use yazi_config::{LAYOUT, popup::{Origin, Position}}; -use yazi_fs::{File, FolderStage}; -use yazi_macro::render; -use yazi_shared::{Id, Ids, url::{Url, Urn}}; +use yazi_fs::File; +use yazi_shared::{Id, Ids, url::Url}; use super::{Backstack, Finder, Folder, History, Mode, Preference, Preview}; use crate::{spot::Spot, tab::Selected}; @@ -67,6 +66,9 @@ impl Tab { #[inline] pub fn hovered(&self) -> Option<&File> { self.current.hovered() } + #[inline] + pub fn hovered_mut(&mut self) -> Option<&mut File> { self.current.hovered_mut() } + pub fn hovered_rect(&self) -> Option { let y = self.current.files.position(self.hovered()?.urn())? - self.current.offset; @@ -108,33 +110,8 @@ impl Tab { self.hovered().filter(|&h| h.is_dir()).and_then(|h| self.history.get(&h.url)) } - pub fn apply_files_attrs(&mut self) { - let apply = |f: &mut Folder| { - if f.stage == FolderStage::Loading { - return render!(); - } - - f.files.set_show_hidden(self.pref.show_hidden); - f.files.set_sorter(<_>::from(&self.pref)); - - render!(f.files.catchup_revision()); - render!(f.repos(f.trace.clone())); - }; - - apply(&mut self.current); - - if let Some(parent) = &mut self.parent { - apply(parent); - - // The parent should always track the CWD - parent.hover(self.current.url.strip_prefix(&parent.url).unwrap_or(Urn::new(""))); - } - - self - .current - .hovered() - .filter(|h| h.is_dir()) - .and_then(|h| self.history.get_mut(&h.url)) - .map(apply); + #[inline] + pub fn hovered_folder_mut(&mut self) -> Option<&mut Folder> { + self.current.hovered_mut().filter(|h| h.is_dir()).and_then(|h| self.history.get_mut(&h.url)) } } diff --git a/yazi-dds/src/spark/spark.rs b/yazi-dds/src/spark/spark.rs index 1be669de..27f47b06 100644 --- a/yazi-dds/src/spark/spark.rs +++ b/yazi-dds/src/spark/spark.rs @@ -32,7 +32,6 @@ pub enum Spark<'a> { Hardlink(yazi_parser::mgr::HardlinkOpt), Hidden(yazi_parser::mgr::HiddenOpt), Hover(yazi_parser::mgr::HoverOpt), - HoverDo(yazi_parser::mgr::HoverDoOpt), Leave(yazi_parser::VoidOpt), Linemode(yazi_parser::mgr::LinemodeOpt), Link(yazi_parser::mgr::LinkOpt), @@ -155,7 +154,6 @@ impl<'a> IntoLua for Spark<'a> { Self::Hardlink(b) => b.into_lua(lua), Self::Hidden(b) => b.into_lua(lua), Self::Hover(b) => b.into_lua(lua), - Self::HoverDo(b) => b.into_lua(lua), Self::Leave(b) => b.into_lua(lua), Self::Linemode(b) => b.into_lua(lua), Self::Link(b) => b.into_lua(lua), @@ -289,7 +287,6 @@ try_from_spark!(mgr::FindDoOpt, mgr:find_do); try_from_spark!(mgr::FindOpt, mgr:find); try_from_spark!(mgr::HardlinkOpt, mgr:hardlink); try_from_spark!(mgr::HiddenOpt, mgr:hidden); -try_from_spark!(mgr::HoverDoOpt, mgr:hover_do); try_from_spark!(mgr::HoverOpt, mgr:hover); try_from_spark!(mgr::LinemodeOpt, mgr:linemode); try_from_spark!(mgr::LinkOpt, mgr:link); diff --git a/yazi-fs/src/files.rs b/yazi-fs/src/files.rs index 402d71ac..c8711370 100644 --- a/yazi-fs/src/files.rs +++ b/yazi-fs/src/files.rs @@ -1,4 +1,4 @@ -use std::{collections::{HashMap, HashSet}, mem, ops::{Deref, Not}}; +use std::{collections::{HashMap, HashSet}, mem, ops::{Deref, DerefMut, Not}}; use tokio::{select, sync::mpsc::{self, UnboundedReceiver}}; use yazi_shared::{Id, url::{Url, Urn, UrnBuf}}; @@ -27,6 +27,10 @@ impl Deref for Files { fn deref(&self) -> &Self::Target { &self.items } } +impl DerefMut for Files { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.items } +} + impl Files { pub fn new(show_hidden: bool) -> Self { Self { show_hidden, ..Default::default() } } diff --git a/yazi-fs/src/sorter.rs b/yazi-fs/src/sorter.rs index 132ffd05..522eefc4 100644 --- a/yazi-fs/src/sorter.rs +++ b/yazi-fs/src/sorter.rs @@ -4,7 +4,7 @@ use yazi_shared::{LcgRng, natsort, translit::Transliterator, url::UrnBuf}; use crate::{File, SortBy}; -#[derive(Clone, Copy, Default, PartialEq)] +#[derive(Clone, Copy, Debug, Default, PartialEq)] pub struct FilesSorter { pub by: SortBy, pub sensitive: bool, diff --git a/yazi-macro/src/context.rs b/yazi-macro/src/context.rs new file mode 100644 index 00000000..30dae489 --- /dev/null +++ b/yazi-macro/src/context.rs @@ -0,0 +1,7 @@ +#[macro_export] +macro_rules! tab { + ($cx:ident) => {{ + let tab = $cx.tab; + &mut $cx.core.mgr.tabs.items[tab] + }}; +} diff --git a/yazi-macro/src/lib.rs b/yazi-macro/src/lib.rs index db8a7f4d..47918fb1 100644 --- a/yazi-macro/src/lib.rs +++ b/yazi-macro/src/lib.rs @@ -1,5 +1,6 @@ mod actor; mod asset; +mod context; mod event; mod fmt; mod log; diff --git a/yazi-parser/src/mgr/hidden.rs b/yazi-parser/src/mgr/hidden.rs index 1a451024..99069bc0 100644 --- a/yazi-parser/src/mgr/hidden.rs +++ b/yazi-parser/src/mgr/hidden.rs @@ -1,20 +1,19 @@ +use std::str::FromStr; + use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; +use serde::{Deserialize, Serialize}; use yazi_shared::event::CmdCow; -#[derive(Debug)] +#[derive(Debug, Default)] pub struct HiddenOpt { - pub state: Option, + pub state: HiddenOptState, } -impl From for HiddenOpt { - fn from(c: CmdCow) -> Self { - let state = match c.first_str() { - Some("show") => Some(true), - Some("hide") => Some(false), - _ => None, - }; +impl TryFrom for HiddenOpt { + type Error = anyhow::Error; - Self { state } + fn try_from(c: CmdCow) -> Result { + Ok(Self { state: c.first_str().map(FromStr::from_str).transpose()?.unwrap_or_default() }) } } @@ -25,3 +24,33 @@ impl FromLua for HiddenOpt { impl IntoLua for HiddenOpt { fn into_lua(self, _: &Lua) -> mlua::Result { Err("unsupported".into_lua_err()) } } + +// --- State +#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +#[serde(rename_all = "kebab-case")] +pub enum HiddenOptState { + #[default] + None, + Show, + Hide, + Toggle, +} + +impl FromStr for HiddenOptState { + type Err = serde::de::value::Error; + + fn from_str(s: &str) -> Result { + Self::deserialize(serde::de::value::StrDeserializer::new(s)) + } +} + +impl HiddenOptState { + pub fn bool(self, old: bool) -> bool { + match self { + Self::None => old, + Self::Show => true, + Self::Hide => false, + Self::Toggle => !old, + } + } +} diff --git a/yazi-parser/src/mgr/hover.rs b/yazi-parser/src/mgr/hover.rs index d381a341..8b0aeb16 100644 --- a/yazi-parser/src/mgr/hover.rs +++ b/yazi-parser/src/mgr/hover.rs @@ -1,17 +1,13 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; -use yazi_shared::{event::CmdCow, url::Url}; +use yazi_shared::url::UrnBuf; #[derive(Debug, Default)] pub struct HoverOpt { - pub url: Option, + pub urn: Option, } -impl From for HoverOpt { - fn from(mut c: CmdCow) -> Self { Self { url: c.take_first_url() } } -} - -impl From> for HoverOpt { - fn from(url: Option) -> Self { Self { url } } +impl From> for HoverOpt { + fn from(urn: Option) -> Self { Self { urn } } } impl FromLua for HoverOpt { @@ -21,21 +17,3 @@ impl FromLua for HoverOpt { impl IntoLua for HoverOpt { fn into_lua(self, _: &Lua) -> mlua::Result { Err("unsupported".into_lua_err()) } } - -// --- Do -#[derive(Debug)] -pub struct HoverDoOpt { - pub url: Url, -} - -impl From for HoverDoOpt { - fn from(url: Url) -> Self { Self { url } } -} - -impl FromLua for HoverDoOpt { - fn from_lua(_: Value, _: &Lua) -> mlua::Result { Err("unsupported".into_lua_err()) } -} - -impl IntoLua for HoverDoOpt { - fn into_lua(self, _: &Lua) -> mlua::Result { Err("unsupported".into_lua_err()) } -} diff --git a/yazi-parser/src/mgr/sort.rs b/yazi-parser/src/mgr/sort.rs index 5f2ac6c3..93f35934 100644 --- a/yazi-parser/src/mgr/sort.rs +++ b/yazi-parser/src/mgr/sort.rs @@ -4,7 +4,7 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; use yazi_fs::SortBy; use yazi_shared::event::CmdCow; -#[derive(Debug)] +#[derive(Debug, Default)] pub struct SortOpt { pub by: Option, pub reverse: Option, diff --git a/yazi-shared/src/url/urn.rs b/yazi-shared/src/url/urn.rs index 98ce60af..e850b05a 100644 --- a/yazi-shared/src/url/urn.rs +++ b/yazi-shared/src/url/urn.rs @@ -61,6 +61,12 @@ impl PartialEq> for &Urn { #[derive(Clone, Debug, Default, Eq, Hash, PartialEq, Serialize)] pub struct UrnBuf(PathBuf); +impl Deref for UrnBuf { + type Target = Urn; + + fn deref(&self) -> &Self::Target { self.borrow() } +} + impl Borrow for UrnBuf { fn borrow(&self) -> &Urn { Urn::new(&self.0) } } @@ -77,6 +83,10 @@ impl PartialEq for UrnBuf { fn eq(&self, other: &Urn) -> bool { self.0 == other.0 } } +impl PartialEq for Urn { + fn eq(&self, other: &UrnBuf) -> bool { self.0 == other.0 } +} + impl> From for UrnBuf { fn from(p: T) -> Self { Self(p.into()) } }