Refactor the open command

This commit is contained in:
sxyazi 2024-02-14 22:04:40 +08:00
parent 9fe0c1bdb7
commit 9788e53f5c
No known key found for this signature in database
7 changed files with 54 additions and 27 deletions

View file

@ -317,7 +317,7 @@ impl Files {
impl Files {
// --- Items
#[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) }
// --- Ticket
#[inline]

View file

@ -5,10 +5,10 @@ use yazi_config::{popup::SelectCfg, ARGS, OPEN};
use yazi_plugin::isolate;
use yazi_shared::{emit, event::{Cmd, EventQuit}, fs::{File, Url}, Layer, MIME_DIR};
use crate::{manager::Manager, select::Select, tasks::Tasks};
use crate::{folder::Folder, manager::Manager, select::Select, tasks::Tasks};
pub struct Opt {
targets: Vec<(Url, Option<String>)>,
targets: Vec<(Url, String)>,
interactive: bool,
}
@ -23,7 +23,7 @@ impl From<Cmd> for Opt {
impl Manager {
pub fn open(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
let selected = self.selected();
let selected = self.selected_or_hovered();
if selected.is_empty() {
return;
} else if Self::quit_with_selected(&selected) {
@ -31,13 +31,13 @@ impl Manager {
}
let (mut done, mut todo) = (Vec::with_capacity(selected.len()), vec![]);
for f in selected {
if f.is_dir() {
done.push((f.url(), Some(MIME_DIR.to_owned())));
} else if self.mimetype.get(&f.url).is_some() {
done.push((f.url(), None));
for u in selected {
if self.mimetype.get(u).is_some() {
done.push((u.clone(), String::new()));
} else if self.guess_its_folder(u) {
done.push((u.clone(), MIME_DIR.to_owned()));
} else {
todo.push(f.clone());
todo.push(u.clone());
}
}
@ -48,8 +48,15 @@ impl Manager {
}
tokio::spawn(async move {
done.extend(todo.iter().map(|f| (f.url(), None)));
if let Err(e) = isolate::preload("mime", todo, true).await {
let mut files = Vec::with_capacity(todo.len());
for u in todo {
if let Ok(f) = File::from(u).await {
files.push(f);
}
}
done.extend(files.iter().map(|f| (f.url(), String::new())));
if let Err(e) = isolate::preload("mime", files, true).await {
error!("preload in watcher failed: {e}");
}
@ -58,7 +65,7 @@ impl Manager {
}
#[inline]
pub fn _open_do(interactive: bool, targets: Vec<(Url, Option<String>)>) {
pub fn _open_do(interactive: bool, targets: Vec<(Url, String)>) {
emit!(Call(
Cmd::new("open_do").with_bool("interactive", interactive).with_data(targets),
Layer::Manager
@ -74,7 +81,9 @@ impl Manager {
let targets: Vec<_> = opt
.targets
.into_iter()
.filter_map(|(u, m)| m.or_else(|| self.mimetype.get(&u).cloned()).map(|m| (u, m)))
.filter_map(|(u, m)| {
Some(m).filter(|m| !m.is_empty()).or_else(|| self.mimetype.get(&u).cloned()).map(|m| (u, m))
})
.collect();
if targets.is_empty() {
@ -98,13 +107,30 @@ impl Manager {
});
}
fn quit_with_selected(selected: &[&File]) -> bool {
fn guess_its_folder(&self, url: &Url) -> bool {
let Some(p) = url.parent_url() else {
return true;
};
let find = |folder: Option<&Folder>| {
folder.is_some_and(|folder| {
folder.cwd == p && folder.files.iter().any(|f| f.is_dir() && f.url == *url)
})
};
find(Some(self.current()))
|| find(self.parent())
|| find(self.hovered_folder())
|| find(self.active().history.get(&p))
}
fn quit_with_selected(selected: &[&Url]) -> bool {
if ARGS.chooser_file.is_none() {
return false;
}
let paths = selected.iter().fold(OsString::new(), |mut s, &f| {
s.push(f.url.as_os_str());
let paths = selected.iter().fold(OsString::new(), |mut s, &u| {
s.push(u.as_os_str());
s.push("\n");
s
});

View file

@ -35,11 +35,7 @@ impl Manager {
return render!(self.active_mut().preview.reset());
};
let folder = Some(())
.filter(|_| hovered.is_dir())
.and_then(|_| self.active().history.get(&hovered.url))
.map(|f| (f.offset, f.mtime));
let folder = self.active().hovered_folder().map(|f| (f.offset, f.mtime));
if !self.active().preview.same_url(&hovered.url) {
self.active_mut().preview.skip = folder.map(|f| f.0).unwrap_or_default();
render!(self.active_mut().preview.reset());

View file

@ -47,6 +47,9 @@ impl Manager {
#[inline]
pub fn hovered(&self) -> Option<&File> { self.tabs.active().current.hovered() }
#[inline]
pub fn hovered_folder(&self) -> Option<&Folder> { self.tabs.active().hovered_folder() }
#[inline]
pub fn selected_or_hovered(&self) -> Vec<&Url> { self.tabs.active().selected_or_hovered() }
}

View file

@ -64,6 +64,11 @@ impl Tab {
self.history.remove(url).unwrap_or_else(|| Folder::from(url))
}
#[inline]
pub fn hovered_folder(&self) -> Option<&Folder> {
self.current.hovered().filter(|&h| h.is_dir()).and_then(|h| self.history.get(&h.url))
}
pub fn apply_files_attrs(&mut self) {
let apply = |f: &mut Folder| {
if f.stage == FolderStage::Loading {

View file

@ -26,10 +26,7 @@ impl Preview {
reg.add_field_method_get("skip", |_, me| Ok(me.skip));
reg.add_field_method_get("folder", |_, me| {
me.tab()
.current
.hovered()
.filter(|&f| f.is_dir())
.and_then(|f| me.tab().history.get(&f.url))
.hovered_folder()
.map(|f| {
let limit = LAYOUT.load().preview.height as usize;
Folder::make(Some(me.skip..f.files.len().min(me.skip + limit)), f, me.tab())

View file

@ -46,7 +46,7 @@ struct SelectedIter(btree_set::Iter<'static, yazi_shared::fs::Url>);
impl SelectedIter {
#[inline]
fn make(selected: &BTreeSet<yazi_shared::fs::Url>) -> mlua::Result<AnyUserData<'static>> {
fn make(selected: &'static BTreeSet<yazi_shared::fs::Url>) -> mlua::Result<AnyUserData<'static>> {
SCOPE.create_any_userdata(Self(selected.iter()))
}
}