mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
refactor: split router from executor
This commit is contained in:
parent
56ede51c53
commit
8cc18976d9
5 changed files with 114 additions and 90 deletions
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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
59
yazi-fm/src/router.rs
Normal 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
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue