yazi/yazi-config/src/keymap/rules.rs
2025-08-19 15:58:39 +08:00

49 lines
1.3 KiB
Rust

use std::ops::Deref;
use anyhow::Result;
use hashbrown::HashSet;
use serde::Deserialize;
use yazi_codegen::DeserializeOver2;
use yazi_shared::Layer;
use super::Chord;
use crate::{Preset, check_for, keymap::Key};
#[derive(Default, Deserialize, DeserializeOver2)]
pub struct KeymapRules {
pub keymap: Vec<Chord>,
#[serde(default)]
prepend_keymap: Vec<Chord>,
#[serde(default)]
append_keymap: Vec<Chord>,
}
impl Deref for KeymapRules {
type Target = Vec<Chord>;
fn deref(&self) -> &Self::Target { &self.keymap }
}
impl KeymapRules {
pub(crate) fn reshape(self, layer: Layer) -> Result<Self> {
#[inline]
fn on(Chord { on, .. }: &Chord) -> [Key; 2] {
[on.first().copied().unwrap_or_default(), on.get(1).copied().unwrap_or_default()]
}
let a_seen: HashSet<_> = self.prepend_keymap.iter().map(on).collect();
let b_seen: HashSet<_> = self.keymap.iter().map(on).collect();
let keymap = Preset::mix(
self.prepend_keymap,
self.keymap.into_iter().filter(|v| !a_seen.contains(&on(v))),
self.append_keymap.into_iter().filter(|v| !b_seen.contains(&on(v))),
)
.map(|mut chord| (chord.r#for.take(), chord))
.filter(|(r#for, chord)| !chord.noop() && check_for(r#for.as_deref()))
.map(|(_, chord)| chord.reshape(layer))
.collect::<Result<_>>()?;
Ok(Self { keymap, ..Default::default() })
}
}