mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 12:46:42 +01:00
implement TokensIterator::peek
This commit is contained in:
parent
a949117017
commit
92fcb0af8f
7 changed files with 196 additions and 198 deletions
|
|
@ -1,5 +1,5 @@
|
|||
use crate::*;
|
||||
use std::{sync::Arc, marker::PhantomData};
|
||||
use std::{sync::Arc, fmt::Debug};
|
||||
use TokenKind::*;
|
||||
/// Define an EDN-backed view.
|
||||
///
|
||||
|
|
@ -46,104 +46,112 @@ use TokenKind::*;
|
|||
}
|
||||
}
|
||||
/// Renders from EDN source and context.
|
||||
#[derive(Default)] pub enum AtomView<'a, E: Output, T: ViewContext<'a, E> + std::fmt::Debug> {
|
||||
///
|
||||
/// Generic over:
|
||||
///
|
||||
/// * `O` - Output target.
|
||||
/// * `S` - State provider.
|
||||
/// * `A` - Atom storage type.
|
||||
#[derive(Default, Clone)] pub enum AtomView<'a, O, S, A> {
|
||||
_Unused(std::marker::PhantomData<&'a O>),
|
||||
#[default] Inert,
|
||||
Ok(T, Atom<Arc<str>>),
|
||||
//render: Box<dyn Fn(&'a T)->Box<dyn Render<E> + Send + Sync + 'a> + Send + Sync + 'a>
|
||||
Err(String),
|
||||
_Unused(PhantomData<&'a E>),
|
||||
Src(S, &'a str),
|
||||
Ref(S, &'a A),
|
||||
Own(S, A),
|
||||
Err(Arc<str>)
|
||||
}
|
||||
impl<'a, E: Output, T: ViewContext<'a, E> + std::fmt::Debug> std::fmt::Debug for AtomView<'a, E, T> {
|
||||
impl<'a, O, S, A> Debug for AtomView<'a, O, S, A>
|
||||
where S: Debug, A: Debug {
|
||||
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
match self {
|
||||
Self::Inert | Self::_Unused(_) =>
|
||||
Self::Inert =>
|
||||
write!(f, "AtomView::Inert"),
|
||||
Self::Ok(state, view) =>
|
||||
write!(f, "AtomView::Ok(state={state:?} view={view:?}"),
|
||||
Self::Src(state, view) =>
|
||||
write!(f, "AtomView::Src(state={state:?} view={view:?}"),
|
||||
Self::Ref(state, view) =>
|
||||
write!(f, "AtomView::Ref(state={state:?} view={view:?}"),
|
||||
Self::Own(state, view) =>
|
||||
write!(f, "AtomView::Arc(state={state:?} view={view:?}"),
|
||||
Self::Err(error) =>
|
||||
write!(f, "AtomView::Err({error})"),
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a, E: Output, T> ViewContext<'a, E> for T where T:
|
||||
Context<'a, bool> +
|
||||
Context<'a, usize> +
|
||||
Context<'a, E::Unit> +
|
||||
Context<'a, Box<dyn Render<E> + 'a>>
|
||||
{}
|
||||
impl<'a, E: Output, T: ViewContext<'a, E> + std::fmt::Debug> AtomView<'a, E, T> {
|
||||
pub fn from_source (state: T, source: &'a str) -> Self {
|
||||
match RefAtom::read_one(&source) {
|
||||
Ok((layout, _)) => Self::Ok(state, layout),
|
||||
Err(error) => Self::Err(format!("{error} in {source}"))
|
||||
}
|
||||
}
|
||||
pub fn from_atoms (state: T, atoms: Vec<impl Atom>) -> Self {
|
||||
Self::Ok(state, Atom::Exp(atoms).to_arc())
|
||||
}
|
||||
}
|
||||
impl<E: Output, T: for<'a>ViewContext<'a, E> + Send + Sync + std::fmt::Debug> Content<E> for AtomView<'_, E, T> {
|
||||
fn content (&self) -> impl Render<E> {
|
||||
impl<'a, O, S, A> Content<O> for AtomView<'a, O, S, A>
|
||||
where O: Output, S: ViewContext<'a, O>, A: Atom {
|
||||
fn content (&self) -> impl Render<O> {
|
||||
match self {
|
||||
Self::Ok(state, layout) => state.get_content(layout),
|
||||
Self::Err(_error) => {
|
||||
panic!("{self:?}");
|
||||
//TODO:&format!("AtomView error: {error:?}")) // FIXME: String is not Render
|
||||
},
|
||||
_ => todo!()
|
||||
Self::Inert => { panic!("inert rendered") },
|
||||
Self::Err(e) => { panic!("render error: {e}") },
|
||||
Self::Src(state, source) => {},
|
||||
Self::Ref(state, atom) => {},
|
||||
Self::Own(state, atom) => {},
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a, E: Output, T> ViewContext<'a, E> for T where T: Sized + Send + Sync
|
||||
+ Context<bool>
|
||||
+ Context<usize>
|
||||
+ Context<E::Unit>
|
||||
+ Context<Box<dyn Render<E> + 'a>> {}
|
||||
/// Provides values to the template
|
||||
pub trait ViewContext<'a, E: Output>:
|
||||
Context<'a, bool> +
|
||||
Context<'a, usize> +
|
||||
Context<'a, E::Unit> +
|
||||
Context<'a, Box<dyn Render<E> + 'a>>
|
||||
pub trait ViewContext<'a, E: Output>: Sized + Send + Sync
|
||||
+ Context<bool>
|
||||
+ Context<usize>
|
||||
+ Context<E::Unit>
|
||||
+ Context<Box<dyn Render<E> + 'a>>
|
||||
{
|
||||
fn get_bool (&'a self, atom: RefAtom<'a>) -> Option<bool> {
|
||||
fn get_bool (&self, atom: &impl Atom) -> Option<bool> {
|
||||
Some(match atom.kind() {
|
||||
Sym => match atom.text().as_ref() {
|
||||
":false" | ":f" => false,
|
||||
":true" | ":t" => true,
|
||||
Num => match atom.num() { 0 => false, _ => true },
|
||||
Sym => match atom.text() {
|
||||
":false" | ":f" => false, ":true" | ":t" => true,
|
||||
_ => return Context::get(self, atom)
|
||||
},
|
||||
Num => match atom.num() {
|
||||
0 => false,
|
||||
_ => true
|
||||
},
|
||||
_ => return Context::get(self, atom)
|
||||
})
|
||||
}
|
||||
fn get_usize (&'a self, atom: RefAtom<'a>) -> Option<usize> {
|
||||
fn get_usize (&self, atom: &impl Atom) -> Option<usize> {
|
||||
Some(match atom.kind() {
|
||||
Num => atom.num(),
|
||||
_ => return Context::get(self, atom)
|
||||
})
|
||||
}
|
||||
fn get_unit (&'a self, atom: RefAtom<'a>) -> Option<E::Unit> {
|
||||
fn get_unit (&self, atom: &impl Atom) -> Option<E::Unit> {
|
||||
Some(match atom.kind() {
|
||||
Num => E::Unit::from(atom.num() as u16),
|
||||
_ => return Context::get(self, atom)
|
||||
})
|
||||
}
|
||||
fn get_content (&'a self, atom: RefAtom<'a>) -> Option<Box<dyn Render<E> + 'a>> where E: 'a {
|
||||
try_delegate!(self, atom, When::<_, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Either::<_, RenderBox<'a, E>, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Align::<_, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Bsp::<_, RenderBox<'a, E>, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Fill::<_, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Fixed::<_, _, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Min::<_, _, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Max::<_, _, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Shrink::<_, _, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Expand::<_, _, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Push::<_, _, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Pull::<_, _, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Margin::<_, _, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Padding::<_, _, RenderBox<'a, E>>);
|
||||
Context::get_or_fail(self, atom)
|
||||
fn get_content (&self, atom: &impl Atom) -> Option<Box<dyn Render<E> + 'a>> where E: 'a {
|
||||
try_delegate!(self, atom, When::<RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Either::<RenderBox<'a, E>, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Align::<RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Bsp::<RenderBox<'a, E>, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Fill::<RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Fixed::<_, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Min::<_, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Max::<_, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Shrink::<_, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Expand::<_, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Push::<_, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Pull::<_, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Margin::<_, RenderBox<'a, E>>);
|
||||
try_delegate!(self, atom, Padding::<_, RenderBox<'a, E>>);
|
||||
Some(Context::get_or_fail(self, atom))
|
||||
}
|
||||
}
|
||||
#[macro_export] macro_rules! try_delegate {
|
||||
($s:ident, $atom:expr, $T:ty) => {
|
||||
if $atom.kind() == TokenKind::Exp {
|
||||
if let [head, tail @ ..] = $atom.as_slice() {
|
||||
if let Some(value) = <$T>::try_from_atoms($s, head, tail) {
|
||||
return Some(value.boxed())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// A function that returns a `RenderBox.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue