diff --git a/dsl/src/dsl_provide.rs b/dsl/src/dsl_provide.rs index 4a4e3bd..92aae3d 100644 --- a/dsl/src/dsl_provide.rs +++ b/dsl/src/dsl_provide.rs @@ -1,49 +1,61 @@ use crate::*; -pub trait Dsl: Sized { - fn take_from <'state, 'source: 'state> (state: &'state State, _: &mut TokenIter<'source>) - -> Perhaps - { - unimplemented!() - } - fn take_from_or_fail <'state, 'source: 'state> ( - state: &'state State, +pub trait Dsl: Sized { + fn take <'state, 'source: 'state> ( + &'state self, + token: &mut TokenIter<'source> + ) + -> Perhaps; + fn take_or_fail <'state, 'source: 'state> ( + &'state self, token: &mut TokenIter<'source>, error: impl Into> - ) -> Usually { - if let Some(value) = Dsl::::take_from(state, token)? { + ) -> Usually { + if let Some(value) = Dsl::::take(self, token)? { Ok(value) } else { Result::Err(error.into()) } } } - -impl> DslFrom for T {} - -pub trait DslFrom>: Sized { +pub trait FromDsl: Sized { + fn take_from <'state, 'source: 'state> (state: &'state State, token: &mut TokenIter<'source>) + -> Perhaps; + fn take_from_or_fail <'state, 'source: 'state> ( + state: &'state State, + token: &mut TokenIter<'source>, + error: impl Into> + ) -> Usually { + if let Some(value) = FromDsl::::take_from(state, token)? { + Ok(value) + } else { + Result::Err(error.into()) + } + } +} +impl, State> Dsl for State { fn take <'state, 'source: 'state> (&'state self, token: &mut TokenIter<'source>) -> Perhaps { - T::take_from(self, token) - } - fn take_or_fail <'state, 'source: 'state> ( - &'state self, - token: &mut TokenIter<'source>, - error: impl Into> - ) -> Usually { - T::take_from_or_fail(self, token, error) + FromDsl::take_from(self, token) } } +//impl, T> FromDsl for T { + //fn take_from <'state, 'source: 'state> (state: &'state State, token: &mut TokenIter<'source>) + //-> Perhaps + //{ + //Dsl::take(state, token) + //} +//} /// Implement the [Dsl] trait, which boils down to /// specifying two types and providing an expression. -#[macro_export] macro_rules! dsl { - ($T:ty: |$self:ident:$S:ty, $iter:ident|$expr:expr) => { - impl ::tengri::dsl::Dsl<$S> for $T { +#[macro_export] macro_rules! from_dsl { + ($T:ty: |$state:ident:$S:ty, $words:ident|$expr:expr) => { + impl ::tengri::dsl::FromDsl<$S> for $T { fn take_from <'state, 'source: 'state> ( - state: &'state $S, - $iter: &mut ::tengri::dsl::TokenIter<'source>, + $state: &'state $S, + $words: &mut ::tengri::dsl::TokenIter<'source>, ) -> ::tengri::Perhaps<$T> { $expr } diff --git a/input/src/input_dsl.rs b/input/src/input_dsl.rs index 67b51ae..3c4e8a6 100644 --- a/input/src/input_dsl.rs +++ b/input/src/input_dsl.rs @@ -5,13 +5,13 @@ use std::marker::PhantomData; pub trait DslInput: Input { fn matches_dsl (&self, token: &str) -> bool; } /// A pre-configured mapping of input events to commands. -pub trait KeyMap + Command, I: DslInput> { +pub trait KeyMap, C: Command, I: DslInput> { /// Try to find a command that matches the current input event. fn keybind_resolve (&self, state: &S, input: &I) -> Perhaps; } /// A [SourceIter] can be a [KeyMap]. -impl<'source, S, C: Dsl + Command, I: DslInput> KeyMap for SourceIter<'source> { +impl<'source, S: Dsl, C: Command, I: DslInput> KeyMap for SourceIter<'source> { fn keybind_resolve (&self, state: &S, input: &I) -> Perhaps { let mut iter = self.clone(); while let Some((token, rest)) = iter.next() { @@ -22,7 +22,7 @@ impl<'source, S, C: Dsl + Command, I: DslInput> KeyMap for Source match exp_iter.next() { Some(Token { value: Value::Sym(binding), .. }) => { if input.matches_dsl(binding) { - if let Some(command) = Dsl::take_from(state, &mut exp_iter)? { + if let Some(command) = state.take(&mut exp_iter)? { return Ok(Some(command)) } } @@ -38,7 +38,7 @@ impl<'source, S, C: Dsl + Command, I: DslInput> KeyMap for Source } /// A [TokenIter] can be a [KeyMap]. -impl<'source, S, C: Dsl + Command, I: DslInput> KeyMap for TokenIter<'source> { +impl<'source, S: Dsl, C: Command, I: DslInput> KeyMap for TokenIter<'source> { fn keybind_resolve (&self, state: &S, input: &I) -> Perhaps { let mut iter = self.clone(); while let Some(next) = iter.next() { @@ -48,7 +48,7 @@ impl<'source, S, C: Dsl + Command, I: DslInput> KeyMap for TokenI match e.next() { Some(Token { value: Value::Sym(binding), .. }) => { if input.matches_dsl(binding) { - if let Some(command) = C::take_from(state, &mut e)? { + if let Some(command) = state.take(&mut e)? { return Ok(Some(command)) } } @@ -68,20 +68,20 @@ pub type InputLayerCond = BoxUsually + Send + Sync>; /// A collection of pre-configured mappings of input events to commands, /// which may be made available subject to given conditions. pub struct InputMap -where C: Dsl + Command, I: DslInput, M: KeyMap + Send + Sync { +where S: Dsl, C: Command, I: DslInput, M: KeyMap + Send + Sync { __: PhantomData<(S, C, I)>, pub layers: Vec<(InputLayerCond, M)>, } impl Default for InputMap -where C: Dsl + Command, I: DslInput, M: KeyMap + Send + Sync { +where S: Dsl, C: Command, I: DslInput, M: KeyMap + Send + Sync { fn default () -> Self { Self { __: PhantomData, layers: vec![] } } } impl InputMap -where C: Dsl + Command, I: DslInput, M: KeyMap + Send + Sync { +where S: Dsl, C: Command, I: DslInput, M: KeyMap + Send + Sync { pub fn new (keymap: M) -> Self { Self::default().layer(keymap) } @@ -104,7 +104,7 @@ where C: Dsl + Command, I: DslInput, M: KeyMap + Send + Sync { } impl std::fmt::Debug for InputMap -where C: Dsl + Command, I: DslInput, M: KeyMap + Send + Sync { +where S: Dsl, C: Command, I: DslInput, M: KeyMap + Send + Sync { fn fmt (&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { write!(f, "[InputMap: {} layer(s)]", self.layers.len()) } @@ -112,7 +112,7 @@ where C: Dsl + Command, I: DslInput, M: KeyMap + Send + Sync { /// An [InputMap] can be a [KeyMap]. impl KeyMap for InputMap -where C: Dsl + Command, I: DslInput, M: KeyMap + Send + Sync { +where S: Dsl, C: Command, I: DslInput, M: KeyMap + Send + Sync { fn keybind_resolve (&self, state: &S, input: &I) -> Perhaps { for (condition, keymap) in self.layers.iter() { if !condition(state)? { diff --git a/output/src/ops/align.rs b/output/src/ops/align.rs index 7a9377f..9d902ad 100644 --- a/output/src/ops/align.rs +++ b/output/src/ops/align.rs @@ -36,20 +36,17 @@ pub enum Alignment { #[default] Center, X, Y, NW, N, NE, E, SE, S, SW, W } pub struct Align(Alignment, A); #[cfg(feature = "dsl")] -impl<'state, E: Output + 'state, T: ViewContext<'state, E>> -Dsl for Align> { - fn take_from <'source: 'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Perhaps { +impl, A> FromDsl for Align { + fn take_from <'state, 'source: 'state> (state: &'state State, iter: &mut TokenIter<'source>) + -> Perhaps + { if let Some(Token { value: Value::Key(key), .. }) = iter.peek() { match key { "align/c"|"align/x"|"align/y"| "align/n"|"align/s"|"align/e"|"align/w"| "align/nw"|"align/sw"|"align/ne"|"align/se" => { let _ = iter.next().unwrap(); - let content = if let Some(content) = state.get_content(&mut iter.clone())? { - content - } else { - panic!("no content corresponding to {:?}", &iter); - }; + let content = state.take_or_fail(&mut iter.clone(), "expected content")?; return Ok(Some(match key { "align/c" => Self::c(content), "align/x" => Self::x(content), diff --git a/output/src/ops/bsp.rs b/output/src/ops/bsp.rs index 895916c..7e961dd 100644 --- a/output/src/ops/bsp.rs +++ b/output/src/ops/bsp.rs @@ -21,9 +21,8 @@ impl, B: Content> Content for Bsp { } } #[cfg(feature = "dsl")] -impl<'state, E: Output + 'state, T: ViewContext<'state, E>> -Dsl for Bsp, RenderBox<'state, E>> { - fn take_from <'source: 'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Perhaps { +impl + Dsl> FromDsl for Bsp { + fn take_from <'state, 'source: 'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Perhaps { Ok(if let Some(Token { value: Value::Key("bsp/n"|"bsp/s"|"bsp/e"|"bsp/w"|"bsp/a"|"bsp/b"), .. @@ -31,23 +30,23 @@ Dsl for Bsp, RenderBox<'state, E>> { let base = iter.clone(); return Ok(Some(match iter.next() { Some(Token { value: Value::Key("bsp/n"), .. }) => - Self::n(state.get_content_or_fail(iter)?, - state.get_content_or_fail(iter)?), + Self::n(state.take_or_fail(iter, "expected content 1")?, + state.take_or_fail(iter, "expected content 2")?), Some(Token { value: Value::Key("bsp/s"), .. }) => - Self::s(state.get_content_or_fail(iter)?, - state.get_content_or_fail(iter)?), + Self::s(state.take_or_fail(iter, "expected content 1")?, + state.take_or_fail(iter, "expected content 2")?), Some(Token { value: Value::Key("bsp/e"), .. }) => - Self::e(state.get_content_or_fail(iter)?, - state.get_content_or_fail(iter)?), + Self::e(state.take_or_fail(iter, "expected content 1")?, + state.take_or_fail(iter, "expected content 2")?), Some(Token { value: Value::Key("bsp/w"), .. }) => - Self::w(state.get_content_or_fail(iter)?, - state.get_content_or_fail(iter)?), + Self::w(state.take_or_fail(iter, "expected content 1")?, + state.take_or_fail(iter, "expected content 2")?), Some(Token { value: Value::Key("bsp/a"), .. }) => - Self::a(state.get_content_or_fail(iter)?, - state.get_content_or_fail(iter)?), + Self::a(state.take_or_fail(iter, "expected content 1")?, + state.take_or_fail(iter, "expected content 2")?), Some(Token { value: Value::Key("bsp/b"), .. }) => - Self::b(state.get_content_or_fail(iter)?, - state.get_content_or_fail(iter)?), + Self::b(state.take_or_fail(iter, "expected content 1")?, + state.take_or_fail(iter, "expected content 2")?), _ => unreachable!(), })) } else { diff --git a/output/src/ops/cond.rs b/output/src/ops/cond.rs index 8d8a27e..ca5ea61 100644 --- a/output/src/ops/cond.rs +++ b/output/src/ops/cond.rs @@ -17,44 +17,26 @@ impl Either { Self(c, a, b) } } - #[cfg(feature = "dsl")] -impl<'state, E: Output + 'state, T: ViewContext<'state, E>> -Dsl for When> { - fn take_from <'source: 'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Perhaps { +impl + Dsl> FromDsl for When { + fn take_from <'state, 'source: 'state> ( + state: &'state T, + token: &mut TokenIter<'source> + ) -> Perhaps { Ok(if let Some(Token { value: Value::Key("when"), .. - }) = iter.peek() { - let base = iter.clone(); + }) = token.peek() { + let base = token.clone(); return Ok(Some(Self( - state.take(iter)?.unwrap_or_else(||panic!("cond: no condition: {base:?}")), - state.get_content_or_fail(iter)? + state.take_or_fail(token, "cond: no condition")?, + state.take_or_fail(token, "cond: no content")?, ))) } else { None }) } } - -#[cfg(feature = "dsl")] -impl<'state, E: Output + 'state, T: ViewContext<'state, E>> -Dsl for Either, RenderBox<'state, E>> { - fn take_from <'source: 'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Perhaps { - if let Some(Token { value: Value::Key("either"), .. }) = iter.peek() { - let base = iter.clone(); - let _ = iter.next().unwrap(); - //panic!("{iter:?}"); - return Ok(Some(Self( - state.take(iter)?.unwrap_or_else(||panic!("either: no condition: {base:?}")), - state.get_content_or_fail(iter)?, - state.get_content_or_fail(iter)?, - ))) - } - Ok(None) - } -} - impl> Content for When { fn layout (&self, to: E::Area) -> E::Area { let Self(cond, item) = self; @@ -73,7 +55,24 @@ impl> Content for When { if *cond { item.render(to) } } } - +#[cfg(feature = "dsl")] +impl + Dsl + Dsl> FromDsl for Either { + fn take_from <'state, 'source: 'state> ( + state: &'state T, + token: &mut TokenIter<'source> + ) -> Perhaps { + if let Some(Token { value: Value::Key("either"), .. }) = token.peek() { + let base = token.clone(); + let _ = token.next().unwrap(); + return Ok(Some(Self( + state.take_or_fail(token, "either: no condition")?, + state.take_or_fail(token, "either: no content 1")?, + state.take_or_fail(token, "either: no content 2")?, + ))) + } + Ok(None) + } +} impl, B: Render> Content for Either { fn layout (&self, to: E::Area) -> E::Area { let Self(cond, a, b) = self; diff --git a/output/src/ops/transform.rs b/output/src/ops/transform.rs index b94def2..c589bfd 100644 --- a/output/src/ops/transform.rs +++ b/output/src/ops/transform.rs @@ -26,31 +26,24 @@ use crate::*; /// along either the X axis, the Y axis, or both. macro_rules! transform_xy { ($x:literal $y:literal $xy:literal |$self:ident : $Enum:ident, $to:ident|$area:expr) => { - pub enum $Enum { X(T), Y(T), XY(T) } - impl $Enum { - #[inline] pub const fn x (item: T) -> Self { - Self::X(item) - } - #[inline] pub const fn y (item: T) -> Self { - Self::Y(item) - } - #[inline] pub const fn xy (item: T) -> Self { - Self::XY(item) - } + pub enum $Enum { X(A), Y(A), XY(A) } + impl $Enum { + #[inline] pub const fn x (item: A) -> Self { Self::X(item) } + #[inline] pub const fn y (item: A) -> Self { Self::Y(item) } + #[inline] pub const fn xy (item: A) -> Self { Self::XY(item) } } #[cfg(feature = "dsl")] - impl<'state, E: Output + 'state, T: ViewContext<'state, E>> - Dsl for $Enum> { - fn take_from <'source: 'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Perhaps { + impl> FromDsl for $Enum { + fn take_from <'state, 'source: 'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Perhaps { if let Some(Token { value: Value::Key(k), .. }) = iter.peek() { let mut base = iter.clone(); return Ok(Some(match iter.next() { Some(Token{value:Value::Key($x),..}) => - Self::x(state.get_content_or_fail(iter)?), + Self::x(state.take_or_fail(iter, "x: no content")?), Some(Token{value:Value::Key($y),..}) => - Self::y(state.get_content_or_fail(iter)?), + Self::y(state.take_or_fail(iter, "y: no content")?), Some(Token{value:Value::Key($xy),..}) => - Self::xy(state.get_content_or_fail(iter)?), + Self::xy(state.take_or_fail(iter, "xy: no content")?), _ => unreachable!() })) } @@ -77,31 +70,30 @@ macro_rules! transform_xy { /// along either the X axis, the Y axis, or both. macro_rules! transform_xy_unit { ($x:literal $y:literal $xy:literal |$self:ident : $Enum:ident, $to:ident|$layout:expr) => { - pub enum $Enum { X(U, T), Y(U, T), XY(U, U, T), } - impl $Enum { - #[inline] pub const fn x (x: U, item: T) -> Self { Self::X(x, item) } - #[inline] pub const fn y (y: U, item: T) -> Self { Self::Y(y, item) } - #[inline] pub const fn xy (x: U, y: U, item: T) -> Self { Self::XY(x, y, item) } + pub enum $Enum { X(U, A), Y(U, A), XY(U, U, A), } + impl $Enum { + #[inline] pub const fn x (x: U, item: A) -> Self { Self::X(x, item) } + #[inline] pub const fn y (y: U, item: A) -> Self { Self::Y(y, item) } + #[inline] pub const fn xy (x: U, y: U, item: A) -> Self { Self::XY(x, y, item) } } #[cfg(feature = "dsl")] - impl<'state, E: Output + 'state, T: ViewContext<'state, E>> - Dsl for $Enum> { - fn take_from <'source: 'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Perhaps { + impl + Dsl> FromDsl for $Enum { + fn take_from <'state, 'source: 'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Perhaps { Ok(if let Some(Token { value: Value::Key($x|$y|$xy), .. }) = iter.peek() { let mut base = iter.clone(); Some(match iter.next() { Some(Token { value: Value::Key($x), .. }) => Self::x( - state.take_or_fail(iter, "no unit specified")?, - state.get_content_or_fail(iter)?, + state.take_or_fail(iter, "x: no unit")?, + state.take_or_fail(iter, "x: no content")?, ), Some(Token { value: Value::Key($y), .. }) => Self::y( - state.take_or_fail(iter, "no unit specified")?, - state.get_content_or_fail(iter)?, + state.take_or_fail(iter, "y: no unit")?, + state.take_or_fail(iter, "y: no content")?, ), Some(Token { value: Value::Key($x), .. }) => Self::xy( - state.take_or_fail(iter, "no unit specified")?, - state.take_or_fail(iter, "no unit specified")?, - state.get_content_or_fail(iter)? + state.take_or_fail(iter, "xy: no unit x")?, + state.take_or_fail(iter, "xy: no unit y")?, + state.take_or_fail(iter, "xy: no content")? ), _ => unreachable!(), }) diff --git a/output/src/view.rs b/output/src/view.rs index 460f1c5..2ae266e 100644 --- a/output/src/view.rs +++ b/output/src/view.rs @@ -1,63 +1,54 @@ use crate::*; -#[cfg(feature = "dsl")] -#[macro_export] macro_rules! try_delegate { - ($s:ident, $dsl:expr, $T:ty) => { - let value: Option<$T> = Dsl::take_from($s, $dsl)?; - if let Some(value) = value { - return Ok(Some(value.boxed())) - } - } -} +//#[cfg(feature = "dsl")] +//#[macro_export] macro_rules! try_delegate { + //($s:ident, $dsl:expr, $T:ty) => { + //let value: Option<$T> = Dsl::take_from($s, $dsl)?; + //if let Some(value) = value { + //return Ok(Some(value.boxed())) + //} + //} +//} -// Provides components to the view. -#[cfg(feature = "dsl")] -pub trait ViewContext<'state, E: Output + 'state>: Send + Sync where - bool: Dsl, - usize: Dsl, - E::Unit: Dsl, -{ - fn get_content_or_fail <'source: 'state> (&'state self, iter: &mut TokenIter<'source>) - -> Usually> - { - let base = iter.clone(); - if let Some(content) = self.get_content(iter)? { - Ok(content) - } else { - Err(format!("not found: {iter:?}").into()) - } - } - fn get_content <'source: 'state> (&'state self, iter: &mut TokenIter<'source>) - -> Perhaps> - { - match iter.peek() { - Some(Token { value: Value::Sym(_), .. }) => - self.get_content_sym(iter), - Some(Token { value: Value::Exp(_, _), .. }) => - self.get_content_exp(iter), - None => Ok(None), - _ => panic!("only :symbols and (expressions) accepted here") - } - } - fn get_content_sym <'source: 'state> (&'state self, iter: &mut TokenIter<'source>) - -> Perhaps>; - fn get_content_exp <'source: 'state> (&'state self, iter: &mut TokenIter<'source>) - -> Perhaps> - { - try_delegate!(self, iter, When::>); - try_delegate!(self, iter, Either::, RenderBox<'state, E>>); - try_delegate!(self, iter, Align::>); - try_delegate!(self, iter, Bsp::, RenderBox<'state, E>>); - try_delegate!(self, iter, Fill::>); - try_delegate!(self, iter, Fixed::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Min::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Max::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Shrink::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Expand::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Push::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Pull::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Margin::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Padding::<_, RenderBox<'state, E>>); - Ok(None) - } -} +//// Provides components to the view. +//#[cfg(feature = "dsl")] +//pub trait ViewContext<'state, E: Output + 'state>: + //FromDsl + FromDsl + FromDsl + Send + Sync +//{ + //fn get_content_sym <'source: 'state> (&'state self, iter: &mut TokenIter<'source>) + //-> Perhaps>; + //fn get_content_exp <'source: 'state> (&'state self, iter: &mut TokenIter<'source>) + //-> Perhaps> + //{ + //try_delegate!(self, iter, When::>); + //try_delegate!(self, iter, Either::, RenderBox<'state, E>>); + //try_delegate!(self, iter, Align::>); + //try_delegate!(self, iter, Bsp::, RenderBox<'state, E>>); + //try_delegate!(self, iter, Fill::>); + //try_delegate!(self, iter, Fixed::<_, RenderBox<'state, E>>); + //try_delegate!(self, iter, Min::<_, RenderBox<'state, E>>); + //try_delegate!(self, iter, Max::<_, RenderBox<'state, E>>); + //try_delegate!(self, iter, Shrink::<_, RenderBox<'state, E>>); + //try_delegate!(self, iter, Expand::<_, RenderBox<'state, E>>); + //try_delegate!(self, iter, Push::<_, RenderBox<'state, E>>); + //try_delegate!(self, iter, Pull::<_, RenderBox<'state, E>>); + //try_delegate!(self, iter, Margin::<_, RenderBox<'state, E>>); + //try_delegate!(self, iter, Padding::<_, RenderBox<'state, E>>); + //Ok(None) + //} +//} + +//#[cfg(feature = "dsl")] +//impl<'context, O: Output + 'context, T: ViewContext<'context, O>> FromDsl for RenderBox<'context, O> { + //fn take_from <'state, 'source: 'state> (state: &'state T, token: &mut TokenIter<'source>) + //-> Perhaps> + //{ + //Ok(if let Some(content) = state.get_content_sym(token)? { + //Some(content) + //} else if let Some(content) = state.get_content_exp(token)? { + //Some(content) + //} else { + //None + //}) + //} +//} diff --git a/proc/src/proc_command.rs b/proc/src/proc_command.rs index 27f68ff..9d83f9f 100644 --- a/proc/src/proc_command.rs +++ b/proc/src/proc_command.rs @@ -144,12 +144,11 @@ impl ToTokens for CommandDef { } } /// Generated by [tengri_proc]. - impl ::tengri::dsl::Dsl<#command_enum> for #state { - fn take <'source, 'state> ( - &'state self, words: &mut TokenIter<'source> - ) - -> ::tengri::Perhaps<#command_enum> - { + impl ::tengri::dsl::FromDsl<#state> for #command_enum { + fn take_from <'state, 'source: 'state> ( + state: &'state #state, + words: &mut TokenIter<'source>, + ) -> Perhaps { let mut words = words.clone(); let token = words.next(); todo!()//Ok(match token { #(#matchers)* _ => None }) diff --git a/proc/src/proc_expose.rs b/proc/src/proc_expose.rs index d6f23a8..887121d 100644 --- a/proc/src/proc_expose.rs +++ b/proc/src/proc_expose.rs @@ -60,7 +60,7 @@ impl ToTokens for ExposeDef { impl ToTokens for ExposeImpl { fn to_tokens (&self, out: &mut TokenStream2) { let Self(block, exposed) = self; - let target = &block.self_ty; + let exposed_impl_type = &block.self_ty; write_quote_to(out, quote! { #block }); for (t, variants) in exposed.iter() { let formatted_type = format!("{}", quote! { #t }); @@ -84,12 +84,13 @@ impl ToTokens for ExposeImpl { }; let values = variants.iter().map(ExposeArm::from); write_quote_to(out, quote! { - /// Generated by [tengri_proc]. - impl ::tengri::dsl::Dsl<#t> for #target { - fn take <'state, 'source> ( - &'state self, iter: &mut ::tengri::dsl::TokenIter<'source> + /// Generated by [tengriproc]. + impl ::tengri::dsl::Dsl<#t> for #exposed_impl_type { + fn take <'state, 'source: 'state> ( + &'state self, + words: &mut ::tengri::dsl::TokenIter<'source> ) -> Perhaps<#t> { - Ok(Some(match iter.next().map(|x|x.value) { + Ok(Some(match words.next().map(|x|x.value) { #predefined #(#values,)* _ => return Ok(None) diff --git a/proc/src/proc_view.rs b/proc/src/proc_view.rs index 6947766..321fb26 100644 --- a/proc/src/proc_view.rs +++ b/proc/src/proc_view.rs @@ -41,15 +41,33 @@ impl Parse for ViewImpl { } } +fn builtins () -> [TokenStream2;14] { + [ + quote! { When:: }, + quote! { Either:: }, + quote! { Align:: }, + quote! { Bsp:: }, + quote! { Fill:: }, + quote! { Fixed::<_, A> }, + quote! { Min::<_, A> }, + quote! { Max::<_, A> }, + quote! { Shrink::<_, A> }, + quote! { Expand::<_, A> }, + quote! { Push::<_, A> }, + quote! { Pull::<_, A> }, + quote! { Margin::<_, A> }, + quote! { Padding::<_, A> }, + ] +} + impl ToTokens for ViewDef { fn to_tokens (&self, out: &mut TokenStream2) { let Self(ViewMeta { output }, ViewImpl { block, exposed }) = self; let view = &block.self_ty; let mut available = vec![]; - let exposed: Vec<_> = exposed.iter().map(|(k,v)|{ - available.push(k.clone()); - ViewArm(k.clone(), v.clone()) - }).collect(); + let exposed: Vec<_> = exposed.iter() + .map(|(k,v)|{ available.push(k.clone()); ViewArm(k.clone(), v.clone()) }) + .collect(); let available: String = available.join(", "); let error_msg = LitStr::new( &format!("expected Sym(content), got: {{token:?}}, available: {available}"), @@ -58,43 +76,33 @@ impl ToTokens for ViewDef { for token in quote! { #block /// Generated by [tengri_proc]. + /// + /// Delegates the rendering of [#view] to the [#view::view} method, + /// which you will need to implement, e.g. passing a [TokenIter] + /// containing a layout and keybindings config from user dirs. impl ::tengri::output::Content<#output> for #view { fn content (&self) -> impl Render<#output> { self.view() } } /// Generated by [tengri_proc]. - impl<'state> ::tengri::dsl::FromDsl<'state, #view> - for ::tengri::output::RenderBox<'state, #output> { - fn take_from <'source: 'state> ( - state: &'state #view, - token: &mut ::tengri::dsl::TokenIter<'source> + /// + /// Gives [#view] the ability to construct the [Render]able + /// which might corresponds to a given [TokenStream], + /// while taking [#view]'s state into consideration. + impl<'context> ::tengri::dsl::FromDsl<#view> for RenderBox<'context, #output> { + fn take_from <'state, 'source: 'state> ( + state: &'state #view, words: &mut ::tengri::dsl::TokenIter<'source> ) -> Perhaps { - Ok(match token.peek() { - Some(::tengri::dsl::Token { - ::tengri::dsl::value: Value::Exp(exp), .. - }) => { - let value: Option<$T> = FromDsl::take_from($s, $dsl)?; - if let Some(value) = value { + Ok(match words.peek() { + Some(::tengri::dsl::Token { value: ::tengri::dsl::Value::Exp(exp), .. }) => { + if let Some(value) = FromDsl::take_from(state, words)? { return Ok(Some(value.boxed())) } - try_delegate!(self, iter, When::>); - try_delegate!(self, iter, Either::, RenderBox<'state, E>>); - try_delegate!(self, iter, Align::>); - try_delegate!(self, iter, Bsp::, RenderBox<'state, E>>); - try_delegate!(self, iter, Fill::>); - try_delegate!(self, iter, Fixed::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Min::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Max::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Shrink::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Expand::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Push::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Pull::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Margin::<_, RenderBox<'state, E>>); - try_delegate!(self, iter, Padding::<_, RenderBox<'state, E>>); + //#builtins None }, - #(#exposed),* + #(#exposed)* _ => None }) } @@ -162,5 +170,6 @@ impl ToTokens for ViewArm { out.append(Group::new(Delimiter::Parenthesis, TokenStream2::new())); out })); + out.append(Punct::new(',', Alone)); } }