Skip to content

Commit a8f2498

Browse files
authored
feat: new stash command to let users customize back and forward command behavior (#3380)
1 parent 3561867 commit a8f2498

File tree

32 files changed

+669
-205
lines changed

32 files changed

+669
-205
lines changed

yazi-actor/src/context.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,5 @@ impl<'a> Ctx<'a> {
118118
pub fn tasks(&self) -> &Tasks { &self.tasks }
119119

120120
#[inline]
121-
pub fn source(&self) -> Source {
122-
use Source::*;
123-
match self.source {
124-
Key if self.level != 1 => Ind,
125-
Emit if self.level != 1 => EmitInd,
126-
Relay if self.level != 1 => RelayInd,
127-
s => s,
128-
}
129-
}
121+
pub fn source(&self) -> Source { if self.level != 1 { Source::Ind } else { self.source } }
130122
}

yazi-actor/src/mgr/back.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ impl Actor for Back {
1414

1515
fn act(cx: &mut Ctx, _: Self::Options) -> Result<Data> {
1616
if let Some(u) = cx.tab_mut().backstack.shift_backward().cloned() {
17-
return act!(mgr:cd, cx, (u, CdSource::Back));
17+
act!(mgr:cd, cx, (u, CdSource::Back))?;
1818
}
1919
succ!();
2020
}

yazi-actor/src/mgr/cd.rs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use yazi_fs::{File, FilesOp, path::expand_url};
99
use yazi_macro::{act, err, render, succ};
1010
use yazi_parser::mgr::CdOpt;
1111
use yazi_proxy::{CmpProxy, InputProxy, MgrProxy};
12-
use yazi_shared::{Debounce, data::Data, errors::InputError, url::{AsUrl, UrlBuf, UrlLike}};
12+
use yazi_shared::{Debounce, data::Data, errors::InputError, url::{UrlBuf, UrlLike}};
1313
use yazi_vfs::VfsFile;
1414

1515
use crate::{Actor, Ctx};
@@ -33,18 +33,8 @@ impl Actor for Cd {
3333
}
3434

3535
// Take parent to history
36-
if let Some(rep) = tab.parent.take() {
37-
tab.history.insert(rep.url.to_owned(), rep);
38-
}
39-
40-
// Backstack
41-
if opt.source.big_jump() {
42-
if tab.current.url.is_regular() {
43-
tab.backstack.push(tab.current.url.as_url());
44-
}
45-
if opt.target.is_regular() {
46-
tab.backstack.push(opt.target.as_url());
47-
}
36+
if let Some(t) = tab.parent.take() {
37+
tab.history.insert(t.url.to_owned(), t);
4838
}
4939

5040
// Current
@@ -58,10 +48,12 @@ impl Actor for Cd {
5848
}
5949

6050
err!(Pubsub::pub_after_cd(tab.id, tab.cwd()));
51+
act!(mgr:displace, cx)?;
6152
act!(mgr:hidden, cx)?;
6253
act!(mgr:sort, cx)?;
6354
act!(mgr:hover, cx)?;
6455
act!(mgr:refresh, cx)?;
56+
act!(mgr:stash, cx, opt).ok();
6557
succ!(render!());
6658
}
6759
}

yazi-actor/src/mgr/displace.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use anyhow::{Result, bail};
2+
use yazi_macro::{act, succ};
3+
use yazi_parser::{VoidOpt, mgr::{CdSource, DisplaceDoOpt}};
4+
use yazi_proxy::MgrProxy;
5+
use yazi_shared::{data::Data, url::UrlLike};
6+
use yazi_vfs::provider;
7+
8+
use crate::{Actor, Ctx};
9+
10+
pub struct Displace;
11+
12+
impl Actor for Displace {
13+
type Options = VoidOpt;
14+
15+
const NAME: &str = "displace";
16+
17+
fn act(cx: &mut Ctx, _: Self::Options) -> Result<Data> {
18+
if cx.cwd().is_absolute() {
19+
succ!();
20+
}
21+
22+
let tab = cx.tab().id;
23+
let from = cx.cwd().to_owned();
24+
tokio::spawn(async move {
25+
if let Ok(to) = provider::absolute(&from).await
26+
&& to.is_owned()
27+
{
28+
MgrProxy::displace_do(tab, DisplaceDoOpt { to: to.into(), from });
29+
}
30+
});
31+
32+
succ!();
33+
}
34+
}
35+
36+
// --- Do
37+
pub struct DisplaceDo;
38+
39+
impl Actor for DisplaceDo {
40+
type Options = DisplaceDoOpt;
41+
42+
const NAME: &str = "displace_do";
43+
44+
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
45+
if !opt.to.is_absolute() {
46+
bail!("Target URL must be absolute");
47+
}
48+
49+
if cx.cwd() != opt.from {
50+
succ!()
51+
} else if let Some(hovered) = cx.hovered()
52+
&& let Ok(url) = opt.to.try_join(hovered.urn())
53+
{
54+
act!(mgr:reveal, cx, (url, CdSource::Displace))
55+
} else {
56+
act!(mgr:cd, cx, (opt.to, CdSource::Displace))
57+
}
58+
}
59+
}

