yazi/yazi-fm/src/router.rs

62 lines
1.6 KiB
Rust

use anyhow::Result;
use yazi_actor::Ctx;
use yazi_config::{KEYMAP, keymap::{Chord, Key}};
use yazi_core::which::WhichOpt;
use yazi_macro::act;
use yazi_shared::Layer;
use yazi_term::event::KeyEvent;
use crate::{Dispatcher, app::App};
pub(super) struct Router<'a> {
app: &'a mut App,
}
impl<'a> Router<'a> {
pub(super) fn new(app: &'a mut App) -> Self { Self { app } }
pub(super) fn route(&mut self, key: KeyEvent) -> Result<bool> {
use Layer as L;
let core = &mut self.app.core;
if core.help.visible && core.help.r#type(&key)? {
return Ok(true);
}
if let Some(mut guard) = core.input.lock_mut()
&& guard.r#type(&key)?
{
return Ok(true);
}
let layer = core.layer();
let key = Key::from(key);
Ok(match layer {
L::Null | L::App | L::Notify => unreachable!(),
L::Mgr | L::Tasks | L::Spot | L::Pick | L::Input | L::Confirm => {
self.matches(layer, layer, key)
}
L::Help => self.matches(L::Help, L::Help, key) || self.matches(L::Input, L::Help, key),
L::Cmp => self.matches(L::Cmp, L::Cmp, key) || self.matches(L::Input, L::Input, key),
L::Which => core.which.r#type(key),
})
}
fn matches(&mut self, src: Layer, dist: Layer, key: Key) -> bool {
for chord in &*KEYMAP.chords(src) {
let Chord { on, .. } = chord.as_ref();
if on.is_empty() || on[0] != key {
continue;
}
if on.len() > 1 {
let cx = &mut Ctx::active(&mut self.app.core, &mut self.app.term);
act!(which:activate, cx, WhichOpt::new(src, dist, key)).ok();
} else {
Dispatcher::new(self.app).dispatch_seq(chord.to_seq(dist));
}
return true;
}
false
}
}