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; use crate::help::Help;
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Help { impl Help {
pub fn escape(&mut self, _: impl Into<Opt>) -> bool { pub fn escape(&mut self, _: &Exec) -> bool {
if self.in_filter.is_some() { if self.in_filter.is_some() {
self.in_filter = None; self.in_filter = None;
self.filter_apply(); self.filter_apply();

View file

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

View file

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

View file

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

View file

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

View file

@ -2,14 +2,8 @@ use yazi_shared::event::Exec;
use crate::input::{op::InputOp, Input}; use crate::input::{op::InputOp, Input};
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Input { impl Input {
pub fn yank(&mut self, _: impl Into<Opt>) -> bool { pub fn yank(&mut self, _: &Exec) -> bool {
match self.snap().op { match self.snap().op {
InputOp::None => { InputOp::None => {
self.snap_mut().op = InputOp::Yank(self.snap().cursor); 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}; use crate::{manager::Manager, tasks::Tasks};
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Manager { 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 { if self.tabs.len() > 1 {
return self.tabs.close(self.tabs.idx); return self.tabs.close(self.tabs.idx);
} }

View file

@ -1,72 +1,117 @@
use std::ffi::OsString; use std::ffi::OsString;
use yazi_config::{popup::SelectCfg, OPEN}; use tokio::fs;
use yazi_shared::{event::Exec, MIME_DIR}; 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}; use crate::{manager::Manager, select::Select, tasks::Tasks};
pub struct Opt { pub struct Opt {
targets: Option<Vec<(Url, Option<String>)>>,
interactive: bool, interactive: bool,
} }
impl From<&Exec> for Opt { 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 { impl Manager {
async fn open_interactive(files: Vec<(OsString, String)>) { pub fn open(&mut self, opt: impl Into<Opt>, tasks: &Tasks) -> bool {
let openers = OPEN.common_openers(&files); let selected = self.selected();
if openers.is_empty() { if selected.is_empty() {
return; return false;
} } else if Self::quit_with_selected(&selected) {
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() {
return false; return false;
} }
let opt = opt.into() as Opt; let (mut done, mut todo) = (Vec::with_capacity(selected.len()), vec![]);
// TODO: plugin system for f in selected {
// tokio::spawn(async move { if f.is_dir() {
// let todo: Vec<_> = files.iter().filter(|(_, m)| m.is_none()).map(|(u, _)| done.push((f.url(), Some(MIME_DIR.to_owned())));
// u).collect(); if let Ok(mut mimes) = external::file(&todo).await { } else if self.mimetype.get(&f.url).is_some() {
// files = files done.push((f.url(), None));
// .into_iter() } else {
// .map(|(u, m)| { todo.push(f.clone());
// let mime = m.or_else(|| mimes.remove(&u)); }
// (u, mime) }
// })
// .collect();
// }
// let files: Vec<_> = let mut opt = opt.into() as Opt;
// files.into_iter().filter_map(|(u, m)| m.map(|m| (u.into_os_string(), if todo.is_empty() {
// m))).collect(); opt.targets = Some(done);
return self.open_do(opt, tasks);
}
// if opt.interactive { tokio::spawn(async move {
// Self::open_interactive(files).await; done.extend(todo.iter().map(|f| (f.url(), None)));
// return; 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 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; use crate::manager::Manager;
pub struct Opt;
impl From<&Exec> for Opt {
fn from(_: &Exec) -> Self { Self }
}
impl Manager { impl Manager {
#[inline] #[inline]
pub fn _refresh() { pub fn _refresh() {
emit!(Call(Exec::call("refresh", vec![]).vec(), Layer::Manager)); 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_current_dir(self.cwd()).ok();
env::set_var("PWD", self.cwd()); env::set_var("PWD", self.cwd());

View file

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

View file

@ -1,4 +1,3 @@
use yazi_adaptor::ADAPTOR;
use yazi_config::BOOT; use yazi_config::BOOT;
use yazi_shared::fs::Url; use yazi_shared::fs::Url;
@ -11,12 +10,12 @@ pub struct Tabs {
impl Tabs { impl Tabs {
pub fn make() -> Self { 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 { if let Some(file) = &BOOT.file {
tabs.items[0].reveal(Url::from(BOOT.cwd.join(file))); tabs.items[0].reveal(Url::from(BOOT.cwd.join(file)));
} }
tabs.set_idx(0); Manager::_refresh();
tabs tabs
} }
@ -31,10 +30,16 @@ impl Tabs {
#[inline] #[inline]
pub(super) fn set_idx(&mut self, idx: usize) { 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; self.idx = idx;
// TODO: plugin system
// self.active_mut().preview.reset_image();
Manager::_refresh(); Manager::_refresh();
Manager::_peek(true);
} }
} }

View file

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

View file

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

View file

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

View file

@ -1,14 +1,12 @@
use std::ffi::OsString;
use anyhow::anyhow; use anyhow::anyhow;
use yazi_config::{open::Opener, ARGS}; use yazi_config::open::Opener;
use yazi_shared::{emit, event::Exec, Layer}; use yazi_shared::{emit, event::Exec, fs::Url, Layer};
use crate::tasks::Tasks; use crate::tasks::Tasks;
pub struct Opt { pub struct Opt {
targets: Vec<(OsString, String)>, targets: Vec<Url>,
opener: Option<Opener>, opener: Opener,
} }
impl TryFrom<&Exec> for Opt { impl TryFrom<&Exec> for Opt {
@ -20,31 +18,13 @@ impl TryFrom<&Exec> for Opt {
} }
impl Tasks { 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)); emit!(Call(Exec::call("open", vec![]).with_data(Opt { targets, opener }).vec(), Layer::Tasks));
} }
pub fn open(&mut self, opt: impl TryInto<Opt>) -> bool { pub fn open(&mut self, opt: impl TryInto<Opt>) -> bool {
let Ok(opt) = opt.try_into() else { if let Ok(opt) = opt.try_into() {
return false; self.file_open_with(&opt.opener, &opt.targets);
};
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);
} }
false false
} }

View file

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

View file

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

View file

@ -177,17 +177,22 @@ impl<'a, 'b> Folder<'a, 'b> {
.iter() .iter()
.skip(window.0) .skip(window.0)
.take(window.1) .take(window.1)
.filter_map(|f| self.file(f).ok()) .enumerate()
.filter_map(|(i, f)| self.file(i, f).ok())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
)?; )?;
ud.set_named_user_value("files", self.scope.create_any_userdata_ref(&self.inner.files)?)?; 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) 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)?; 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)?)?; ud.set_named_user_value("folder", self.scope.create_any_userdata_ref(self.inner)?)?;
Ok(ud) Ok(ud)