refactor: split router from executor

This commit is contained in:
sxyazi 2024-01-23 10:35:00 +08:00
parent 56ede51c53
commit 8cc18976d9
No known key found for this signature in database
5 changed files with 114 additions and 90 deletions

View file

@ -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<Exec>, 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<Exec>, layer: Layer) {
if let Some(exec) = execs.pop_front() {
Executor::new(self).dispatch(exec, layer);
}
if !execs.is_empty() {
emit!(Seq(execs, layer));
}
}
}

View file

@ -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();
}

View file

@ -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) => {

View file

@ -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]

59
yazi-fm/src/router.rs Normal file
View file

@ -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
}
}