mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
8100598224
commit
bbe157bd9f
6 changed files with 61 additions and 46 deletions
2
yazi-core/src/external/zoxide.rs
vendored
2
yazi-core/src/external/zoxide.rs
vendored
|
|
@ -20,7 +20,7 @@ pub async fn zoxide(opt: ZoxideOpt) -> Result<Url> {
|
||||||
let selected = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
let selected = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||||
|
|
||||||
if !selected.is_empty() {
|
if !selected.is_empty() {
|
||||||
return Ok(Url::from(selected).into_dir());
|
return Ok(Url::from(selected).push_slash());
|
||||||
}
|
}
|
||||||
bail!("No match")
|
bail!("No match")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@ use crate::tab::Tab;
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn back(&mut self) -> bool {
|
pub fn back(&mut self) -> bool {
|
||||||
if let Some(url) = self.backstack.shift_backward().cloned() {
|
if let Some(url) = self.backstack.shift_backward().cloned() {
|
||||||
self.cd(url.into_dir());
|
self.cd(url.push_slash());
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn forward(&mut self) -> bool {
|
pub fn forward(&mut self) -> bool {
|
||||||
if let Some(url) = self.backstack.shift_forward().cloned() {
|
if let Some(url) = self.backstack.shift_forward().cloned() {
|
||||||
self.cd(url.into_dir());
|
self.cd(url.push_slash());
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use crate::{emit, files::{File, FilesOp}, input::InputOpt, tab::Tab};
|
||||||
impl Tab {
|
impl Tab {
|
||||||
pub fn cd(&mut self, mut target: Url) -> bool {
|
pub fn cd(&mut self, mut target: Url) -> bool {
|
||||||
let mut hovered = None;
|
let mut hovered = None;
|
||||||
if let (false, Some(parent)) = (target.pop_dir(), target.parent_url()) {
|
if let (false, Some(parent)) = (target.pop_slash(), target.parent_url()) {
|
||||||
emit!(Files(FilesOp::Creating(parent.clone(), File::from_dummy(target.clone()).into_map())));
|
emit!(Files(FilesOp::Creating(parent.clone(), File::from_dummy(target.clone()).into_map())));
|
||||||
hovered = Some(target);
|
hovered = Some(target);
|
||||||
target = parent;
|
target = parent;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ impl Tab {
|
||||||
while let Some(chunk) = rx.next().await {
|
while let Some(chunk) = rx.next().await {
|
||||||
if first {
|
if first {
|
||||||
emit!(Call(
|
emit!(Call(
|
||||||
Exec::call("cd", vec![cwd.clone().into_dir().to_string()]).vec(),
|
Exec::call("cd", vec![cwd.clone().push_slash().to_string()]).vec(),
|
||||||
KeymapLayer::Manager
|
KeymapLayer::Manager
|
||||||
));
|
));
|
||||||
first = false;
|
first = false;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{borrow::Cow, env, ffi::OsString, path::{Component, Path, PathBuf}};
|
use std::{borrow::Cow, env, ffi::OsString, path::{Component, Path, PathBuf, MAIN_SEPARATOR, MAIN_SEPARATOR_STR}};
|
||||||
|
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
|
|
||||||
|
|
@ -20,15 +20,24 @@ fn _expand_path(p: &Path) -> PathBuf {
|
||||||
});
|
});
|
||||||
|
|
||||||
let p = Path::new(s.as_ref());
|
let p = Path::new(s.as_ref());
|
||||||
if let Ok(p) = p.strip_prefix("~") {
|
if let (slash, Ok(rest)) = (ends_with_slash(p), p.strip_prefix("~")) {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
if let Some(home) = env::var_os("HOME") {
|
let Some(home) = env::var_os("HOME") else {
|
||||||
return Path::new(&home).join(p);
|
return rest.to_path_buf();
|
||||||
}
|
};
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
if let Some(home) = env::var_os("USERPROFILE") {
|
let Some(home) = env::var_os("USERPROFILE") else {
|
||||||
return Path::new(&home).join(p);
|
return rest.to_path_buf();
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.is_absolute() {
|
if p.is_absolute() {
|
||||||
|
|
@ -46,6 +55,39 @@ pub fn expand_url(mut u: Url) -> Url {
|
||||||
u
|
u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn ends_with_slash(p: &Path) -> bool {
|
||||||
|
// TODO: uncomment this when Rust 1.74 is released
|
||||||
|
// let b = p.as_os_str().as_encoded_bytes();
|
||||||
|
// if let [.., last] = b { *last == MAIN_SEPARATOR as u8 } else { false }
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
let b = p.as_os_str().as_bytes();
|
||||||
|
if let [.., last] = b { *last == MAIN_SEPARATOR as u8 } else { false }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
let s = p.to_string_lossy();
|
||||||
|
let b = s.as_bytes();
|
||||||
|
if let [.., last] = b { *last == MAIN_SEPARATOR as u8 } else { false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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 {
|
pub async fn unique_path(mut p: Url) -> Url {
|
||||||
let Some(stem) = p.file_stem().map(|s| s.to_owned()) else {
|
let Some(stem) = p.file_stem().map(|s| s.to_owned()) else {
|
||||||
return p;
|
return p;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
use std::{ffi::{OsStr, OsString}, fmt::{Debug, Formatter}, ops::{Deref, DerefMut}, path::{Path, PathBuf, MAIN_SEPARATOR}};
|
use std::{ffi::{OsStr, OsString}, fmt::{Debug, Formatter}, ops::{Deref, DerefMut}, path::{Path, PathBuf, MAIN_SEPARATOR_STR}};
|
||||||
|
|
||||||
use percent_encoding::{percent_decode_str, percent_encode, AsciiSet, CONTROLS};
|
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'#');
|
const ENCODE_SET: &AsciiSet = &CONTROLS.add(b'#');
|
||||||
|
|
||||||
#[derive(Clone, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
#[derive(Clone, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
|
|
@ -158,43 +160,14 @@ impl Url {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn was_dir(&self) -> bool {
|
pub fn pop_slash(&mut self) -> bool { pop_end_slash(self) }
|
||||||
// TODO: uncomment this when Rust 1.74 is released
|
|
||||||
// let b = self.path.as_os_str().as_encoded_bytes();
|
|
||||||
// if let [.., last] = b { *last == MAIN_SEPARATOR as u8 } else { false }
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
{
|
|
||||||
use std::os::unix::ffi::OsStrExt;
|
|
||||||
let b = self.path.as_os_str().as_bytes();
|
|
||||||
if let [.., last] = b { *last == MAIN_SEPARATOR as u8 } else { false }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
{
|
|
||||||
let s = self.path.to_string_lossy();
|
|
||||||
let b = s.as_bytes();
|
|
||||||
if let [.., last] = b { *last == MAIN_SEPARATOR as u8 } else { false }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pop_dir(&mut self) -> bool {
|
pub fn push_slash(mut self) -> Self {
|
||||||
if !self.was_dir() {
|
if !ends_with_slash(&self) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if let Some(n) = self.path.file_name() {
|
|
||||||
self.path.set_file_name(n.to_owned());
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn into_dir(mut self) -> Self {
|
|
||||||
if self.was_dir() {
|
|
||||||
self
|
self
|
||||||
} else {
|
} else {
|
||||||
self.path.as_mut_os_string().push("/");
|
self.path.as_mut_os_string().push(MAIN_SEPARATOR_STR);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue