This commit is contained in:
sxyazi 2023-11-09 08:18:39 +08:00
parent bbe157bd9f
commit 67fcb484fb
No known key found for this signature in database
11 changed files with 58 additions and 76 deletions

View file

@ -20,7 +20,7 @@ pub async fn zoxide(opt: ZoxideOpt) -> Result<Url> {
let selected = String::from_utf8_lossy(&output.stdout).trim().to_string();
if !selected.is_empty() {
return Ok(Url::from(selected).push_slash());
return Ok(Url::from(selected));
}
bail!("No match")
}

View file

@ -39,7 +39,7 @@ impl File {
cm |= ChaMeta::BAD_LINK;
}
if url.was_hidden() {
if url.is_hidden() {
cm |= ChaMeta::HIDDEN;
}
@ -48,7 +48,7 @@ impl File {
#[inline]
pub fn from_dummy(url: Url) -> Self {
let cm = if url.was_hidden() { ChaMeta::HIDDEN } else { ChaMeta::empty() };
let cm = if url.is_hidden() { ChaMeta::HIDDEN } else { ChaMeta::empty() };
Self { url, cha: Cha::default().with_meta(cm), link_to: None }
}

View file

@ -3,14 +3,14 @@ use crate::tab::Tab;
impl Tab {
pub fn back(&mut self) -> bool {
if let Some(url) = self.backstack.shift_backward().cloned() {
self.cd(url.push_slash());
self.cd(url);
}
false
}
pub fn forward(&mut self) -> bool {
if let Some(url) = self.backstack.shift_forward().cloned() {
self.cd(url.push_slash());
self.cd(url);
}
false
}

View file

@ -1,26 +1,15 @@
use std::{mem, time::Duration};
use tokio::pin;
use tokio::{fs, pin};
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
use yazi_config::keymap::{Exec, KeymapLayer};
use yazi_shared::{expand_path, Debounce, InputError, Url};
use crate::{emit, files::{File, FilesOp}, input::InputOpt, tab::Tab};
use crate::{emit, input::InputOpt, tab::Tab};
impl Tab {
pub fn cd(&mut self, mut target: Url) -> bool {
let mut hovered = None;
if let (false, Some(parent)) = (target.pop_slash(), target.parent_url()) {
emit!(Files(FilesOp::Creating(parent.clone(), File::from_dummy(target.clone()).into_map())));
hovered = Some(target);
target = parent;
}
// Already in target
pub fn cd(&mut self, target: Url) -> bool {
if self.current.cwd == target {
if let Some(h) = hovered {
emit!(Hover(h));
}
return false;
}
@ -41,11 +30,6 @@ impl Tab {
self.parent = Some(self.history_new(&parent));
}
// Hover the file
if let Some(h) = hovered {
emit!(Hover(h));
}
// Backstack
if target.is_regular() {
self.backstack.push(target.clone());
@ -67,8 +51,16 @@ impl Tab {
while let Some(result) = rx.next().await {
match result {
Ok(s) => {
let p = expand_path(s);
let Ok(meta) = fs::metadata(&p).await else {
return;
};
emit!(Call(
Exec::call("cd", vec![expand_path(s).to_string_lossy().to_string()]).vec(),
Exec::call(if meta.is_dir() { "cd" } else { "reveal" }, vec![
p.to_string_lossy().to_string()
])
.vec(),
KeymapLayer::Manager
));
}

View file

@ -1,5 +1,5 @@
use yazi_config::keymap::{Exec, KeymapLayer};
use yazi_shared::Defer;
use yazi_shared::{ends_with_slash, Defer};
use crate::{emit, external::{self, FzfOpt, ZoxideOpt}, tab::Tab, Event, BLOCKER};
@ -18,7 +18,8 @@ impl Tab {
external::zoxide(ZoxideOpt { cwd }).await
}?;
emit!(Call(Exec::call("cd", vec![url.to_string()]).vec(), KeymapLayer::Manager));
let op = if global && !ends_with_slash(&url) { "reveal" } else { "cd" };
emit!(Call(Exec::call(op, vec![url.to_string()]).vec(), KeymapLayer::Manager));
Ok::<(), anyhow::Error>(())
});
false

View file

@ -9,6 +9,7 @@ mod hidden;
mod jump;
mod leave;
mod linemode;
mod reveal;
mod search;
mod select;
mod shell;

View file

@ -0,0 +1,28 @@
use yazi_config::keymap::Exec;
use yazi_shared::Url;
use crate::{emit, files::{File, FilesOp}, tab::Tab};
pub struct Opt<'a> {
target: &'a str,
}
impl<'a> From<&'a Exec> for Opt<'a> {
fn from(e: &'a Exec) -> Self { Self { target: e.args.first().map(|s| s.as_str()).unwrap_or("") } }
}
impl Tab {
pub fn reveal<'a>(&mut self, opt: impl Into<Opt<'a>>) -> bool {
let opt = opt.into() as Opt;
let target = Url::from(opt.target);
let Some(parent) = target.parent_url() else {
return false;
};
let b = self.cd(parent.clone());
emit!(Files(FilesOp::Creating(parent.clone(), File::from_dummy(target.clone()).into_map())));
emit!(Hover(target));
b
}
}

View file

@ -35,10 +35,7 @@ impl Tab {
let mut first = true;
while let Some(chunk) = rx.next().await {
if first {
emit!(Call(
Exec::call("cd", vec![cwd.clone().push_slash().to_string()]).vec(),
KeymapLayer::Manager
));
emit!(Call(Exec::call("cd", vec![cwd.clone().to_string()]).vec(), KeymapLayer::Manager));
first = false;
}
emit!(Files(FilesOp::Part(cwd.clone(), ticket, chunk)));

View file

@ -99,6 +99,7 @@ impl<'a> Executor<'a> {
self.cx.manager.active_mut().cd(expand_url(url))
}
}
"reveal" => self.cx.manager.active_mut().reveal(exec),
// Selection
"select" => {

View file

@ -1,4 +1,4 @@
use std::{borrow::Cow, env, ffi::OsString, path::{Component, Path, PathBuf, MAIN_SEPARATOR, MAIN_SEPARATOR_STR}};
use std::{borrow::Cow, env, ffi::OsString, path::{Component, Path, PathBuf, MAIN_SEPARATOR}};
use tokio::fs;
@ -20,24 +20,13 @@ fn _expand_path(p: &Path) -> PathBuf {
});
let p = Path::new(s.as_ref());
if let (slash, Ok(rest)) = (ends_with_slash(p), p.strip_prefix("~")) {
if let Ok(rest) = p.strip_prefix("~") {
#[cfg(unix)]
let Some(home) = env::var_os("HOME") else {
return rest.to_path_buf();
};
let home = env::var_os("HOME");
#[cfg(windows)]
let Some(home) = env::var_os("USERPROFILE") else {
return rest.to_path_buf();
};
let home = env::var_os("USERPROFILE");
let mut home = PathBuf::from(home);
pop_end_slash(&mut home);
let mut p = if rest == Path::new("") { home } else { home.join(rest) };
if slash {
p.as_mut_os_string().push(MAIN_SEPARATOR_STR);
}
return p;
return if let Some(p) = home { PathBuf::from(p).join(rest) } else { rest.to_path_buf() };
}
if p.is_absolute() {
@ -76,18 +65,6 @@ pub fn ends_with_slash(p: &Path) -> bool {
}
}
#[inline]
#[allow(clippy::unnecessary_to_owned)]
pub fn pop_end_slash(p: &mut PathBuf) -> bool {
if !ends_with_slash(p) {
return false;
}
if let Some(n) = p.file_name() {
p.set_file_name(n.to_owned());
}
true
}
pub async fn unique_path(mut p: Url) -> Url {
let Some(stem) = p.file_stem().map(|s| s.to_owned()) else {
return p;

View file

@ -1,9 +1,7 @@
use std::{ffi::{OsStr, OsString}, fmt::{Debug, Formatter}, ops::{Deref, DerefMut}, path::{Path, PathBuf, MAIN_SEPARATOR_STR}};
use std::{ffi::{OsStr, OsString}, fmt::{Debug, Formatter}, ops::{Deref, DerefMut}, path::{Path, PathBuf}};
use percent_encoding::{percent_decode_str, percent_encode, AsciiSet, CONTROLS};
use crate::{ends_with_slash, pop_end_slash};
const ENCODE_SET: &AsciiSet = &CONTROLS.add(b'#');
#[derive(Clone, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
@ -155,22 +153,9 @@ impl Url {
pub fn into_os_string(self) -> OsString { self.path.into_os_string() }
#[inline]
pub fn was_hidden(&self) -> bool {
pub fn is_hidden(&self) -> bool {
self.file_name().map_or(false, |s| s.to_string_lossy().starts_with('.'))
}
#[inline]
pub fn pop_slash(&mut self) -> bool { pop_end_slash(self) }
#[inline]
pub fn push_slash(mut self) -> Self {
if !ends_with_slash(&self) {
self
} else {
self.path.as_mut_os_string().push(MAIN_SEPARATOR_STR);
self
}
}
}
impl Url {