diff --git a/yazi-fm/src/app/app.rs b/yazi-fm/src/app/app.rs index 1b1f9805..a2805e65 100644 --- a/yazi-fm/src/app/app.rs +++ b/yazi-fm/src/app/app.rs @@ -1,4 +1,4 @@ -use std::{collections::VecDeque, mem, sync::atomic::Ordering}; +use std::{collections::VecDeque, sync::atomic::Ordering}; use anyhow::Result; use crossterm::event::KeyEvent; @@ -6,7 +6,7 @@ use yazi_config::keymap::Key; use yazi_core::input::InputMode; use yazi_shared::{emit, event::{Event, Exec, NEED_RENDER}, term::Term, Layer}; -use crate::{lives::Lives, Ctx, Executor, Logs, Panic, Signals}; +use crate::{lives::Lives, Ctx, Executor, Logs, Panic, Router, Signals}; pub(crate) struct App { pub(crate) cx: Ctx, @@ -25,43 +25,68 @@ impl App { let mut app = Self { cx: Ctx::make(), term: Some(term), signals }; app.render()?; - let mut events = Vec::with_capacity(50); - let mut render_in_place = false; + let mut times = 0; + let mut events = Vec::with_capacity(200); while app.signals.rx.recv_many(&mut events, 50).await > 0 { for event in events.drain(..) { - match event { - Event::Call(exec, layer) => app.dispatch_call(exec, layer), - Event::Seq(execs, layer) => app.dispatch_seq(execs, layer), - Event::Render => render_in_place = true, - Event::Key(key) => app.dispatch_key(key), - Event::Resize => app.resize()?, - Event::Paste(str) => app.dispatch_paste(str), - Event::Quit(opt) => { - app.quit(opt)?; - return Ok(()); - } - } + times += 1; + app.dispatch(event)?; } - if mem::replace(&mut render_in_place, false) { - if let Ok(event) = app.signals.rx.try_recv() { - events.push(event); - NEED_RENDER.store(true, Ordering::Relaxed); - } else { - app.render()?; - } + if !NEED_RENDER.swap(false, Ordering::Relaxed) { + continue; } - if NEED_RENDER.swap(false, Ordering::Relaxed) { + if times >= 50 { + times = 0; + app.render()?; + } else if let Ok(event) = app.signals.rx.try_recv() { + events.push(event); emit!(Render); + } else { + times = 0; + app.render()?; } } Ok(()) } #[inline] - fn dispatch_key(&mut self, key: KeyEvent) { Executor::new(self).handle(Key::from(key)); } + fn dispatch(&mut self, event: Event) -> Result<()> { + match event { + Event::Call(exec, layer) => self.dispatch_call(exec, layer), + Event::Seq(execs, layer) => self.dispatch_seq(execs, layer), + Event::Render => self.dispatch_render(), + Event::Key(key) => self.dispatch_key(key), + Event::Resize => self.resize()?, + Event::Paste(str) => self.dispatch_paste(str), + Event::Quit(opt) => self.quit(opt), + } + Ok(()) + } + #[inline] + fn dispatch_call(&mut self, exec: Exec, layer: Layer) { + Executor::new(self).execute(exec, layer); + } + + #[inline] + fn dispatch_seq(&mut self, mut execs: VecDeque, layer: Layer) { + if let Some(exec) = execs.pop_front() { + Executor::new(self).execute(exec, layer); + } + if !execs.is_empty() { + emit!(Seq(execs, layer)); + } + } + + #[inline] + fn dispatch_render(&mut self) { NEED_RENDER.store(true, Ordering::Relaxed); } + + #[inline] + fn dispatch_key(&mut self, key: KeyEvent) { Router::new(self).route(Key::from(key)); } + + #[inline] fn dispatch_paste(&mut self, str: String) { if self.cx.input.visible { let input = &mut self.cx.input; @@ -70,19 +95,4 @@ impl App { } } } - - #[inline] - fn dispatch_call(&mut self, exec: Exec, layer: Layer) { - Executor::new(self).dispatch(exec, layer); - } - - #[inline] - fn dispatch_seq(&mut self, mut execs: VecDeque, layer: Layer) { - if let Some(exec) = execs.pop_front() { - Executor::new(self).dispatch(exec, layer); - } - if !execs.is_empty() { - emit!(Seq(execs, layer)); - } - } } diff --git a/yazi-fm/src/app/commands/quit.rs b/yazi-fm/src/app/commands/quit.rs index 43a07bcf..5a772e5b 100644 --- a/yazi-fm/src/app/commands/quit.rs +++ b/yazi-fm/src/app/commands/quit.rs @@ -1,13 +1,12 @@ use std::ffi::OsString; -use anyhow::Result; use yazi_config::ARGS; use yazi_shared::{event::EventQuit, term::Term}; use crate::app::App; impl App { - pub(crate) fn quit(&mut self, opt: EventQuit) -> Result<()> { + pub(crate) fn quit(&mut self, opt: EventQuit) -> ! { if !opt.no_cwd_file { self.cwd_to_file(); } diff --git a/yazi-fm/src/executor.rs b/yazi-fm/src/executor.rs index 54b7cb9e..b05b4881 100644 --- a/yazi-fm/src/executor.rs +++ b/yazi-fm/src/executor.rs @@ -1,6 +1,5 @@ -use yazi_config::{keymap::{Control, Key}, KEYMAP}; use yazi_core::input::InputMode; -use yazi_shared::{emit, event::Exec, Layer}; +use yazi_shared::{event::Exec, Layer}; use crate::app::App; @@ -13,7 +12,7 @@ impl<'a> Executor<'a> { pub(super) fn new(app: &'a mut App) -> Self { Self { app } } #[inline] - pub(super) fn dispatch(&mut self, exec: Exec, layer: Layer) { + pub(super) fn execute(&mut self, exec: Exec, layer: Layer) { match layer { Layer::App => self.app(exec), Layer::Manager => self.manager(exec), @@ -26,51 +25,6 @@ impl<'a> Executor<'a> { } } - pub(super) fn handle(&mut self, key: Key) -> bool { - let cx = &mut self.app.cx; - - if cx.which.visible { - return cx.which.type_(key); - } - if cx.help.visible && cx.help.type_(&key) { - return true; - } - if cx.input.visible && cx.input.type_(&key) { - return true; - } - - if cx.completion.visible { - self.matches(Layer::Completion, key) || self.matches(Layer::Input, key) - } else if cx.help.visible { - self.matches(Layer::Help, key) - } else if cx.input.visible { - self.matches(Layer::Input, key) - } else if cx.select.visible { - self.matches(Layer::Select, key) - } else if cx.tasks.visible { - self.matches(Layer::Tasks, key) - } else { - self.matches(Layer::Manager, key) - } - } - - #[inline] - fn matches(&mut self, layer: Layer, key: Key) -> bool { - for ctrl @ Control { on, .. } in KEYMAP.get(layer) { - if on.is_empty() || on[0] != key { - continue; - } - - if on.len() > 1 { - self.app.cx.which.show(&key, layer); - } else { - emit!(Seq(ctrl.to_seq(), layer)); - } - return true; - } - false - } - fn app(&mut self, exec: Exec) { macro_rules! on { ($name:ident) => { diff --git a/yazi-fm/src/main.rs b/yazi-fm/src/main.rs index ecd90bb9..0657a219 100644 --- a/yazi-fm/src/main.rs +++ b/yazi-fm/src/main.rs @@ -11,6 +11,7 @@ mod lives; mod logs; mod panic; mod root; +mod router; mod select; mod signals; mod tasks; @@ -23,6 +24,7 @@ use logs::*; use panic::*; #[allow(unused_imports)] use root::*; +use router::*; use signals::*; #[tokio::main] diff --git a/yazi-fm/src/router.rs b/yazi-fm/src/router.rs new file mode 100644 index 00000000..2dfcd152 --- /dev/null +++ b/yazi-fm/src/router.rs @@ -0,0 +1,59 @@ +use yazi_config::{keymap::{Control, Key}, KEYMAP}; +use yazi_shared::{emit, Layer}; + +use crate::app::App; + +pub(super) struct Router<'a> { + app: &'a mut App, +} + +impl<'a> Router<'a> { + #[inline] + pub(super) fn new(app: &'a mut App) -> Self { Self { app } } + + #[inline] + pub(super) fn route(&mut self, key: Key) -> bool { + let cx = &mut self.app.cx; + + if cx.which.visible { + return cx.which.type_(key); + } + if cx.help.visible && cx.help.type_(&key) { + return true; + } + if cx.input.visible && cx.input.type_(&key) { + return true; + } + + if cx.completion.visible { + self.matches(Layer::Completion, key) || self.matches(Layer::Input, key) + } else if cx.help.visible { + self.matches(Layer::Help, key) + } else if cx.input.visible { + self.matches(Layer::Input, key) + } else if cx.select.visible { + self.matches(Layer::Select, key) + } else if cx.tasks.visible { + self.matches(Layer::Tasks, key) + } else { + self.matches(Layer::Manager, key) + } + } + + #[inline] + fn matches(&mut self, layer: Layer, key: Key) -> bool { + for ctrl @ Control { on, .. } in KEYMAP.get(layer) { + if on.is_empty() || on[0] != key { + continue; + } + + if on.len() > 1 { + self.app.cx.which.show(&key, layer); + } else { + emit!(Seq(ctrl.to_seq(), layer)); + } + return true; + } + false + } +}