yazi-actor/src/mgr/forward.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ impl Actor for Forward {
1313
const NAME: &str = "forward";
1414

1515
fn act(cx: &mut Ctx, _: Self::Options) -> Result<Data> {
16-
match cx.tab_mut().backstack.shift_forward().cloned() {
17-
Some(u) => act!(mgr:cd, cx, (u, CdSource::Forward)),
18-
None => succ!(),
16+
if let Some(u) = cx.tab_mut().backstack.shift_forward().cloned() {
17+
act!(mgr:cd, cx, (u, CdSource::Forward))?;
1918
}
19+
succ!()
2020
}
2121
}

yazi-actor/src/mgr/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ yazi_macro::mod_flat!(
66
close
77
copy
88
create
9+
displace
910
download
1011
enter
1112
escape
@@ -36,6 +37,7 @@ yazi_macro::mod_flat!(
3637
shell
3738
sort
3839
spot
40+
stash
3941
suspend
4042
tab_close
4143
tab_create

yazi-actor/src/mgr/search.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
use std::{borrow::Cow, mem, time::Duration};
1+
use std::{borrow::Cow, time::Duration};
22

33
use anyhow::Result;
44
use tokio::pin;
55
use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
66
use yazi_config::popup::InputCfg;
77
use yazi_fs::{FilesOp, cha::Cha};
88
use yazi_macro::{act, succ};
9-
use yazi_parser::{VoidOpt, mgr::{SearchOpt, SearchOptVia}};
9+
use yazi_parser::{VoidOpt, mgr::{CdSource, SearchOpt, SearchOptVia}};
1010
use yazi_plugin::external;
1111
use yazi_proxy::{InputProxy, MgrProxy};
1212
use yazi_shared::data::Data;
@@ -107,15 +107,10 @@ impl Actor for SearchStop {
107107
handle.abort();
108108
}
109109

110-
if !tab.cwd().is_search() {
111-
succ!();
110+
if tab.cwd().is_search() {
111+
act!(mgr:cd, cx, (tab.cwd().to_regular()?, CdSource::Escape))?;
112112
}
113113

114-
let rep = tab.history.remove_or(tab.cwd().to_regular()?);
115-
drop(mem::replace(&mut tab.current, rep));
116-
117-
act!(mgr:hidden, cx)?;
118-
act!(mgr:sort, cx)?;
119-
act!(mgr:refresh, cx)
114+
succ!();
120115
}
121116
}

yazi-actor/src/mgr/stash.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use anyhow::Result;
2+
use yazi_dds::spark::SparkKind;
3+
use yazi_macro::succ;
4+
use yazi_parser::mgr::StashOpt;
5+
use yazi_shared::{Source, data::Data, url::AsUrl};
6+
7+
use crate::{Actor, Ctx};
8+
9+
pub struct Stash;
10+
11+
impl Actor for Stash {
12+
type Options = StashOpt;
13+
14+
const NAME: &str = "stash";
15+
16+
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
17+
if opt.target.is_regular() {
18+
cx.tab_mut().backstack.push(opt.target.as_url());
19+
}
20+
21+
succ!()
22+
}
23+
24+
fn hook(cx: &Ctx, _opt: &Self::Options) -> Option<SparkKind> {
25+
match cx.source() {
26+
Source::Relay => Some(SparkKind::RelayStash),
27+
Source::Ind => Some(SparkKind::IndStash),
28+
_ => None,
29+
}
30+
}
31+
}

yazi-binding/src/url.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ impl From<Url> for yazi_shared::url::UrlBufCov {
4949
fn from(value: Url) -> Self { Self(value.inner) }
5050
}
5151

52+
impl From<Url> for yazi_shared::url::UrlCow<'_> {
53+
fn from(value: Url) -> Self { value.inner.into() }
54+
}
55+
5256
impl TryFrom<&[u8]> for Url {
5357
type Error = mlua::Error;
5458

yazi-config/src/which/sorting.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use serde::{Deserialize, Serialize};
22

3-
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
3+
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
44
#[serde(rename_all = "kebab-case")]
55
pub enum SortBy {
66
#[default]

0 commit comments

Comments
 (0)