mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 03:36:42 +01:00
edn -> dsl
This commit is contained in:
parent
d30eda33d1
commit
877b344765
35 changed files with 197 additions and 225 deletions
|
|
@ -5,10 +5,11 @@ version = "0.1.0"
|
|||
description = "UI metaframework, input layer."
|
||||
|
||||
[dependencies]
|
||||
tengri_edn = { optional = true, path = "../edn" }
|
||||
tengri_dsl = { optional = true, path = "../dsl" }
|
||||
|
||||
[features]
|
||||
edn = [ "tengri_edn" ]
|
||||
dsl = [ "tengri_dsl" ]
|
||||
|
||||
[dev-dependencies]
|
||||
tengri_tui = { path = "../tui" }
|
||||
tengri_dsl = { path = "../dsl" }
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ impl<'a, S, I: PartialEq, C> EventMap<'a, S, I, C> {
|
|||
input_to_command!($(<$lt>)? $Command: |$state: $State, input: $Input|$KEYS.handle($state, input)?);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! input_to_command {
|
||||
(<$($l:lifetime),+> $Command:ty: |$state:ident:$State:ty, $input:ident:$Input:ty| $handler:expr) => {
|
||||
impl<$($l),+> InputToCommand<$Input, $State> for $Command {
|
||||
|
|
@ -70,4 +71,3 @@ pub trait InputToCommand<I, S>: Command<S> + Sized {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ impl<E: Input, H: Handle<E>> Handle<E> for &mut H {
|
|||
}
|
||||
impl<E: Input, H: Handle<E>> Handle<E> for Option<H> {
|
||||
fn handle (&mut self, context: &E) -> Perhaps<E::Handled> {
|
||||
if let Some(ref mut handle) = self {
|
||||
if let Some(handle) = self {
|
||||
handle.handle(context)
|
||||
} else {
|
||||
Ok(None)
|
||||
|
|
@ -1,13 +1,18 @@
|
|||
use crate::*;
|
||||
|
||||
/// [Input] state that can be matched against a [Value].
|
||||
pub trait AtomInput: Input {
|
||||
fn matches_atom (&self, token: &str) -> bool;
|
||||
}
|
||||
|
||||
#[cfg(feature = "dsl")]
|
||||
pub trait KeyMap<'a> {
|
||||
/// Try to find a command that matches the current input event.
|
||||
fn command <S, C: AtomCommand<'a, S>, I: AtomInput> (&'a self, state: &'a S, input: &'a I)
|
||||
-> Option<C>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "dsl")]
|
||||
impl<'a> KeyMap<'a> for SourceIter<'a> {
|
||||
fn command <S, C: AtomCommand<'a, S>, I: AtomInput> (&'a self, state: &'a S, input: &'a I)
|
||||
-> Option<C>
|
||||
|
|
@ -35,6 +40,8 @@ impl<'a> KeyMap<'a> for SourceIter<'a> {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dsl")]
|
||||
impl<'a> KeyMap<'a> for TokenIter<'a> {
|
||||
fn command <S, C: AtomCommand<'a, S>, I: AtomInput> (&'a self, state: &'a S, input: &'a I)
|
||||
-> Option<C>
|
||||
|
|
@ -61,10 +68,16 @@ impl<'a> KeyMap<'a> for TokenIter<'a> {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// A [Command] that can be constructed from a [Token].
|
||||
#[cfg(feature = "dsl")]
|
||||
pub trait AtomCommand<'a, C>: TryFromAtom<'a, C> + Command<C> {}
|
||||
|
||||
#[cfg(feature = "dsl")]
|
||||
impl<'a, C, T: TryFromAtom<'a, C> + Command<C>> AtomCommand<'a, C> for T {}
|
||||
|
||||
/** Implement `AtomCommand` for given `State` and `Command` */
|
||||
#[cfg(feature = "dsl")]
|
||||
#[macro_export] macro_rules! atom_command {
|
||||
($Command:ty : |$state:ident:<$State:ident: $Trait:path>| { $((
|
||||
// identifier
|
||||
|
|
@ -156,72 +169,9 @@ impl<'a, C, T: TryFromAtom<'a, C> + Command<C>> AtomCommand<'a, C> for T {}
|
|||
let $arg: $type = Context::<$type>::get_or_fail($state, $arg);
|
||||
};
|
||||
}
|
||||
//pub struct SourceKeyMap<'a>(&'a str);
|
||||
//impl<'a> KeyMap for SourceKeyMap<'a> {
|
||||
//fn command <S, C: AtomCommand<S>> (&self, state: &S, input: &AtomInput) -> Option<C> {
|
||||
//todo!();
|
||||
//None
|
||||
//}
|
||||
//}
|
||||
//pub struct ParsedKeyMap<'a>(TokensIterator<'a>);
|
||||
//impl<'a> KeyMap for ParsedKeyMap<'a> {
|
||||
//fn command <S, C: AtomCommand<S>> (&self, state: &S, input: &AtomInput) -> Option<C> {
|
||||
//todo!();
|
||||
//None
|
||||
//}
|
||||
//}
|
||||
//pub struct RefKeyMap<'a>(TokensIterator<'a>);
|
||||
//impl<'a> KeyMap for RefKeyMap<'a> {
|
||||
//fn command <S, C: AtomCommand<S>> (&self, state: &S, input: &AtomInput) -> Option<C> {
|
||||
//todo!();
|
||||
////for token in self.0 {
|
||||
////match token?.kind() {
|
||||
////TokenKind::Exp => match atoms.as_slice() {
|
||||
////[key, command, args @ ..] => match (key.kind(), key.text()) {
|
||||
////(TokenKind::Sym, key) => {
|
||||
////if input.matches_atom(key) {
|
||||
////let command = C::from_atom(state, command, args);
|
||||
////if command.is_some() {
|
||||
////return command
|
||||
////}
|
||||
////}
|
||||
////},
|
||||
////_ => panic!("invalid config: {item}")
|
||||
////},
|
||||
////_ => panic!("invalid config: {item}")
|
||||
////}
|
||||
////_ => panic!("invalid config: {item}")
|
||||
////}
|
||||
////}
|
||||
//None
|
||||
//}
|
||||
//}
|
||||
//pub struct ArcKeyMap(Vec<ArcAtom>);
|
||||
//impl KeyMap for ArcKeyMap {
|
||||
//fn command <S, C: AtomCommand<S>> (&self, state: &S, input: &AtomInput) -> Option<C> {
|
||||
//for atom in self.0.iter() {
|
||||
//match atom {
|
||||
//ArcAtom::Exp(atoms) => match atoms.as_slice() {
|
||||
//[key, command, args @ ..] => match (key.kind(), key.text()) {
|
||||
//(TokenKind::Sym, key) => {
|
||||
//if input.matches_atom(key) {
|
||||
//let command = C::from_atom(state, command, args);
|
||||
//if command.is_some() {
|
||||
//return command
|
||||
//}
|
||||
//}
|
||||
//},
|
||||
//_ => panic!("invalid config: {atom}")
|
||||
//},
|
||||
//_ => panic!("invalid config: {atom}")
|
||||
//}
|
||||
//_ => panic!("invalid config: {atom}")
|
||||
//}
|
||||
//}
|
||||
//None
|
||||
//}
|
||||
//}
|
||||
#[cfg(test)] #[test] fn test_atom_keymap () -> Usually<()> {
|
||||
|
||||
#[cfg(all(test, feature = "dsl"))]
|
||||
#[test] fn test_atom_keymap () -> Usually<()> {
|
||||
let keymap = SourceIter::new("");
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
#![feature(associated_type_defaults)]
|
||||
mod input; pub use self::input::*;
|
||||
mod command; pub use self::command::*;
|
||||
mod handle; pub use self::handle::*;
|
||||
mod keymap; pub use self::keymap::*;
|
||||
//mod event_map; pub use self::event_map::*;
|
||||
pub(crate) use ::tek_edn::*;
|
||||
|
||||
#[cfg(feature = "dsl")] pub(crate) use ::tengri_dsl::*;
|
||||
|
||||
/// Standard error trait.
|
||||
pub(crate) use std::error::Error;
|
||||
/// Standard result type.
|
||||
#[cfg(test)] pub(crate) type Usually<T> = Result<T, Box<dyn Error>>;
|
||||
|
||||
/// Standard optional result type.
|
||||
pub(crate) type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
||||
#[cfg(test)] #[test] fn test_stub_input () -> Usually<()> {
|
||||
|
||||
/// Standard result type.
|
||||
#[cfg(test)]
|
||||
pub(crate) type Usually<T> = Result<T, Box<dyn Error>>;
|
||||
|
||||
#[cfg(test)]
|
||||
#[test] fn test_stub_input () -> Usually<()> {
|
||||
use crate::*;
|
||||
struct TestInput(bool);
|
||||
enum TestEvent { Test1 }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue