This commit is contained in:
sxyazi 2023-11-28 01:51:30 +08:00
parent a281c3f81a
commit a4629adc30
No known key found for this signature in database
21 changed files with 215 additions and 127 deletions

View file

@ -64,6 +64,7 @@ impl Keymap {
#[inline] #[inline]
pub fn get(&self, layer: Layer) -> &Vec<Control> { pub fn get(&self, layer: Layer) -> &Vec<Control> {
match layer { match layer {
Layer::App => unreachable!(),
Layer::Manager => &self.manager, Layer::Manager => &self.manager,
Layer::Tasks => &self.tasks, Layer::Tasks => &self.tasks,
Layer::Select => &self.select, Layer::Select => &self.select,

View file

@ -1,7 +1,9 @@
use ratatui::prelude::Rect; use ratatui::prelude::Rect;
use tokio::sync::oneshot;
use yazi_config::popup::{Origin, Position}; use yazi_config::popup::{Origin, Position};
use yazi_shared::{Exec, Layer};
use crate::{completion::Completion, help::Help, input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which}; use crate::{completion::Completion, emit, help::Help, input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which};
pub struct Ctx { pub struct Ctx {
pub manager: Manager, pub manager: Manager,
@ -26,6 +28,21 @@ impl Ctx {
} }
} }
#[inline]
pub async fn stop() {
let (tx, rx) = oneshot::channel::<()>();
emit!(Call(Exec::call("stop", vec!["true".to_string()]).with_data(Some(tx)).vec(), Layer::App));
rx.await.ok();
}
#[inline]
pub fn resume() {
emit!(Call(
Exec::call("stop", vec!["false".to_string()]).with_data(None::<oneshot::Sender<()>>).vec(),
Layer::App
));
}
pub fn area(&self, position: &Position) -> Rect { pub fn area(&self, position: &Position) -> Rect {
if position.origin != Origin::Hovered { if position.origin != Origin::Hovered {
return position.rect(); return position.rect();

View file

@ -1,8 +1,7 @@
use std::{collections::BTreeMap, ffi::OsString}; use std::collections::BTreeMap;
use crossterm::event::KeyEvent; use crossterm::event::KeyEvent;
use tokio::sync::{mpsc::UnboundedSender, oneshot}; use tokio::sync::{mpsc::UnboundedSender, oneshot};
use yazi_config::open::Opener;
use yazi_shared::{fs::Url, term::Term, Exec, Layer, RoCell}; use yazi_shared::{fs::Url, term::Term, Exec, Layer, RoCell};
use super::files::FilesOp; use super::files::FilesOp;
@ -16,7 +15,6 @@ pub enum Event {
Paste(String), Paste(String),
Render(String), Render(String),
Resize(u16, u16), Resize(u16, u16),
Stop(bool, Option<oneshot::Sender<()>>),
Call(Vec<Exec>, Layer), Call(Vec<Exec>, Layer),
// Manager // Manager
@ -24,9 +22,6 @@ pub enum Event {
Pages(usize), Pages(usize),
Mimetype(BTreeMap<Url, String>), Mimetype(BTreeMap<Url, String>),
Preview(PreviewLock), Preview(PreviewLock),
// Tasks
Open(Vec<(OsString, String)>, Option<Opener>),
} }
impl Event { impl Event {
@ -56,10 +51,6 @@ macro_rules! emit {
(Resize($cols:expr, $rows:expr)) => { (Resize($cols:expr, $rows:expr)) => {
$crate::Event::Resize($cols, $rows).emit(); $crate::Event::Resize($cols, $rows).emit();
}; };
(Stop($state:expr)) => {{
let (tx, rx) = tokio::sync::oneshot::channel();
$crate::Event::Stop($state, Some(tx)).wait(rx)
}};
(Call($exec:expr, $layer:expr)) => { (Call($exec:expr, $layer:expr)) => {
$crate::Event::Call($exec, $layer).emit(); $crate::Event::Call($exec, $layer).emit();
}; };

View file

@ -3,7 +3,7 @@ use std::ffi::OsString;
use yazi_config::{popup::SelectCfg, OPEN}; use yazi_config::{popup::SelectCfg, OPEN};
use yazi_shared::{Exec, MIME_DIR}; use yazi_shared::{Exec, MIME_DIR};
use crate::{emit, external, manager::Manager, select::Select}; use crate::{external, manager::Manager, select::Select, tasks::Tasks};
pub struct Opt { pub struct Opt {
interactive: bool, interactive: bool,
@ -22,7 +22,7 @@ impl Manager {
let result = Select::_show(SelectCfg::open(openers.iter().map(|o| o.desc.clone()).collect())); let result = Select::_show(SelectCfg::open(openers.iter().map(|o| o.desc.clone()).collect()));
if let Ok(choice) = result.await { if let Ok(choice) = result.await {
emit!(Open(files, Some(openers[choice].clone()))); Tasks::_open(files, Some(openers[choice].clone()));
} }
} }
@ -63,7 +63,7 @@ impl Manager {
return; return;
} }
emit!(Open(files, None)); Tasks::_open(files, None);
}); });
false false
} }

View file

@ -5,7 +5,7 @@ use tokio::{fs::{self, OpenOptions}, io::{stdin, AsyncReadExt, AsyncWriteExt}};
use yazi_config::{popup::InputCfg, OPEN, PREVIEW}; use yazi_config::{popup::InputCfg, OPEN, PREVIEW};
use yazi_shared::{fs::{max_common_root, Url}, term::Term, Defer, Exec}; use yazi_shared::{fs::{max_common_root, Url}, term::Term, Defer, Exec};
use crate::{emit, external::{self, ShellOpt}, files::{File, FilesOp}, input::Input, manager::Manager, Event, BLOCKER}; use crate::{emit, external::{self, ShellOpt}, files::{File, FilesOp}, input::Input, manager::Manager, Ctx, BLOCKER};
pub struct Opt { pub struct Opt {
force: bool, force: bool,
@ -86,10 +86,10 @@ impl Manager {
let _guard = BLOCKER.acquire().await.unwrap(); let _guard = BLOCKER.acquire().await.unwrap();
let _defer = Defer::new(|| { let _defer = Defer::new(|| {
Event::Stop(false, None).emit(); Ctx::resume();
tokio::spawn(fs::remove_file(tmp.clone())) tokio::spawn(fs::remove_file(tmp.clone()))
}); });
emit!(Stop(true)).await; Ctx::stop().await;
let mut child = external::shell(ShellOpt { let mut child = external::shell(ShellOpt {
cmd: (*opener.exec).into(), cmd: (*opener.exec).into(),

View file

@ -1,6 +1,6 @@
use yazi_shared::Exec; use yazi_shared::Exec;
use crate::manager::Manager; use crate::{manager::Manager, Ctx};
pub struct Opt; pub struct Opt;
impl From<&Exec> for Opt { impl From<&Exec> for Opt {
@ -11,7 +11,7 @@ impl Manager {
pub fn suspend(&mut self, _: impl Into<Opt>) -> bool { pub fn suspend(&mut self, _: impl Into<Opt>) -> bool {
#[cfg(unix)] #[cfg(unix)]
tokio::spawn(async move { tokio::spawn(async move {
crate::emit!(Stop(true)).await; Ctx::stop().await;
unsafe { libc::raise(libc::SIGTSTP) }; unsafe { libc::raise(libc::SIGTSTP) };
}); });
false false

View file

@ -1,7 +1,6 @@
use yazi_shared::Exec; use yazi_shared::{fs::ends_with_slash, Defer, Exec};
use yazi_shared::{fs::ends_with_slash, Defer};
use crate::{emit, external::{self, FzfOpt, ZoxideOpt}, tab::Tab, Event, BLOCKER}; use crate::{external::{self, FzfOpt, ZoxideOpt}, tab::Tab, Ctx, BLOCKER};
pub struct Opt { pub struct Opt {
type_: OptType, type_: OptType,
@ -36,8 +35,8 @@ impl Tab {
let cwd = self.current.cwd.clone(); let cwd = self.current.cwd.clone();
tokio::spawn(async move { tokio::spawn(async move {
let _guard = BLOCKER.acquire().await.unwrap(); let _guard = BLOCKER.acquire().await.unwrap();
let _defer = Defer::new(|| Event::Stop(false, None).emit()); let _defer = Defer::new(Ctx::resume);
emit!(Stop(true)).await; Ctx::stop().await;
let result = if opt.type_ == OptType::Fzf { let result = if opt.type_ == OptType::Fzf {
external::fzf(FzfOpt { cwd }).await external::fzf(FzfOpt { cwd }).await

View file

@ -1,7 +1,7 @@
use yazi_config::{open::Opener, popup::InputCfg}; use yazi_config::{open::Opener, popup::InputCfg};
use yazi_shared::Exec; use yazi_shared::Exec;
use crate::{emit, input::Input, tab::Tab}; use crate::{input::Input, tab::Tab, tasks::Tasks};
pub struct Opt { pub struct Opt {
cmd: String, cmd: String,
@ -37,7 +37,7 @@ impl Tab {
} }
} }
emit!(Open( Tasks::_open(
selected, selected,
Some(Opener { Some(Opener {
exec: opt.cmd, exec: opt.cmd,
@ -46,8 +46,8 @@ impl Tab {
desc: Default::default(), desc: Default::default(),
for_: None, for_: None,
spread: true, spread: true,
}) }),
)); );
}); });
false false

View file

@ -2,10 +2,9 @@ use std::io::{stdout, Write};
use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
use tokio::{io::{stdin, AsyncReadExt}, select, sync::mpsc, time}; use tokio::{io::{stdin, AsyncReadExt}, select, sync::mpsc, time};
use yazi_shared::Exec; use yazi_shared::{term::Term, Defer, Exec};
use yazi_shared::{term::Term, Defer};
use crate::{emit, tasks::Tasks, Event, BLOCKER}; use crate::{tasks::Tasks, Ctx, BLOCKER};
pub struct Opt; pub struct Opt;
@ -32,10 +31,10 @@ impl Tasks {
task.logs.clone() task.logs.clone()
}; };
emit!(Stop(true)).await; Ctx::stop().await;
let _defer = Defer::new(|| { let _defer = Defer::new(|| {
disable_raw_mode().ok(); disable_raw_mode().ok();
Event::Stop(false, None).emit(); Ctx::resume();
}); });
Term::clear(&mut stdout()).ok(); Term::clear(&mut stdout()).ok();

View file

@ -1,5 +1,6 @@
mod arrow; mod arrow;
mod cancel; mod cancel;
mod inspect; mod inspect;
mod open;
mod toggle; mod toggle;
mod update; mod update;

View file

@ -0,0 +1,51 @@
use std::ffi::OsString;
use anyhow::anyhow;
use yazi_config::{open::Opener, BOOT};
use yazi_shared::{Exec, Layer};
use crate::{emit, tasks::Tasks};
pub struct Opt {
targets: Vec<(OsString, String)>,
opener: Option<Opener>,
}
impl TryFrom<&Exec> for Opt {
type Error = anyhow::Error;
fn try_from(e: &Exec) -> Result<Self, Self::Error> {
e.take_data().ok_or_else(|| anyhow!("invalid data"))
}
}
impl Tasks {
pub fn _open(targets: Vec<(OsString, String)>, opener: Option<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) = &BOOT.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
}
}

View file

@ -3,7 +3,7 @@ use std::{ffi::OsString, mem};
use anyhow::Result; use anyhow::Result;
use tokio::{io::{AsyncBufReadExt, BufReader}, select, sync::{mpsc, oneshot}}; use tokio::{io::{AsyncBufReadExt, BufReader}, select, sync::{mpsc, oneshot}};
use crate::{emit, external::{self, ShellOpt}, tasks::TaskOp, BLOCKER}; use crate::{external::{self, ShellOpt}, tasks::TaskOp, Ctx, BLOCKER};
pub(crate) struct Process { pub(crate) struct Process {
sch: mpsc::UnboundedSender<TaskOp>, sch: mpsc::UnboundedSender<TaskOp>,
@ -37,7 +37,7 @@ impl Process {
let opt = ShellOpt::from(&mut task); let opt = ShellOpt::from(&mut task);
if task.block { if task.block {
let _guard = BLOCKER.acquire().await.unwrap(); let _guard = BLOCKER.acquire().await.unwrap();
emit!(Stop(true)).await; Ctx::stop().await;
match external::shell(opt) { match external::shell(opt) {
Ok(mut child) => { Ok(mut child) => {
@ -49,7 +49,7 @@ impl Process {
self.fail(task.id, format!("Failed to spawn process: {e}"))?; self.fail(task.id, format!("Failed to spawn process: {e}"))?;
} }
} }
return Ok(emit!(Stop(false)).await); return Ok(Ctx::resume());
} }
if task.orphan { if task.orphan {

View file

@ -1,23 +1,22 @@
use std::{ffi::OsString, sync::atomic::Ordering}; use std::sync::atomic::Ordering;
use anyhow::{Ok, Result}; use anyhow::{Ok, Result};
use crossterm::event::KeyEvent; use crossterm::event::KeyEvent;
use ratatui::{backend::Backend, prelude::Rect}; use ratatui::{backend::Backend, prelude::Rect};
use tokio::sync::oneshot;
use yazi_config::{keymap::Key, BOOT}; use yazi_config::{keymap::Key, BOOT};
use yazi_core::{emit, files::FilesOp, input::InputMode, manager::Manager, preview::COLLISION, Ctx, Event}; use yazi_core::{emit, files::FilesOp, input::InputMode, preview::COLLISION, Ctx, Event};
use yazi_shared::{term::Term, Exec, Layer}; use yazi_shared::{term::Term, Exec, Layer};
use crate::{Executor, Logs, Panic, Root, Signals}; use crate::{Executor, Logs, Panic, Root, Signals};
pub(super) struct App { pub(crate) struct App {
cx: Ctx, pub(crate) cx: Ctx,
term: Option<Term>, pub(crate) term: Option<Term>,
signals: Signals, pub(crate) signals: Signals,
} }
impl App { impl App {
pub(super) async fn run() -> Result<()> { pub(crate) async fn run() -> Result<()> {
Panic::install(); Panic::install();
let _log = Logs::init()?; let _log = Logs::init()?;
let term = Term::start()?; let term = Term::start()?;
@ -35,7 +34,6 @@ impl App {
Event::Paste(str) => app.dispatch_paste(str), Event::Paste(str) => app.dispatch_paste(str),
Event::Render(_) => app.dispatch_render()?, Event::Render(_) => app.dispatch_render()?,
Event::Resize(cols, rows) => app.dispatch_resize(cols, rows), Event::Resize(cols, rows) => app.dispatch_resize(cols, rows),
Event::Stop(state, tx) => app.dispatch_stop(state, tx),
Event::Call(exec, layer) => app.dispatch_call(exec, layer), Event::Call(exec, layer) => app.dispatch_call(exec, layer),
event => app.dispatch_module(event), event => app.dispatch_module(event),
} }
@ -53,7 +51,7 @@ impl App {
fn dispatch_key(&mut self, key: KeyEvent) { fn dispatch_key(&mut self, key: KeyEvent) {
let key = Key::from(key); let key = Key::from(key);
if Executor::new(&mut self.cx).handle(key) { if Executor::new(self).handle(key) {
emit!(Render); emit!(Render);
} }
} }
@ -121,25 +119,9 @@ impl App {
emit!(Render); emit!(Render);
} }
fn dispatch_stop(&mut self, state: bool, tx: Option<oneshot::Sender<()>>) {
self.cx.manager.active_mut().preview.reset_image();
if state {
self.signals.stop_term(true);
self.term = None;
} else {
self.term = Some(Term::start().unwrap());
self.signals.stop_term(false);
emit!(Render);
Manager::_hover(None);
}
if let Some(tx) = tx {
tx.send(()).ok();
}
}
#[inline] #[inline]
fn dispatch_call(&mut self, exec: Vec<Exec>, layer: Layer) { fn dispatch_call(&mut self, exec: Vec<Exec>, layer: Layer) {
if Executor::new(&mut self.cx).dispatch(&exec, layer) { if Executor::new(self).dispatch(&exec, layer) {
emit!(Render); emit!(Render);
} }
} }
@ -176,26 +158,6 @@ impl App {
emit!(Render); emit!(Render);
} }
} }
Event::Open(targets, opener) => {
if let Some(p) = &BOOT.chooser_file {
let paths = 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();
return emit!(Quit(false));
}
if let Some(opener) = opener {
tasks.file_open_with(&opener, &targets.into_iter().map(|(f, _)| f).collect::<Vec<_>>());
} else {
tasks.file_open(&targets);
}
}
_ => unreachable!(), _ => unreachable!(),
} }
} }

View file

@ -0,0 +1 @@
mod stop;

View file

@ -0,0 +1,42 @@
use anyhow::Result;
use tokio::sync::oneshot;
use yazi_core::{emit, manager::Manager};
use yazi_shared::{term::Term, Exec};
use crate::app::App;
pub struct Opt {
state: bool,
tx: Option<oneshot::Sender<()>>,
}
impl TryFrom<&Exec> for Opt {
type Error = anyhow::Error;
fn try_from(e: &Exec) -> Result<Self, Self::Error> {
Ok(Self { state: e.args.first().map_or(false, |s| s == "true"), tx: e.take_data() })
}
}
impl App {
pub(crate) fn stop(&mut self, opt: impl TryInto<Opt>) -> bool {
let Ok(opt) = opt.try_into() else {
return false;
};
self.cx.manager.active_mut().preview.reset_image();
if opt.state {
self.signals.stop_term(true);
self.term = None;
} else {
self.term = Some(Term::start().unwrap());
self.signals.stop_term(false);
emit!(Render);
Manager::_hover(None);
}
if let Some(tx) = opt.tx {
tx.send(()).ok();
}
false
}
}

4
yazi-fm/src/app/mod.rs Normal file
View file

@ -0,0 +1,4 @@
mod app;
mod commands;
pub(crate) use app::*;

View file

@ -1,35 +1,39 @@
use yazi_config::{keymap::{Control, Key}, KEYMAP}; use yazi_config::{keymap::{Control, Key}, KEYMAP};
use yazi_core::{input::InputMode, Ctx}; use yazi_core::input::InputMode;
use yazi_shared::{Exec, Layer}; use yazi_shared::{Exec, Layer};
use crate::app::App;
pub(super) struct Executor<'a> { pub(super) struct Executor<'a> {
cx: &'a mut Ctx, app: &'a mut App,
} }
impl<'a> Executor<'a> { impl<'a> Executor<'a> {
#[inline] #[inline]
pub(super) fn new(cx: &'a mut Ctx) -> Self { Self { cx } } pub(super) fn new(app: &'a mut App) -> Self { Self { app } }
pub(super) fn handle(&mut self, key: Key) -> bool { pub(super) fn handle(&mut self, key: Key) -> bool {
if self.cx.which.visible { let cx = &mut self.app.cx;
return self.cx.which.press(key);
if cx.which.visible {
return cx.which.press(key);
} }
if self.cx.help.visible && self.cx.help.type_(&key) { if cx.help.visible && cx.help.type_(&key) {
return true; return true;
} }
if self.cx.input.visible && self.cx.input.type_(&key) { if cx.input.visible && cx.input.type_(&key) {
return true; return true;
} }
let b = if self.cx.completion.visible { let b = if cx.completion.visible {
self.matches(Layer::Completion, key).or_else(|| self.matches(Layer::Input, key)) self.matches(Layer::Completion, key).or_else(|| self.matches(Layer::Input, key))
} else if self.cx.help.visible { } else if cx.help.visible {
self.matches(Layer::Help, key) self.matches(Layer::Help, key)
} else if self.cx.input.visible { } else if cx.input.visible {
self.matches(Layer::Input, key) self.matches(Layer::Input, key)
} else if self.cx.select.visible { } else if cx.select.visible {
self.matches(Layer::Select, key) self.matches(Layer::Select, key)
} else if self.cx.tasks.visible { } else if cx.tasks.visible {
self.matches(Layer::Tasks, key) self.matches(Layer::Tasks, key)
} else { } else {
self.matches(Layer::Manager, key) self.matches(Layer::Manager, key)
@ -45,7 +49,7 @@ impl<'a> Executor<'a> {
} }
return Some(if on.len() > 1 { return Some(if on.len() > 1 {
self.cx.which.show(&key, layer) self.app.cx.which.show(&key, layer)
} else { } else {
self.dispatch(exec, layer) self.dispatch(exec, layer)
}); });
@ -58,6 +62,7 @@ impl<'a> Executor<'a> {
let mut render = false; let mut render = false;
for e in exec { for e in exec {
render |= match layer { render |= match layer {
Layer::App => self.app(e),
Layer::Manager => self.manager(e), Layer::Manager => self.manager(e),
Layer::Tasks => self.tasks(e), Layer::Tasks => self.tasks(e),
Layer::Select => self.select(e), Layer::Select => self.select(e),
@ -70,21 +75,35 @@ impl<'a> Executor<'a> {
render render
} }
fn app(&mut self, exec: &Exec) -> bool {
macro_rules! on {
($name:ident) => {
if exec.cmd == stringify!($name) {
return self.app.$name(exec);
}
};
}
on!(stop);
false
}
fn manager(&mut self, exec: &Exec) -> bool { fn manager(&mut self, exec: &Exec) -> bool {
macro_rules! on { macro_rules! on {
(MANAGER, $name:ident $(,$args:expr)*) => { (MANAGER, $name:ident $(,$args:expr)*) => {
if exec.cmd == stringify!($name) { if exec.cmd == stringify!($name) {
return self.cx.manager.$name(exec, $($args),*); return self.app.cx.manager.$name(exec, $($args),*);
} }
}; };
(ACTIVE, $name:ident) => { (ACTIVE, $name:ident) => {
if exec.cmd == stringify!($name) { if exec.cmd == stringify!($name) {
return self.cx.manager.active_mut().$name(exec); return self.app.cx.manager.active_mut().$name(exec);
} }
}; };
(TABS, $name:ident) => { (TABS, $name:ident) => {
if exec.cmd == concat!("tab_", stringify!($name)) { if exec.cmd == concat!("tab_", stringify!($name)) {
return self.cx.manager.tabs.$name(exec); return self.app.cx.manager.tabs.$name(exec);
} }
}; };
} }
@ -92,8 +111,8 @@ impl<'a> Executor<'a> {
on!(MANAGER, peek); on!(MANAGER, peek);
on!(MANAGER, hover); on!(MANAGER, hover);
on!(MANAGER, refresh); on!(MANAGER, refresh);
on!(MANAGER, quit, &self.cx.tasks); on!(MANAGER, quit, &self.app.cx.tasks);
on!(MANAGER, close, &self.cx.tasks); on!(MANAGER, close, &self.app.cx.tasks);
on!(MANAGER, suspend); on!(MANAGER, suspend);
on!(ACTIVE, escape); on!(ACTIVE, escape);
@ -114,9 +133,9 @@ impl<'a> Executor<'a> {
// Operation // Operation
on!(MANAGER, open); on!(MANAGER, open);
on!(MANAGER, yank); on!(MANAGER, yank);
on!(MANAGER, paste, &self.cx.tasks); on!(MANAGER, paste, &self.app.cx.tasks);
on!(MANAGER, link, &self.cx.tasks); on!(MANAGER, link, &self.app.cx.tasks);
on!(MANAGER, remove, &self.cx.tasks); on!(MANAGER, remove, &self.app.cx.tasks);
on!(MANAGER, create); on!(MANAGER, create);
on!(MANAGER, rename); on!(MANAGER, rename);
on!(ACTIVE, copy); on!(ACTIVE, copy);
@ -142,9 +161,9 @@ impl<'a> Executor<'a> {
match exec.cmd.as_bytes() { match exec.cmd.as_bytes() {
// Tasks // Tasks
b"tasks_show" => self.cx.tasks.toggle(()), b"tasks_show" => self.app.cx.tasks.toggle(()),
// Help // Help
b"help" => self.cx.help.toggle(Layer::Manager), b"help" => self.app.cx.help.toggle(Layer::Manager),
_ => false, _ => false,
} }
} }
@ -153,24 +172,25 @@ impl<'a> Executor<'a> {
macro_rules! on { macro_rules! on {
($name:ident) => { ($name:ident) => {
if exec.cmd == stringify!($name) { if exec.cmd == stringify!($name) {
return self.cx.tasks.$name(exec); return self.app.cx.tasks.$name(exec);
} }
}; };
($name:ident, $alias:literal) => { ($name:ident, $alias:literal) => {
if exec.cmd == $alias { if exec.cmd == $alias {
return self.cx.tasks.$name(exec); return self.app.cx.tasks.$name(exec);
} }
}; };
} }
on!(update); on!(update);
on!(open);
on!(toggle, "close"); on!(toggle, "close");
on!(arrow); on!(arrow);
on!(inspect); on!(inspect);
on!(cancel); on!(cancel);
match exec.cmd.as_str() { match exec.cmd.as_str() {
"help" => self.cx.help.toggle(Layer::Tasks), "help" => self.app.cx.help.toggle(Layer::Tasks),
_ => false, _ => false,
} }
} }
@ -179,7 +199,7 @@ impl<'a> Executor<'a> {
macro_rules! on { macro_rules! on {
($name:ident) => { ($name:ident) => {
if exec.cmd == stringify!($name) { if exec.cmd == stringify!($name) {
return self.cx.select.$name(exec); return self.app.cx.select.$name(exec);
} }
}; };
} }
@ -189,7 +209,7 @@ impl<'a> Executor<'a> {
on!(arrow); on!(arrow);
match exec.cmd.as_str() { match exec.cmd.as_str() {
"help" => self.cx.help.toggle(Layer::Select), "help" => self.app.cx.help.toggle(Layer::Select),
_ => false, _ => false,
} }
} }
@ -198,12 +218,12 @@ impl<'a> Executor<'a> {
macro_rules! on { macro_rules! on {
($name:ident) => { ($name:ident) => {
if exec.cmd == stringify!($name) { if exec.cmd == stringify!($name) {
return self.cx.input.$name(exec); return self.app.cx.input.$name(exec);
} }
}; };
($name:ident, $alias:literal) => { ($name:ident, $alias:literal) => {
if exec.cmd == $alias { if exec.cmd == $alias {
return self.cx.input.$name(exec); return self.app.cx.input.$name(exec);
} }
}; };
} }
@ -217,13 +237,13 @@ impl<'a> Executor<'a> {
if exec.cmd.as_str() == "complete" { if exec.cmd.as_str() == "complete" {
return if exec.named.contains_key("trigger") { return if exec.named.contains_key("trigger") {
self.cx.completion.trigger(exec) self.app.cx.completion.trigger(exec)
} else { } else {
self.cx.input.complete(exec) self.app.cx.input.complete(exec)
}; };
} }
match self.cx.input.mode() { match self.app.cx.input.mode() {
InputMode::Normal => { InputMode::Normal => {
on!(insert); on!(insert);
on!(visual); on!(visual);
@ -236,7 +256,7 @@ impl<'a> Executor<'a> {
on!(redo); on!(redo);
match exec.cmd.as_str() { match exec.cmd.as_str() {
"help" => self.cx.help.toggle(Layer::Input), "help" => self.app.cx.help.toggle(Layer::Input),
_ => false, _ => false,
} }
} }
@ -253,7 +273,7 @@ impl<'a> Executor<'a> {
macro_rules! on { macro_rules! on {
($name:ident) => { ($name:ident) => {
if exec.cmd == stringify!($name) { if exec.cmd == stringify!($name) {
return self.cx.help.$name(exec); return self.app.cx.help.$name(exec);
} }
}; };
} }
@ -263,7 +283,7 @@ impl<'a> Executor<'a> {
on!(filter); on!(filter);
match exec.cmd.as_str() { match exec.cmd.as_str() {
"close" => self.cx.help.toggle(Layer::Help), "close" => self.app.cx.help.toggle(Layer::Help),
_ => false, _ => false,
} }
} }
@ -272,7 +292,7 @@ impl<'a> Executor<'a> {
macro_rules! on { macro_rules! on {
($name:ident) => { ($name:ident) => {
if exec.cmd == stringify!($name) { if exec.cmd == stringify!($name) {
return self.cx.completion.$name(exec); return self.app.cx.completion.$name(exec);
} }
}; };
} }
@ -283,7 +303,7 @@ impl<'a> Executor<'a> {
on!(arrow); on!(arrow);
match exec.cmd.as_str() { match exec.cmd.as_str() {
"help" => self.cx.help.toggle(Layer::Completion), "help" => self.app.cx.help.toggle(Layer::Completion),
_ => false, _ => false,
} }
} }

View file

@ -14,7 +14,6 @@ mod tasks;
mod which; mod which;
mod widgets; mod widgets;
use app::*;
use executor::*; use executor::*;
use logs::*; use logs::*;
use panic::*; use panic::*;
@ -34,5 +33,5 @@ async fn main() -> anyhow::Result<()> {
yazi_adaptor::init(); yazi_adaptor::init();
App::run().await app::App::run().await
} }

View file

@ -8,7 +8,7 @@ impl Panic {
let hook = std::panic::take_hook(); let hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| { std::panic::set_hook(Box::new(move |info| {
_ = Term::goodbye(|| { Term::goodbye(|| {
hook(info); hook(info);
true true
}); });

View file

@ -50,6 +50,7 @@ impl Signals {
#[cfg(unix)] #[cfg(unix)]
fn spawn_system_task(&self) -> Result<JoinHandle<()>> { fn spawn_system_task(&self) -> Result<JoinHandle<()>> {
use libc::{SIGCONT, SIGHUP, SIGINT, SIGQUIT, SIGTERM}; use libc::{SIGCONT, SIGHUP, SIGINT, SIGQUIT, SIGTERM};
use yazi_core::Ctx;
let tx = self.tx.clone(); let tx = self.tx.clone();
let mut signals = signal_hook_tokio::Signals::new([ let mut signals = signal_hook_tokio::Signals::new([
@ -67,9 +68,7 @@ impl Signals {
break; break;
} }
} }
SIGCONT => { SIGCONT => Ctx::resume(),
tx.send(Event::Stop(false, None)).ok();
}
_ => {} _ => {}
} }
} }

View file

@ -3,6 +3,7 @@ use std::fmt::{self, Display};
#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Copy)] #[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Copy)]
pub enum Layer { pub enum Layer {
#[default] #[default]
App,
Manager, Manager,
Tasks, Tasks,
Select, Select,
@ -15,6 +16,7 @@ pub enum Layer {
impl Display for Layer { impl Display for Layer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Self::App => write!(f, "app"),
Self::Manager => write!(f, "manager"), Self::Manager => write!(f, "manager"),
Self::Tasks => write!(f, "tasks"), Self::Tasks => write!(f, "tasks"),
Self::Select => write!(f, "select"), Self::Select => write!(f, "select"),