mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-23 07:41:03 +00:00
refactor: simplify cursor repositioning (#3040)
This commit is contained in:
parent
41b00c8d4e
commit
292d37ccde
25 changed files with 209 additions and 164 deletions
|
|
@ -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 }
|
||||
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -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!());
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Data> {
|
||||
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!()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Data> {
|
||||
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<Data> {
|
||||
// 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!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Data> {
|
||||
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!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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!());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<impl AsRef<Urn>>) -> 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();
|
||||
|
|
|
|||
|
|
@ -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<Rect> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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() } }
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
7
yazi-macro/src/context.rs
Normal file
7
yazi-macro/src/context.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#[macro_export]
|
||||
macro_rules! tab {
|
||||
($cx:ident) => {{
|
||||
let tab = $cx.tab;
|
||||
&mut $cx.core.mgr.tabs.items[tab]
|
||||
}};
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
mod actor;
|
||||
mod asset;
|
||||
mod context;
|
||||
mod event;
|
||||
mod fmt;
|
||||
mod log;
|
||||
|
|
|
|||
|
|
@ -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<bool>,
|
||||
pub state: HiddenOptState,
|
||||
}
|
||||
|
||||
impl From<CmdCow> for HiddenOpt {
|
||||
fn from(c: CmdCow) -> Self {
|
||||
let state = match c.first_str() {
|
||||
Some("show") => Some(true),
|
||||
Some("hide") => Some(false),
|
||||
_ => None,
|
||||
};
|
||||
impl TryFrom<CmdCow> for HiddenOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
Self { state }
|
||||
fn try_from(c: CmdCow) -> Result<Self, Self::Error> {
|
||||
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<Value> { 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, Self::Err> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Url>,
|
||||
pub urn: Option<UrnBuf>,
|
||||
}
|
||||
|
||||
impl From<CmdCow> for HoverOpt {
|
||||
fn from(mut c: CmdCow) -> Self { Self { url: c.take_first_url() } }
|
||||
}
|
||||
|
||||
impl From<Option<Url>> for HoverOpt {
|
||||
fn from(url: Option<Url>) -> Self { Self { url } }
|
||||
impl From<Option<UrnBuf>> for HoverOpt {
|
||||
fn from(urn: Option<UrnBuf>) -> 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<Value> { Err("unsupported".into_lua_err()) }
|
||||
}
|
||||
|
||||
// --- Do
|
||||
#[derive(Debug)]
|
||||
pub struct HoverDoOpt {
|
||||
pub url: Url,
|
||||
}
|
||||
|
||||
impl From<Url> for HoverDoOpt {
|
||||
fn from(url: Url) -> Self { Self { url } }
|
||||
}
|
||||
|
||||
impl FromLua for HoverDoOpt {
|
||||
fn from_lua(_: Value, _: &Lua) -> mlua::Result<Self> { Err("unsupported".into_lua_err()) }
|
||||
}
|
||||
|
||||
impl IntoLua for HoverDoOpt {
|
||||
fn into_lua(self, _: &Lua) -> mlua::Result<Value> { Err("unsupported".into_lua_err()) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<SortBy>,
|
||||
pub reverse: Option<bool>,
|
||||
|
|
|
|||
|
|
@ -61,6 +61,12 @@ impl PartialEq<Cow<'_, OsStr>> 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<Urn> for UrnBuf {
|
||||
fn borrow(&self) -> &Urn { Urn::new(&self.0) }
|
||||
}
|
||||
|
|
@ -77,6 +83,10 @@ impl PartialEq<Urn> for UrnBuf {
|
|||
fn eq(&self, other: &Urn) -> bool { self.0 == other.0 }
|
||||
}
|
||||
|
||||
impl PartialEq<UrnBuf> for Urn {
|
||||
fn eq(&self, other: &UrnBuf) -> bool { self.0 == other.0 }
|
||||
}
|
||||
|
||||
impl<T: Into<PathBuf>> From<T> for UrnBuf {
|
||||
fn from(p: T) -> Self { Self(p.into()) }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue