mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: add file/folder differentiation to the cd command to support revealing directory
This commit is contained in:
parent
1f744810f4
commit
e7e75b8365
1 changed files with 40 additions and 30 deletions
|
|
@ -62,7 +62,7 @@ impl Watcher {
|
||||||
);
|
);
|
||||||
|
|
||||||
let instance = Self { watcher: watcher.unwrap(), watched: Default::default() };
|
let instance = Self { watcher: watcher.unwrap(), watched: Default::default() };
|
||||||
tokio::spawn(Self::changed(rx, instance.watched.clone()));
|
tokio::spawn(Self::on_changed(rx, instance.watched.clone()));
|
||||||
instance
|
instance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,13 +124,17 @@ impl Watcher {
|
||||||
|
|
||||||
let watched = self.watched.clone();
|
let watched = self.watched.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
let watched = watched.read().clone();
|
||||||
for dir in dirs {
|
for dir in dirs {
|
||||||
Self::dir_changed(&dir, watched.clone()).await;
|
Self::dir_changed(&dir, &watched).await;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn changed(rx: UnboundedReceiver<Url>, watched: Arc<RwLock<IndexMap<Url, Option<Url>>>>) {
|
async fn on_changed(
|
||||||
|
rx: UnboundedReceiver<Url>,
|
||||||
|
watched: Arc<RwLock<IndexMap<Url, Option<Url>>>>,
|
||||||
|
) {
|
||||||
// TODO: revert this once a new notification is implemented
|
// TODO: revert this once a new notification is implemented
|
||||||
// let rx = UnboundedReceiverStream::new(rx).chunks_timeout(100,
|
// let rx = UnboundedReceiverStream::new(rx).chunks_timeout(100,
|
||||||
// Duration::from_millis(200));
|
// Duration::from_millis(200));
|
||||||
|
|
@ -147,70 +151,76 @@ impl Watcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::file_changed(&files, watched.clone()).await;
|
let watched = watched.read().clone();
|
||||||
|
|
||||||
|
Self::files_changed(&files, &watched).await;
|
||||||
for file in files {
|
for file in files {
|
||||||
|
for u in Self::linked_urls(&file, &watched) {
|
||||||
|
emit!(Files(FilesOp::IOErr(u.clone())));
|
||||||
|
}
|
||||||
emit!(Files(FilesOp::IOErr(file)));
|
emit!(Files(FilesOp::IOErr(file)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for dir in dirs {
|
for dir in dirs {
|
||||||
Self::dir_changed(&dir, watched.clone()).await;
|
Self::dir_changed(&dir, &watched).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn file_changed(urls: &[Url], watched: Arc<RwLock<IndexMap<Url, Option<Url>>>>) {
|
async fn files_changed(urls: &[Url], watched: &IndexMap<Url, Option<Url>>) {
|
||||||
let Ok(mut mimes) = external::file(urls).await else {
|
let Ok(mut mimes) = external::file(urls).await else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let linked: Vec<_> = watched
|
let linked: Vec<_> = watched.iter().filter_map(|(k, v)| v.as_ref().map(|v| (k, v))).fold(
|
||||||
.read()
|
Vec::new(),
|
||||||
.iter()
|
|mut aac, (k, v)| {
|
||||||
.filter_map(|(k, v)| v.as_ref().map(|v| (k, v)))
|
|
||||||
.fold(Vec::new(), |mut aac, (k, v)| {
|
|
||||||
mimes
|
mimes
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(f, _)| f.parent().map(|p| p == **v) == Some(true))
|
.filter(|(u, _)| u.parent().map(|p| p == **v) == Some(true))
|
||||||
.for_each(|(f, m)| aac.push((k.join(f.file_name().unwrap()), m.clone())));
|
.for_each(|(u, m)| aac.push((k.join(u.file_name().unwrap()), m.clone())));
|
||||||
aac
|
aac
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
mimes.extend(linked);
|
mimes.extend(linked);
|
||||||
emit!(Mimetype(mimes));
|
emit!(Mimetype(mimes));
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn dir_changed(url: &Url, watched: Arc<RwLock<IndexMap<Url, Option<Url>>>>) {
|
async fn dir_changed(url: &Url, watched: &IndexMap<Url, Option<Url>>) {
|
||||||
let linked: Vec<_> = watched
|
let linked = Self::linked_urls(url, watched);
|
||||||
.read()
|
|
||||||
.iter()
|
|
||||||
.filter_map(|(k, v)| v.as_ref().map(|v| (k, v)))
|
|
||||||
.filter(|(_, v)| *v == url)
|
|
||||||
.map(|(k, _)| k.clone())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let Ok(rx) = Files::from_dir(url).await else {
|
let Ok(rx) = Files::from_dir(url).await else {
|
||||||
emit!(Files(FilesOp::IOErr(url.clone())));
|
emit!(Files(FilesOp::IOErr(url.clone())));
|
||||||
for ori in linked {
|
for u in linked {
|
||||||
emit!(Files(FilesOp::IOErr(ori)));
|
emit!(Files(FilesOp::IOErr(u.clone())));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let linked_files = |files: &[File], ori: &Url| -> Vec<File> {
|
let linked_files = |files: &[File], linked: &Url| -> Vec<File> {
|
||||||
let mut new = Vec::with_capacity(files.len());
|
let mut new = Vec::with_capacity(files.len());
|
||||||
for file in files {
|
for file in files {
|
||||||
let mut file = file.clone();
|
let mut file = file.clone();
|
||||||
file.url = ori.join(file.url.strip_prefix(url).unwrap());
|
file.url = linked.join(file.url.strip_prefix(url).unwrap());
|
||||||
new.push(file);
|
new.push(file);
|
||||||
}
|
}
|
||||||
new
|
new
|
||||||
};
|
};
|
||||||
|
|
||||||
let files: Vec<_> = UnboundedReceiverStream::new(rx).collect().await;
|
let files: Vec<_> = UnboundedReceiverStream::new(rx).collect().await;
|
||||||
for ori in linked {
|
for u in linked {
|
||||||
let files = linked_files(&files, &ori);
|
let files = linked_files(&files, u);
|
||||||
emit!(Files(FilesOp::Full(ori, files)));
|
emit!(Files(FilesOp::Full(u.clone(), files)));
|
||||||
}
|
}
|
||||||
emit!(Files(FilesOp::Full(url.clone(), files)));
|
emit!(Files(FilesOp::Full(url.clone(), files)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn linked_urls<'a>(url: &'a Url, watched: &'a IndexMap<Url, Option<Url>>) -> Vec<&'a Url> {
|
||||||
|
watched
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(k, v)| v.as_ref().map(|v| (k, v)))
|
||||||
|
.filter(|(_, v)| *v == url)
|
||||||
|
.map(|(k, _)| k)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue