mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
169543b799
commit
b7d184abaf
19 changed files with 144 additions and 189 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue