mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
wip: more const parsing
This commit is contained in:
parent
ff31957fed
commit
297f9b30df
4 changed files with 141 additions and 114 deletions
|
|
@ -1,13 +1,49 @@
|
|||
use crate::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct KeyMap<'a, T>(AtomIterator<'a>);
|
||||
impl<'a, T> KeyMap<'a, T> {
|
||||
pub const fn new (source: &'a str) -> Self {
|
||||
Self(AtomIterator::new(TokenIterator::new(source)))
|
||||
}
|
||||
/// Try to find a binding matching the currently pressed key
|
||||
pub fn command <S, C> (&self, state: &S, input: &impl EdnInput) -> Option<C>
|
||||
where
|
||||
C: Command<S> + EdnCommand<S>
|
||||
{
|
||||
use Atom::*;
|
||||
let mut command: Option<C> = None;
|
||||
match self {
|
||||
Self::TokenIterator(t) => todo!(),
|
||||
Self::TokenSlice(t) => todo!(),
|
||||
Self::TokenVec(t) => todo!(),
|
||||
//Self::AtomIterator(t) => todo!(),
|
||||
Self::AtomSlice(t) => todo!(),
|
||||
Self::Atom(t) => todo!(),
|
||||
}
|
||||
for item in self.0.iter() {
|
||||
if let Exp(e) = item {
|
||||
match e.as_slice() {
|
||||
[Sym(key), c, args @ ..] if input.matches_edn(key) => {
|
||||
command = C::from_edn(state, c, args);
|
||||
if command.is_some() {
|
||||
break
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
panic!("invalid config")
|
||||
}
|
||||
}
|
||||
command
|
||||
}
|
||||
}
|
||||
/// [Input] state that can be matched against an [Atom].
|
||||
pub trait EdnInput: Input {
|
||||
fn matches_edn (&self, token: &str) -> bool;
|
||||
fn get_event (_: &Atom<impl AsRef<str>>) -> Option<Self::Event> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Turns an EDN item sequence into a command enum variant.
|
||||
pub trait EdnCommand<C>: Command<C> {
|
||||
fn from_edn <'a> (
|
||||
|
|
@ -16,7 +52,6 @@ pub trait EdnCommand<C>: Command<C> {
|
|||
tail: &'a [Atom<impl AsRef<str>>]
|
||||
) -> Option<Self>;
|
||||
}
|
||||
|
||||
/** Implement `EdnCommand` for given `State` and `Command` */
|
||||
#[macro_export] macro_rules! edn_command {
|
||||
($Command:ty : |$state:ident:<$T:ident: $Trait:path>| { $((
|
||||
|
|
@ -112,39 +147,6 @@ pub trait EdnCommand<C>: Command<C> {
|
|||
let $arg: $type = EdnProvide::<$type>::get_or_fail($state, $arg);
|
||||
};
|
||||
}
|
||||
|
||||
pub struct KeyMap(Vec<Atom<Arc<str>>>);
|
||||
impl KeyMap {
|
||||
/// Construct keymap from source text or fail
|
||||
pub fn new (keymap: &str) -> Usually<Self> {
|
||||
Ok(Self(Atom::read_all(keymap)?))
|
||||
}
|
||||
/// Try to find a binding matching the currently pressed key
|
||||
pub fn command <T, C> (&self, state: &T, input: &impl EdnInput) -> Option<C>
|
||||
where
|
||||
C: Command<T> + EdnCommand<T>
|
||||
{
|
||||
use Atom::*;
|
||||
let mut command: Option<C> = None;
|
||||
for item in self.0.iter() {
|
||||
if let Exp(e) = item {
|
||||
match e.as_slice() {
|
||||
[Sym(key), c, args @ ..] if input.matches_edn(key) => {
|
||||
command = C::from_edn(state, c, args);
|
||||
if command.is_some() {
|
||||
break
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
panic!("invalid config")
|
||||
}
|
||||
}
|
||||
command
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)] #[test] fn test_edn_keymap () -> Usually<()> {
|
||||
let keymap = KeyMap::new("")?;
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ mod input; pub use self::input::*;
|
|||
mod command; pub use self::command::*;
|
||||
mod keymap; pub use self::keymap::*;
|
||||
//mod event_map; pub use self::event_map::*;
|
||||
pub(crate) use ::tek_edn::Atom;
|
||||
pub(crate) use ::tek_edn::*;
|
||||
/// Standard error trait.
|
||||
pub(crate) use std::error::Error;
|
||||
/// Standard result type.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue