mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
Add the excluded command to toggle/show/hide excluded files via keymaps
This commit is contained in:
parent
e32db2a539
commit
f068dafec2
7 changed files with 150 additions and 4 deletions
52
yazi-actor/src/mgr/excluded.rs
Normal file
52
yazi-actor/src/mgr/excluded.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
use anyhow::Result;
|
||||
use yazi_core::tab::Folder;
|
||||
use yazi_fs::FolderStage;
|
||||
use yazi_macro::{act, render, render_and, succ};
|
||||
use yazi_parser::mgr::ExcludedOpt;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Excluded;
|
||||
|
||||
impl Actor for Excluded {
|
||||
type Options = ExcludedOpt;
|
||||
|
||||
const NAME: &str = "excluded";
|
||||
|
||||
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
|
||||
let state = opt.state.bool(cx.tab().current.files.show_excluded());
|
||||
let hovered = cx.hovered().map(|f| f.urn().to_owned());
|
||||
|
||||
let apply = |f: &mut Folder| {
|
||||
if f.stage == FolderStage::Loading {
|
||||
render!();
|
||||
false
|
||||
} else {
|
||||
f.files.set_show_excluded(state);
|
||||
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)?;
|
||||
}
|
||||
|
||||
// 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!()
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ yazi_macro::mod_flat!(
|
|||
enter
|
||||
escape
|
||||
exclude_add
|
||||
excluded
|
||||
filter
|
||||
filter_do
|
||||
find
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ pub enum Spark<'a> {
|
|||
EscapeSelect(yazi_parser::VoidOpt),
|
||||
EscapeVisual(yazi_parser::VoidOpt),
|
||||
ExcludeAdd(yazi_parser::mgr::ExcludeAddOpt),
|
||||
Excluded(yazi_parser::mgr::ExcludedOpt),
|
||||
Filter(yazi_parser::mgr::FilterOpt),
|
||||
FilterDo(yazi_parser::mgr::FilterOpt),
|
||||
Find(yazi_parser::mgr::FindOpt),
|
||||
|
|
@ -149,6 +150,7 @@ impl<'a> IntoLua for Spark<'a> {
|
|||
Self::EscapeSelect(b) => b.into_lua(lua),
|
||||
Self::EscapeVisual(b) => b.into_lua(lua),
|
||||
Self::ExcludeAdd(b) => b.into_lua(lua),
|
||||
Self::Excluded(b) => b.into_lua(lua),
|
||||
Self::Filter(b) => b.into_lua(lua),
|
||||
Self::FilterDo(b) => b.into_lua(lua),
|
||||
Self::Find(b) => b.into_lua(lua),
|
||||
|
|
@ -310,6 +312,7 @@ try_from_spark!(mgr::RevealOpt, mgr:reveal);
|
|||
try_from_spark!(mgr::SearchOpt, mgr:search, mgr:search_do);
|
||||
try_from_spark!(mgr::SeekOpt, mgr:seek);
|
||||
try_from_spark!(mgr::ShellOpt, mgr:shell);
|
||||
try_from_spark!(mgr::ExcludedOpt, mgr:excluded);
|
||||
try_from_spark!(mgr::SortOpt, mgr:sort);
|
||||
try_from_spark!(mgr::SpotOpt, mgr:spot);
|
||||
try_from_spark!(mgr::TabCloseOpt, mgr:tab_close);
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ impl<'a> Executor<'a> {
|
|||
on!(copy);
|
||||
on!(shell);
|
||||
on!(hidden);
|
||||
on!(excluded);
|
||||
on!(ignore);
|
||||
on!(linemode);
|
||||
on!(search);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ pub struct Files {
|
|||
sorter: FilesSorter,
|
||||
filter: Option<Filter>,
|
||||
show_hidden: bool,
|
||||
show_excluded: bool,
|
||||
ignore_filter: Option<IgnoreFilter>,
|
||||
}
|
||||
|
||||
|
|
@ -261,12 +262,23 @@ impl Files {
|
|||
files.into_iter().partition(|f| {
|
||||
(f.is_hidden() && !self.show_hidden)
|
||||
|| !filter.matches(f.urn())
|
||||
|| self.ignore_filter.as_ref().is_some_and(|ig| ig.matches_url(&f.url))
|
||||
|| (!self.show_excluded
|
||||
&& self.ignore_filter.as_ref().is_some_and(|ig| ig.matches_url(&f.url)))
|
||||
})
|
||||
} else if let Some(ignore_filter) = &self.ignore_filter {
|
||||
files
|
||||
.into_iter()
|
||||
.partition(|f| (f.is_hidden() && !self.show_hidden) || ignore_filter.matches_url(&f.url))
|
||||
if self.show_excluded {
|
||||
// Show excluded files - only hide based on hidden status
|
||||
if self.show_hidden {
|
||||
(vec![], files.into_iter().collect())
|
||||
} else {
|
||||
files.into_iter().partition(|f| f.is_hidden())
|
||||
}
|
||||
} else {
|
||||
// Hide excluded files - apply ignore filter
|
||||
files
|
||||
.into_iter()
|
||||
.partition(|f| (f.is_hidden() && !self.show_hidden) || ignore_filter.matches_url(&f.url))
|
||||
}
|
||||
} else if self.show_hidden {
|
||||
(vec![], files.into_iter().collect())
|
||||
} else {
|
||||
|
|
@ -341,6 +353,26 @@ impl Files {
|
|||
true
|
||||
}
|
||||
|
||||
// --- Show excluded
|
||||
#[inline]
|
||||
pub fn show_excluded(&self) -> bool { self.show_excluded }
|
||||
|
||||
pub fn set_show_excluded(&mut self, state: bool) -> bool {
|
||||
if self.show_excluded == state {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.show_excluded = state;
|
||||
|
||||
// Re-split files with the new state
|
||||
let it = mem::take(&mut self.items).into_iter().chain(mem::take(&mut self.hidden));
|
||||
(self.hidden, self.items) = self.split_files(it);
|
||||
self.sorter.sort(&mut self.items, &self.sizes);
|
||||
self.revision += 1;
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
// --- Show hidden
|
||||
pub fn set_show_hidden(&mut self, state: bool) {
|
||||
if self.show_hidden == state {
|
||||
|
|
|
|||
56
yazi-parser/src/mgr/excluded.rs
Normal file
56
yazi-parser/src/mgr/excluded.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yazi_shared::event::CmdCow;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ExcludedOpt {
|
||||
pub state: ExcludedOptState,
|
||||
}
|
||||
|
||||
impl TryFrom<CmdCow> for ExcludedOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(c: CmdCow) -> Result<Self, Self::Error> {
|
||||
Ok(Self { state: c.str(0).parse().unwrap_or_default() })
|
||||
}
|
||||
}
|
||||
|
||||
impl FromLua for ExcludedOpt {
|
||||
fn from_lua(_: Value, _: &Lua) -> mlua::Result<Self> { Err("unsupported".into_lua_err()) }
|
||||
}
|
||||
|
||||
impl IntoLua for ExcludedOpt {
|
||||
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 ExcludedOptState {
|
||||
#[default]
|
||||
None,
|
||||
Show,
|
||||
Hide,
|
||||
Toggle,
|
||||
}
|
||||
|
||||
impl FromStr for ExcludedOptState {
|
||||
type Err = serde::de::value::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Self::deserialize(serde::de::value::StrDeserializer::new(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl ExcludedOptState {
|
||||
pub fn bool(self, old: bool) -> bool {
|
||||
match self {
|
||||
Self::None => old,
|
||||
Self::Show => true,
|
||||
Self::Hide => false,
|
||||
Self::Toggle => !old,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ yazi_macro::mod_flat!(
|
|||
download
|
||||
escape
|
||||
exclude_add
|
||||
excluded
|
||||
filter
|
||||
find
|
||||
find_arrow
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue