This commit is contained in:
sxyazi 2023-09-06 22:53:07 +08:00
parent 358ce77581
commit 59eec67c35
No known key found for this signature in database
13 changed files with 91 additions and 49 deletions

View file

@ -71,8 +71,8 @@ macro_rules! emit {
$crate::Event::Ctrl($exec, $layer).emit();
};
(Cd($op:expr)) => {
$crate::Event::Cd($op).emit();
(Cd($url:expr)) => {
$crate::Event::Cd($url).emit();
};
(Files($op:expr)) => {
$crate::Event::Files($op).emit();

View file

@ -17,12 +17,11 @@ pub fn zoxide(opt: ZoxideOpt) -> Result<Receiver<Result<Url>>> {
.spawn()?;
let (tx, rx) = oneshot::channel();
let cwd = opt.cwd.clone();
tokio::spawn(async move {
if let Ok(output) = child.wait_with_output().await {
let selected = String::from_utf8_lossy(&output.stdout).trim().to_string();
if !selected.is_empty() {
tx.send(Ok(Url::new(selected, &cwd))).ok();
tx.send(Ok(Url::from(selected))).ok();
return;
}
}

View file

@ -46,13 +46,12 @@ impl Files {
let mut it = fs::read_dir(url).await?;
let (tx, rx) = mpsc::unbounded_channel();
let url = url.clone();
tokio::spawn(async move {
while let Ok(Some(item)) = it.next_entry().await {
select! {
_ = tx.closed() => break,
Ok(meta) = item.metadata() => {
tx.send(File::from_meta(Url::new(item.path(), &url), meta).await).ok();
tx.send(File::from_meta(Url::from(item.path()), meta).await).ok();
}
}
}
@ -82,10 +81,23 @@ impl Files {
pub fn select_all(&mut self, state: Option<bool>) -> bool {
match state {
Some(true) => {
let b = if self.selected.len() < self.items.len() {
true
} else {
self.items.iter().any(|f| !self.selected.contains(&f.url))
};
self.selected = self.iter().map(|f| f.url_owned()).collect();
b
}
Some(false) => {
if self.selected.is_empty() {
return false;
}
let b = self.items.iter().any(|f| self.selected.contains(&f.url));
self.selected.clear();
b
}
None => {
for item in &self.items {
@ -95,9 +107,9 @@ impl Files {
self.selected.insert(item.url_owned());
}
}
!self.items.is_empty()
}
}
!self.items.is_empty()
}
pub fn select_index(&mut self, indices: &BTreeSet<usize>, state: Option<bool>) -> bool {
@ -169,7 +181,7 @@ impl Files {
}
#[inline]
pub fn position(&self, url: &Url) -> Option<usize> { self.iter().position(|f| f.url == *url) }
pub fn position(&self, url: &Url) -> Option<usize> { self.iter().position(|f| &f.url == url) }
#[inline]
pub fn duplicate(&self, idx: usize) -> Option<File> { self.items.get(idx).cloned() }

View file

@ -17,14 +17,13 @@ pub enum FilesOp {
impl FilesOp {
#[inline]
pub fn url(&self) -> Url {
pub fn url(&self) -> &Url {
match self {
Self::Full(url, _) => url,
Self::Part(url, ..) => url,
Self::Size(url, _) => url,
Self::IOErr(url) => url,
}
.clone()
}
#[inline]

View file

@ -308,7 +308,7 @@ impl Input {
};
snap.cursor = snap.count().saturating_sub(snap.mode.delta()).min(snap.cursor);
if *snap == old {
if snap == &old {
return false;
}
if !matches!(old.op, InputOp::None | InputOp::Select(_)) {

View file

@ -189,7 +189,7 @@ impl Manager {
fs::File::create(path).await?;
}
if let Ok(file) = File::from(Url::new(hovered, &cwd)).await {
if let Ok(file) = File::from(Url::from(hovered)).await {
emit!(Hover(file));
emit!(Refresh);
}
@ -326,7 +326,7 @@ impl Manager {
}
pub fn update_read(&mut self, op: FilesOp) -> bool {
let url = op.url();
let url = op.url().clone();
let cwd = self.cwd().to_owned();
let hovered = self.hovered().map(|h| h.url_owned());
@ -337,7 +337,7 @@ impl Manager {
} else {
self.active_mut().history.entry(url.clone()).or_insert_with(|| Folder::from(&url)).update(op);
matches!(self.hovered(), Some(h) if *h.url() == url)
matches!(self.hovered(), Some(h) if h.url() == &url)
};
b |= self.active_mut().parent.as_mut().map_or(false, |p| p.hover(&cwd));
@ -353,9 +353,9 @@ impl Manager {
let url = op.url();
let op = FilesOp::Full(url.clone(), Vec::new());
if url == *self.cwd() {
if url == self.cwd() {
self.current_mut().update(op);
} else if matches!(self.parent(), Some(p) if p.cwd == url) {
} else if matches!(self.parent(), Some(p) if &p.cwd == url) {
self.active_mut().parent.as_mut().unwrap().update(op);
} else {
return false;

View file

@ -169,7 +169,7 @@ impl Preview {
#[inline]
pub fn same(&self, url: &Url, mime: &str) -> bool {
if let Some(ref lock) = self.lock {
return lock.url == *url && lock.mime == mime && lock.skip == self.skip;
return &lock.url == url && lock.mime == mime && lock.skip == self.skip;
}
false
}
@ -177,7 +177,7 @@ impl Preview {
#[inline]
pub fn same_mime(&self, url: &Url, mime: &str) -> bool {
if let Some(ref lock) = self.lock {
return lock.url == *url && lock.mime == mime;
return &lock.url == url && lock.mime == mime;
}
false
}
@ -185,7 +185,7 @@ impl Preview {
#[inline]
pub fn same_path(&self, url: &Url) -> bool {
if let Some(ref lock) = self.lock {
return lock.url == *url;
return &lock.url == url;
}
false
}

View file

@ -106,7 +106,7 @@ impl Tab {
let rep = self.history_new(&target);
let rep = mem::replace(&mut self.current, rep);
if !rep.cwd.is_search() {
if rep.cwd.is_regular() {
self.history.insert(rep.cwd.clone(), rep);
}
@ -127,7 +127,7 @@ impl Tab {
emit!(Input(InputOpt::top("Change directory:").with_value(target.to_string_lossy())));
if let Ok(s) = result.await {
emit!(Cd(Url::new(s, &target)));
emit!(Cd(Url::from(s)));
}
});
false
@ -143,7 +143,7 @@ impl Tab {
let rep = self.history_new(hovered.url());
let rep = mem::replace(&mut self.current, rep);
if !rep.cwd.is_search() {
if rep.cwd.is_regular() {
self.history.insert(rep.cwd.clone(), rep);
}
@ -178,7 +178,7 @@ impl Tab {
let rep = self.history_new(&current);
let rep = mem::replace(&mut self.current, rep);
if !rep.cwd.is_search() {
if rep.cwd.is_regular() {
self.history.insert(rep.cwd.clone(), rep);
}
@ -253,7 +253,12 @@ impl Tab {
pin!(rx);
let version = FilesOp::prepare(&cwd);
let mut first = true;
while let Some(chunk) = rx.next().await {
if first {
emit!(Cd(cwd.clone()));
first = false;
}
emit!(Files(FilesOp::Part(cwd.clone(), version, chunk)));
}
Ok(())
@ -268,7 +273,7 @@ impl Tab {
if self.current.cwd.is_search() {
self.preview_reset_image();
let rep = self.history_new(&self.current.cwd.to_none());
let rep = self.history_new(&self.current.cwd.to_regular());
drop(mem::replace(&mut self.current, rep));
emit!(Refresh);
}

View file

@ -67,6 +67,7 @@ impl Watcher {
}
pub(super) fn watch(&mut self, mut watched: BTreeSet<&Url>) {
watched.retain(|&u| u.is_regular());
let (to_unwatch, to_watch): (BTreeSet<_>, BTreeSet<_>) = {
let guard = self.watched.read();
let keys = guard.keys().collect::<BTreeSet<_>>();
@ -119,8 +120,12 @@ impl Watcher {
}
pub(super) fn trigger_dirs(&self, dirs: &[&Url]) {
let dirs: Vec<_> = dirs.iter().filter(|&u| u.is_regular()).map(|&u| u.clone()).collect();
if dirs.is_empty() {
return;
}
let watched = self.watched.clone();
let dirs: Vec<_> = dirs.iter().map(|&u| u.clone()).collect();
tokio::spawn(async move {
for dir in dirs {
Self::dir_changed(&dir, watched.clone()).await;

View file

@ -157,7 +157,7 @@ impl Tasks {
pub fn file_cut(&self, src: &HashSet<Url>, dest: Url, force: bool) -> bool {
for p in src {
let to = dest.join(p.file_name().unwrap());
if force && *p == to {
if force && p == &to {
trace!("file_cut: same file, skipping {:?}", to);
} else {
self.scheduler.file_cut(p.clone(), to, force);
@ -169,7 +169,7 @@ impl Tasks {
pub fn file_copy(&self, src: &HashSet<Url>, dest: Url, force: bool, follow: bool) -> bool {
for p in src {
let to = dest.join(p.file_name().unwrap());
if force && *p == to {
if force && p == &to {
trace!("file_copy: same file, skipping {:?}", to);
} else {
self.scheduler.file_copy(p.clone(), to, force, follow);

View file

@ -256,7 +256,7 @@ impl File {
let mut dirs = VecDeque::from([task.target]);
while let Some(target) = dirs.pop_front() {
let mut it = match fs::read_dir(&target).await {
let mut it = match fs::read_dir(target).await {
Ok(it) => it,
Err(_) => continue,
};
@ -268,11 +268,11 @@ impl File {
};
if meta.is_dir() {
dirs.push_front(Url::new(entry.path(), &target));
dirs.push_front(Url::from(entry.path()));
continue;
}
task.target = Url::new(entry.path(), &target);
task.target = Url::from(entry.path());
task.length = meta.len();
self.sch.send(TaskOp::New(task.id, meta.len()))?;
self.tx.send(FileOp::Delete(task.clone())).await?;

View file

@ -23,7 +23,7 @@ impl Which {
self.layer = layer;
self.times = 1;
self.cands =
KEYMAP.get(layer).iter().filter(|s| s.on.len() > 1 && s.on[0] == *key).cloned().collect();
KEYMAP.get(layer).iter().filter(|s| s.on.len() > 1 && &s.on[0] == key).cloned().collect();
self.switch(true);
true
}

View file

@ -9,7 +9,7 @@ pub struct Url {
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum UrlScheme {
#[default]
None,
Regular,
Search,
Archive,
}
@ -62,14 +62,26 @@ impl AsRef<OsStr> for Url {
impl Url {
#[inline]
pub fn new(url: impl Into<Url>, ctx: &Url) -> Self {
let mut url: Self = url.into();
url.scheme = ctx.scheme;
url
pub fn join(&self, path: impl AsRef<Path>) -> Self {
let url = Self::from(self.path.join(path));
match self.scheme {
UrlScheme::Regular => url,
UrlScheme::Search => url,
UrlScheme::Archive => url.into_archive(),
}
}
#[inline]
pub fn join(&self, path: impl AsRef<Path>) -> Self { Self::new(self.path.join(path), self) }
pub fn parent_url(&self) -> Option<Url> {
self.path.parent().map(|p| {
let url = Self::from(p);
match self.scheme {
UrlScheme::Regular => url,
UrlScheme::Search => url,
UrlScheme::Archive => url,
}
})
}
#[inline]
pub fn strip_prefix(&self, base: impl AsRef<Path>) -> Option<&Path> {
@ -83,32 +95,42 @@ impl Url {
impl Url {
// --- Scheme
#[inline]
pub fn is_none(&self) -> bool { self.scheme == UrlScheme::None }
pub fn is_regular(&self) -> bool { self.scheme == UrlScheme::Regular }
#[inline]
pub fn to_none(&self) -> Self {
let mut url = self.clone();
url.scheme = UrlScheme::None;
url
pub fn to_regular(&self) -> Self { self.clone().into_regular() }
#[inline]
pub fn into_regular(mut self) -> Self {
self.scheme = UrlScheme::Regular;
self
}
#[inline]
pub fn is_search(&self) -> bool { self.scheme == UrlScheme::Search }
#[inline]
pub fn to_search(&self) -> Self {
let mut url = self.clone();
url.scheme = UrlScheme::Search;
url
pub fn to_search(&self) -> Self { self.clone().into_search() }
#[inline]
pub fn into_search(mut self) -> Self {
self.scheme = UrlScheme::Search;
self
}
#[inline]
pub fn is_archive(&self) -> bool { self.scheme == UrlScheme::Archive }
#[inline]
pub fn to_archive(&self) -> Self { self.clone().into_archive() }
#[inline]
pub fn into_archive(mut self) -> Self {
self.scheme = UrlScheme::Archive;
self
}
// --- Path
#[inline]
pub fn set_path(&mut self, path: PathBuf) { self.path = path; }
#[inline]
pub fn parent_url(&self) -> Option<Url> { self.path.parent().map(|p| Self::new(p, self)) }
}