mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-07 12:16:44 +01:00
core, input, output, dsl: factor away 'flexi' traits
This commit is contained in:
parent
8cbd7dd8e8
commit
9f7d0efda5
11 changed files with 355 additions and 339 deletions
|
|
@ -1,8 +1,10 @@
|
|||
use crate::*;
|
||||
|
||||
/// Map of each event (e.g. key combination) to
|
||||
/// all command expressions bound to it by
|
||||
/// all loaded input layers.
|
||||
type EventMapImpl<E, C> = BTreeMap<E, Vec<Binding<C>>>;
|
||||
|
||||
/// A collection of input bindings.
|
||||
///
|
||||
/// Each contained layer defines a mapping from input event to command invocation
|
||||
|
|
@ -14,8 +16,26 @@ type EventMapImpl<E, C> = BTreeMap<E, Vec<Binding<C>>>;
|
|||
/// that .event()binding's value is returned.
|
||||
#[derive(Debug)]
|
||||
pub struct EventMap<E, C>(EventMapImpl<E, C>);
|
||||
|
||||
/// An input binding.
|
||||
#[derive(Debug)]
|
||||
pub struct Binding<C> {
|
||||
pub command: C,
|
||||
pub condition: Option<Condition>,
|
||||
pub description: Option<Arc<str>>,
|
||||
pub source: Option<Arc<PathBuf>>,
|
||||
}
|
||||
|
||||
/// Input bindings are only returned if this evaluates to true
|
||||
pub struct Condition(Box<dyn Fn()->bool + Send + Sync>);
|
||||
|
||||
impl_debug!(Condition |self, w| { write!(w, "*") });
|
||||
|
||||
/// Default is always empty map regardless if `E` and `C` implement [Default].
|
||||
impl<E, C> Default for EventMap<E, C> { fn default () -> Self { Self(Default::default()) } }
|
||||
impl<E, C> Default for EventMap<E, C> {
|
||||
fn default () -> Self { Self(Default::default()) }
|
||||
}
|
||||
|
||||
impl<E: Clone + Ord, C> EventMap<E, C> {
|
||||
/// Create a new event map
|
||||
pub fn new () -> Self {
|
||||
|
|
@ -28,7 +48,7 @@ impl<E: Clone + Ord, C> EventMap<E, C> {
|
|||
}
|
||||
/// Add a binding to an event map.
|
||||
pub fn add (&mut self, event: E, binding: Binding<C>) -> &mut Self {
|
||||
if (!self.0.contains_key(&event)) {
|
||||
if !self.0.contains_key(&event) {
|
||||
self.0.insert(event.clone(), Default::default());
|
||||
}
|
||||
self.0.get_mut(&event).unwrap().push(binding);
|
||||
|
|
@ -57,47 +77,46 @@ impl<E: Clone + Ord, C> EventMap<E, C> {
|
|||
Self::from_dsl(&mut source.as_ref())
|
||||
}
|
||||
/// Create event map from DSL tokenizer.
|
||||
pub fn from_dsl <'s, D: DslExp<'s> + 's> (dsl: &'s mut D) -> Usually<Self> where E: From<Arc<str>> {
|
||||
pub fn from_dsl <'s, > (dsl: &'s mut impl Dsl) -> Usually<Self> where E: From<Arc<str>> {
|
||||
let mut map: Self = Default::default();
|
||||
let mut head: Option<D> = dsl.head()?;
|
||||
let mut tail: Option<D> = dsl.tail()?;
|
||||
loop {
|
||||
if let Some(ref token) = head {
|
||||
if let Some(ref text) = token.text()? {
|
||||
map.0.extend(Self::from_path(PathBuf::from(text))?.0);
|
||||
continue
|
||||
if let Some(dsl) = dsl.exp()? {
|
||||
let mut head = dsl.head()?;
|
||||
let mut tail = dsl.tail()?;
|
||||
loop {
|
||||
if let Some(ref token) = head {
|
||||
if let Some(ref text) = token.text()? {
|
||||
map.0.extend(Self::from_path(PathBuf::from(text))?.0);
|
||||
continue
|
||||
}
|
||||
//if let Some(ref exp) = token.exp()? {
|
||||
////_ if let Some(sym) = token.head()?.sym()?.as_ref() => {
|
||||
////todo!()
|
||||
////},
|
||||
////_ if Some(&"if") == token.head()?.key()?.as_ref() => {
|
||||
////todo!()
|
||||
////},
|
||||
//return Err(format!("unexpected: {:?}", token.exp()).into())
|
||||
//}
|
||||
return Err(format!("unexpected: {token:?}").into())
|
||||
} else {
|
||||
break
|
||||
}
|
||||
if let Some(next) = tail {
|
||||
head = next.head()?;
|
||||
tail = next.tail()?;
|
||||
} else {
|
||||
break
|
||||
}
|
||||
//if let Some(ref exp) = token.exp()? {
|
||||
////_ if let Some(sym) = token.head()?.sym()?.as_ref() => {
|
||||
////todo!()
|
||||
////},
|
||||
////_ if Some(&"if") == token.head()?.key()?.as_ref() => {
|
||||
////todo!()
|
||||
////},
|
||||
//return Err(format!("unexpected: {:?}", token.exp()).into())
|
||||
//}
|
||||
return Err(format!("unexpected: {token:?}").into())
|
||||
} else {
|
||||
break
|
||||
}
|
||||
if let Some(next) = tail {
|
||||
head = next.head()?;
|
||||
tail = next.tail()?;
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else if let Some(text) = dsl.text()? {
|
||||
todo!("load from file path")
|
||||
} else {
|
||||
todo!("return error for invalid input")
|
||||
}
|
||||
Ok(map)
|
||||
}
|
||||
}
|
||||
/// An input binding.
|
||||
#[derive(Debug)]
|
||||
pub struct Binding<C> {
|
||||
pub command: C,
|
||||
pub condition: Option<Condition>,
|
||||
pub description: Option<Arc<str>>,
|
||||
pub source: Option<Arc<PathBuf>>,
|
||||
}
|
||||
|
||||
impl<C> Binding<C> {
|
||||
fn from_dsl (dsl: impl Dsl) -> Usually<Self> {
|
||||
let mut command: Option<C> = None;
|
||||
|
|
@ -111,8 +130,6 @@ impl<C> Binding<C> {
|
|||
}
|
||||
}
|
||||
}
|
||||
pub struct Condition(Box<dyn Fn()->bool + Send + Sync>);
|
||||
impl_debug!(Condition |self, w| { write!(w, "*") });
|
||||
|
||||
fn unquote (x: &str) -> &str {
|
||||
let mut chars = x.chars();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue