mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 14:51:03 +00:00
74 lines
1.8 KiB
Rust
74 lines
1.8 KiB
Rust
use std::{ops::Deref, sync::Arc};
|
|
|
|
use arc_swap::ArcSwap;
|
|
use serde::Deserialize;
|
|
use yazi_shared::Layer;
|
|
use yazi_shim::{arc_swap::{ArcSwapExt, IntoPointee}, vec::{IndexAtError, VecExt}};
|
|
|
|
use crate::keymap::{Chord, ChordArc, ChordMatcher};
|
|
|
|
#[derive(Debug, Default, Deserialize)]
|
|
pub struct Chords<const L: u8 = { Layer::Null as u8 }>(ArcSwap<Vec<ChordArc<L>>>);
|
|
|
|
impl<const L: u8> Deref for Chords<L> {
|
|
type Target = ArcSwap<Vec<ChordArc<L>>>;
|
|
|
|
fn deref(&self) -> &Self::Target { &self.0 }
|
|
}
|
|
|
|
impl<const L: u8> From<Vec<ChordArc<L>>> for Chords<L> {
|
|
fn from(inner: Vec<ChordArc<L>>) -> Self { Self(inner.into_pointee()) }
|
|
}
|
|
|
|
impl<const L: u8> Chords<L> {
|
|
pub fn as_erased<const M: u8>(&self) -> Arc<Vec<ChordArc<M>>> {
|
|
let chords = self.0.load_full();
|
|
unsafe { Arc::from_raw(Arc::into_raw(chords) as *const Vec<ChordArc<M>>) }
|
|
}
|
|
|
|
pub fn insert(&self, index: isize, rule: ChordArc) -> Result<(), IndexAtError> {
|
|
self.0.try_rcu(|rules| {
|
|
let (before, after) = rules.split_at(rules.index_at(index)?);
|
|
Ok(
|
|
before
|
|
.iter()
|
|
.cloned()
|
|
.chain([rule.as_erased().clone()])
|
|
.chain(after.iter().cloned())
|
|
.collect::<Vec<_>>(),
|
|
)
|
|
})?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn remove(&self, matcher: ChordMatcher) {
|
|
self.0.rcu(|chords| {
|
|
let mut next = Vec::clone(chords);
|
|
next.retain(|arc| !matcher.matches(arc.as_erased()));
|
|
next
|
|
});
|
|
}
|
|
|
|
pub fn update<E>(
|
|
&self,
|
|
matcher: ChordMatcher,
|
|
f: impl Fn(Chord) -> Result<Chord, E>,
|
|
) -> Result<(), E> {
|
|
self.0.try_rcu(|rules| {
|
|
let mut next = Vec::clone(rules);
|
|
for arc in &mut next {
|
|
if matcher.matches(arc.as_erased()) {
|
|
*arc = f(Chord::clone(arc.as_erased()))?.into();
|
|
}
|
|
}
|
|
Ok(Arc::new(next))
|
|
})?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub(crate) fn unwrap_unchecked(self) -> Vec<ChordArc<L>> {
|
|
Arc::try_unwrap(self.0.into_inner()).expect("unique chords arc")
|
|
}
|
|
}
|