mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41: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 anyhow::Result;
|
||||||
use crossterm::event::KeyEvent;
|
use crossterm::event::KeyEvent;
|
||||||
|
|
@ -6,7 +6,7 @@ use yazi_config::keymap::Key;
|
||||||
use yazi_core::input::InputMode;
|
use yazi_core::input::InputMode;
|
||||||
use yazi_shared::{emit, event::{Event, Exec, NEED_RENDER}, term::Term, Layer};
|
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) struct App {
|
||||||
pub(crate) cx: Ctx,
|
pub(crate) cx: Ctx,
|
||||||
|
|
@ -25,43 +25,68 @@ impl App {
|
||||||
let mut app = Self { cx: Ctx::make(), term: Some(term), signals };
|
let mut app = Self { cx: Ctx::make(), term: Some(term), signals };
|
||||||
app.render()?;
|
app.render()?;
|
||||||
|
|
||||||
let mut events = Vec::with_capacity(50);
|
let mut times = 0;
|
||||||
let mut render_in_place = false;
|
let mut events = Vec::with_capacity(200);
|
||||||
while app.signals.rx.recv_many(&mut events, 50).await > 0 {
|
while app.signals.rx.recv_many(&mut events, 50).await > 0 {
|
||||||
for event in events.drain(..) {
|
for event in events.drain(..) {
|
||||||
match event {
|
times += 1;
|
||||||
Event::Call(exec, layer) => app.dispatch_call(exec, layer),
|
app.dispatch(event)?;
|
||||||
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(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if mem::replace(&mut render_in_place, false) {
|
if !NEED_RENDER.swap(false, Ordering::Relaxed) {
|
||||||
if let Ok(event) = app.signals.rx.try_recv() {
|
continue;
|
||||||
events.push(event);
|
|
||||||
NEED_RENDER.store(true, Ordering::Relaxed);
|
|
||||||
} else {
|
|
||||||
app.render()?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
emit!(Render);
|
||||||
|
} else {
|
||||||
|
times = 0;
|
||||||
|
app.render()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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) {
|
fn dispatch_paste(&mut self, str: String) {
|
||||||
if self.cx.input.visible {
|
if self.cx.input.visible {
|
||||||
let input = &mut self.cx.input;
|
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 std::ffi::OsString;
|
||||||
|
|
||||||
use anyhow::Result;
|
|
||||||
use yazi_config::ARGS;
|
use yazi_config::ARGS;
|
||||||
use yazi_shared::{event::EventQuit, term::Term};
|
use yazi_shared::{event::EventQuit, term::Term};
|
||||||
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
|
|
||||||
impl 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 {
|
if !opt.no_cwd_file {
|
||||||
self.cwd_to_file();
|
self.cwd_to_file();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use yazi_config::{keymap::{Control, Key}, KEYMAP};
|
|
||||||
use yazi_core::input::InputMode;
|
use yazi_core::input::InputMode;
|
||||||
use yazi_shared::{emit, event::Exec, Layer};
|
use yazi_shared::{event::Exec, Layer};
|
||||||
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
|
|
||||||
|
|
@ -13,7 +12,7 @@ impl<'a> Executor<'a> {
|
||||||
pub(super) fn new(app: &'a mut App) -> Self { Self { app } }
|
pub(super) fn new(app: &'a mut App) -> Self { Self { app } }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn dispatch(&mut self, exec: Exec, layer: Layer) {
|
pub(super) fn execute(&mut self, exec: Exec, layer: Layer) {
|
||||||
match layer {
|
match layer {
|
||||||
Layer::App => self.app(exec),
|
Layer::App => self.app(exec),
|
||||||
Layer::Manager => self.manager(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) {
|
fn app(&mut self, exec: Exec) {
|
||||||
macro_rules! on {
|
macro_rules! on {
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ mod lives;
|
||||||
mod logs;
|
mod logs;
|
||||||
mod panic;
|
mod panic;
|
||||||
mod root;
|
mod root;
|
||||||
|
mod router;
|
||||||
mod select;
|
mod select;
|
||||||
mod signals;
|
mod signals;
|
||||||
mod tasks;
|
mod tasks;
|
||||||
|
|
@ -23,6 +24,7 @@ use logs::*;
|
||||||
use panic::*;
|
use panic::*;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use root::*;
|
use root::*;
|
||||||
|
use router::*;
|
||||||
use signals::*;
|
use signals::*;
|
||||||
|
|
||||||
#[tokio::main]
|
#[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