This commit is contained in:
sxyazi 2023-12-25 22:29:42 +08:00
parent 169543b799
commit b7d184abaf
No known key found for this signature in database
19 changed files with 144 additions and 189 deletions

View file

@ -2,14 +2,8 @@ use yazi_shared::event::Exec;
use crate::help::Help;
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Help {
pub fn escape(&mut self, _: impl Into<Opt>) -> bool {
pub fn escape(&mut self, _: &Exec) -> bool {
if self.in_filter.is_some() {
self.in_filter = None;
self.filter_apply();

View file

@ -3,14 +3,8 @@ use yazi_shared::event::Exec;
use crate::{help::Help, input::Input};
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Help {
pub fn filter(&mut self, _: impl Into<Opt>) -> bool {
pub fn filter(&mut self, _: &Exec) -> bool {
let mut input = Input::default();
input.position = Position::new(Origin::BottomLeft, Offset::line());

View file

@ -2,14 +2,8 @@ use yazi_shared::{event::Exec, CharKind};
use crate::input::Input;
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Input {
pub fn backward(&mut self, _: impl Into<Opt>) -> bool {
pub fn backward(&mut self, _: &Exec) -> bool {
let snap = self.snap();
if snap.cursor == 0 {
return self.move_(0);

View file

@ -2,12 +2,6 @@ use yazi_shared::event::Exec;
use crate::input::Input;
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Input {
pub fn redo(&mut self, _: impl Into<Opt>) -> bool { self.snaps.redo() }
pub fn redo(&mut self, _: &Exec) -> bool { self.snaps.redo() }
}

View file

@ -2,14 +2,8 @@ use yazi_shared::event::Exec;
use crate::input::{Input, InputMode};
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Input {
pub fn undo(&mut self, _: impl Into<Opt>) -> bool {
pub fn undo(&mut self, _: &Exec) -> bool {
if !self.snaps.undo() {
return false;
}

View file

@ -2,15 +2,9 @@ use yazi_shared::event::Exec;
use crate::input::{op::InputOp, Input, InputMode};
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Input {
#[inline]
pub fn visual(&mut self, _: impl Into<Opt>) -> bool {
pub fn visual(&mut self, _: &Exec) -> bool {
let snap = self.snap_mut();
if snap.mode != InputMode::Normal {
return false;

View file

@ -2,14 +2,8 @@ use yazi_shared::event::Exec;
use crate::input::{op::InputOp, Input};
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Input {
pub fn yank(&mut self, _: impl Into<Opt>) -> bool {
pub fn yank(&mut self, _: &Exec) -> bool {
match self.snap().op {
InputOp::None => {
self.snap_mut().op = InputOp::Yank(self.snap().cursor);

View file

@ -2,14 +2,8 @@ use yazi_shared::event::Exec;
use crate::{manager::Manager, tasks::Tasks};
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Manager {
pub fn close(&mut self, _: impl Into<Opt>, tasks: &Tasks) -> bool {
pub fn close(&mut self, _: &Exec, tasks: &Tasks) -> bool {
if self.tabs.len() > 1 {
return self.tabs.close(self.tabs.idx);
}

View file

@ -1,72 +1,117 @@
use std::ffi::OsString;
use yazi_config::{popup::SelectCfg, OPEN};
use yazi_shared::{event::Exec, MIME_DIR};
use tokio::fs;
use tracing::error;
use yazi_config::{popup::SelectCfg, ARGS, OPEN};
use yazi_plugin::isolate;
use yazi_shared::{emit, event::Exec, fs::{File, Url}, Layer, MIME_DIR};
use crate::{manager::Manager, select::Select, tasks::Tasks};
pub struct Opt {
targets: Option<Vec<(Url, Option<String>)>>,
interactive: bool,
}
impl From<&Exec> for Opt {
fn from(e: &Exec) -> Self { Self { interactive: e.named.contains_key("interactive") } }
fn from(e: &Exec) -> Self {
Self { targets: e.take_data(), interactive: e.named.contains_key("interactive") }
}
}
impl Manager {
async fn open_interactive(files: Vec<(OsString, String)>) {
let openers = OPEN.common_openers(&files);
if openers.is_empty() {
return;
}
let result = Select::_show(SelectCfg::open(openers.iter().map(|o| o.desc.clone()).collect()));
if let Ok(choice) = result.await {
Tasks::_open(files, Some(openers[choice].clone()));
}
}
pub fn open(&mut self, opt: impl Into<Opt>) -> bool {
let mut files: Vec<_> = self
.selected()
.into_iter()
.map(|f| {
(
f.url(),
f.is_dir().then(|| MIME_DIR.to_owned()).or_else(|| self.mimetype.get(&f.url).cloned()),
)
})
.collect();
if files.is_empty() {
pub fn open(&mut self, opt: impl Into<Opt>, tasks: &Tasks) -> bool {
let selected = self.selected();
if selected.is_empty() {
return false;
} else if Self::quit_with_selected(&selected) {
return false;
}
let opt = opt.into() as Opt;
// TODO: plugin system
// tokio::spawn(async move {
// let todo: Vec<_> = files.iter().filter(|(_, m)| m.is_none()).map(|(u, _)|
// u).collect(); if let Ok(mut mimes) = external::file(&todo).await {
// files = files
// .into_iter()
// .map(|(u, m)| {
// let mime = m.or_else(|| mimes.remove(&u));
// (u, mime)
// })
// .collect();
// }
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));
} else {
todo.push(f.clone());
}
}
// let files: Vec<_> =
// files.into_iter().filter_map(|(u, m)| m.map(|m| (u.into_os_string(),
// m))).collect();
let mut opt = opt.into() as Opt;
if todo.is_empty() {
opt.targets = Some(done);
return self.open_do(opt, tasks);
}
// if opt.interactive {
// Self::open_interactive(files).await;
// return;
// }
tokio::spawn(async move {
done.extend(todo.iter().map(|f| (f.url(), None)));
if let Err(e) = isolate::preload("mime.lua".to_string(), todo, true).await {
error!("preload in watcher failed: {e}");
}
// Tasks::_open(files, None);
// });
Self::_open_do(opt.interactive, done);
});
false
}
#[inline]
pub fn _open_do(interactive: bool, targets: Vec<(Url, Option<String>)>) {
emit!(Call(
Exec::call("open_do", vec![]).with_bool("interactive", interactive).with_data(targets).vec(),
Layer::Manager
));
}
pub fn open_do(&mut self, opt: impl Into<Opt>, tasks: &Tasks) -> bool {
let opt = opt.into() as Opt;
let Some(targets) = opt.targets else {
return false;
};
let targets: Vec<_> = targets
.into_iter()
.filter_map(|(u, m)| m.or_else(|| self.mimetype.get(&u).cloned()).map(|m| (u, m)))
.collect();
if targets.is_empty() {
return false;
} else if !opt.interactive {
tasks.file_open(&targets);
return false;
}
let openers: Vec<_> = OPEN.common_openers(&targets).into_iter().cloned().collect();
if openers.is_empty() {
return false;
}
let urls = targets.into_iter().map(|(u, _)| u).collect();
tokio::spawn(async move {
let result = Select::_show(SelectCfg::open(openers.iter().map(|o| o.desc.clone()).collect()));
if let Ok(choice) = result.await {
Tasks::_open(urls, openers[choice].clone());
}
});
false
}
fn quit_with_selected(selected: &[&File]) -> bool {
let Some(p) = ARGS.chooser_file.clone() else {
return false;
};
let paths = selected.iter().fold(OsString::new(), |mut s, &f| {
s.push(f.url.as_os_str());
s.push("\n");
s
});
tokio::spawn(async move {
fs::write(p, paths.as_encoded_bytes()).await.ok();
emit!(Quit(false));
});
true
}
}

View file

@ -4,19 +4,13 @@ use yazi_shared::{emit, event::Exec, Layer};
use crate::manager::Manager;
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Manager {
#[inline]
pub fn _refresh() {
emit!(Call(Exec::call("refresh", vec![]).vec(), Layer::Manager));
}
pub fn refresh(&mut self, _: impl Into<Opt>) -> bool {
pub fn refresh(&mut self, _: &Exec) -> bool {
env::set_current_dir(self.cwd()).ok();
env::set_var("PWD", self.cwd());

View file

@ -3,13 +3,8 @@ use yazi_shared::event::Exec;
use crate::manager::Manager;
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Manager {
pub fn suspend(&mut self, _: impl Into<Opt>) -> bool {
pub fn suspend(&mut self, _: &Exec) -> bool {
#[cfg(unix)]
tokio::spawn(async move {
Scheduler::app_stop().await;

View file

@ -1,4 +1,3 @@
use yazi_adaptor::ADAPTOR;
use yazi_config::BOOT;
use yazi_shared::fs::Url;
@ -11,12 +10,12 @@ pub struct Tabs {
impl Tabs {
pub fn make() -> Self {
let mut tabs = Self { idx: usize::MAX, items: vec![Tab::from(Url::from(&BOOT.cwd))] };
let mut tabs = Self { idx: 0, items: vec![Tab::from(Url::from(&BOOT.cwd))] };
if let Some(file) = &BOOT.file {
tabs.items[0].reveal(Url::from(BOOT.cwd.join(file)));
}
tabs.set_idx(0);
Manager::_refresh();
tabs
}
@ -31,10 +30,16 @@ impl Tabs {
#[inline]
pub(super) fn set_idx(&mut self, idx: usize) {
if self.idx == idx {
return;
}
// We must reset it before changing the tab index.
self.active_mut().preview.reset_image();
self.idx = idx;
// TODO: plugin system
// self.active_mut().preview.reset_image();
Manager::_refresh();
Manager::_peek(true);
}
}

View file

@ -21,13 +21,9 @@ impl<'a> From<&'a Exec> for Opt {
impl Tab {
pub fn shell(&self, opt: impl Into<Opt>) -> bool {
let selected: Vec<_> = self
.selected()
.into_iter()
.map(|f| (f.url.as_os_str().to_owned(), Default::default()))
.collect();
let mut opt = opt.into() as Opt;
let selected: Vec<_> = self.selected().into_iter().map(|f| f.url()).collect();
tokio::spawn(async move {
if !opt.confirm || opt.cmd.is_empty() {
let mut result = Input::_show(InputCfg::shell(opt.block).with_value(opt.cmd));
@ -37,19 +33,15 @@ impl Tab {
}
}
Tasks::_open(
selected,
Some(Opener {
exec: opt.cmd,
block: opt.block,
orphan: false,
desc: Default::default(),
for_: None,
spread: true,
}),
);
Tasks::_open(selected, Opener {
exec: opt.cmd,
block: opt.block,
orphan: false,
desc: Default::default(),
for_: None,
spread: true,
});
});
false
}
}

View file

@ -2,14 +2,8 @@ use yazi_shared::event::Exec;
use crate::tasks::Tasks;
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Tasks {
pub fn cancel(&mut self, _: impl Into<Opt>) -> bool {
pub fn cancel(&mut self, _: &Exec) -> bool {
let id = self.scheduler.running.read().get_id(self.cursor);
if id.map(|id| self.scheduler.cancel(id)) != Some(true) {
return false;

View file

@ -7,14 +7,8 @@ use yazi_shared::{event::Exec, term::Term, Defer};
use crate::tasks::Tasks;
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Tasks {
pub fn inspect(&self, _: impl Into<Opt>) -> bool {
pub fn inspect(&self, _: &Exec) -> bool {
let Some(id) = self.scheduler.running.read().get_id(self.cursor) else {
return false;
};

View file

@ -1,14 +1,12 @@
use std::ffi::OsString;
use anyhow::anyhow;
use yazi_config::{open::Opener, ARGS};
use yazi_shared::{emit, event::Exec, Layer};
use yazi_config::open::Opener;
use yazi_shared::{emit, event::Exec, fs::Url, Layer};
use crate::tasks::Tasks;
pub struct Opt {
targets: Vec<(OsString, String)>,
opener: Option<Opener>,
targets: Vec<Url>,
opener: Opener,
}
impl TryFrom<&Exec> for Opt {
@ -20,31 +18,13 @@ impl TryFrom<&Exec> for Opt {
}
impl Tasks {
pub fn _open(targets: Vec<(OsString, String)>, opener: Option<Opener>) {
pub fn _open(targets: Vec<Url>, opener: Opener) {
emit!(Call(Exec::call("open", vec![]).with_data(Opt { targets, opener }).vec(), Layer::Tasks));
}
pub fn open(&mut self, opt: impl TryInto<Opt>) -> bool {
let Ok(opt) = opt.try_into() else {
return false;
};
if let Some(p) = &ARGS.chooser_file {
let paths = opt.targets.into_iter().fold(OsString::new(), |mut s, (p, _)| {
s.push(p);
s.push("\n");
s
});
std::fs::write(p, paths.as_encoded_bytes()).ok();
emit!(Quit(false));
return false;
}
if let Some(opener) = opt.opener {
self.file_open_with(&opener, &opt.targets.into_iter().map(|(f, _)| f).collect::<Vec<_>>());
} else {
self.file_open(&opt.targets);
if let Ok(opt) = opt.try_into() {
self.file_open_with(&opt.opener, &opt.targets);
}
false
}

View file

@ -1,7 +1,5 @@
use anyhow::Result;
use tokio::sync::oneshot;
use yazi_adaptor::ADAPTOR;
use yazi_core::manager::Manager;
use yazi_shared::{emit, event::Exec, term::Term};
use crate::app::App;

View file

@ -137,7 +137,8 @@ impl<'a> Executor<'a> {
on!(ACTIVE, visual_mode);
// Operation
on!(MANAGER, open);
on!(MANAGER, open, &self.app.cx.tasks);
on!(MANAGER, open_do, &self.app.cx.tasks);
on!(MANAGER, yank);
on!(MANAGER, paste, &self.app.cx.tasks);
on!(MANAGER, link, &self.app.cx.tasks);

View file

@ -177,17 +177,22 @@ impl<'a, 'b> Folder<'a, 'b> {
.iter()
.skip(window.0)
.take(window.1)
.filter_map(|f| self.file(f).ok())
.enumerate()
.filter_map(|(i, f)| self.file(i, f).ok())
.collect::<Vec<_>>(),
)?;
ud.set_named_user_value("files", self.scope.create_any_userdata_ref(&self.inner.files)?)?;
ud.set_named_user_value("hovered", self.inner.hovered().and_then(|h| self.file(h).ok()))?;
ud.set_named_user_value(
"hovered",
self.inner.hovered().and_then(|h| self.file(self.inner.cursor - window.0, h).ok()),
)?;
Ok(ud)
}
fn file(&self, inner: &'a yazi_shared::fs::File) -> mlua::Result<AnyUserData<'a>> {
fn file(&self, idx: usize, inner: &'a yazi_shared::fs::File) -> mlua::Result<AnyUserData<'a>> {
let ud = self.scope.create_any_userdata_ref(inner)?;
ud.set_named_user_value("idx", idx)?;
ud.set_named_user_value("folder", self.scope.create_any_userdata_ref(self.inner)?)?;
Ok(ud)