From f797a7143dcee3b7d4b41ed32c80804dbe403936 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Tue, 20 May 2025 16:27:05 +0300 Subject: [PATCH] extact dsl_token; flip Dsl; try to obviate ViewContext --- dsl/src/dsl_parse.rs | 109 ----------------------------------- dsl/src/dsl_provide.rs | 106 +++++++++++++++++++--------------- dsl/src/dsl_token.rs | 110 ++++++++++++++++++++++++++++++++++++ dsl/src/lib.rs | 1 + input/src/input_dsl.rs | 22 ++++---- output/src/ops/align.rs | 2 +- output/src/ops/bsp.rs | 2 +- output/src/ops/cond.rs | 4 +- output/src/ops/stack.rs | 71 +++++++++++++---------- output/src/ops/transform.rs | 4 +- output/src/view.rs | 10 ++-- proc/src/proc_view.rs | 32 ++++++++++- 12 files changed, 264 insertions(+), 209 deletions(-) create mode 100644 dsl/src/dsl_token.rs diff --git a/dsl/src/dsl_parse.rs b/dsl/src/dsl_parse.rs index 81a0336..63bc567 100644 --- a/dsl/src/dsl_parse.rs +++ b/dsl/src/dsl_parse.rs @@ -171,112 +171,3 @@ pub const fn to_digit (c: char) -> DslResult { _ => return Result::Err(Unexpected(c)) }) } - -#[derive(Debug, Copy, Clone, Default, PartialEq)] pub struct Token<'source> { - pub source: &'source str, - pub start: usize, - pub length: usize, - pub value: Value<'source>, -} - -#[derive(Debug, Copy, Clone, Default, PartialEq)] pub enum Value<'source> { - #[default] Nil, - Err(DslError), - Num(usize), - Sym(&'source str), - Key(&'source str), - Str(&'source str), - Exp(usize, TokenIter<'source>), -} - -impl<'source> std::fmt::Display for Value<'source> { - fn fmt (&self, out: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - write!(out, "{}", match self { - Nil => String::new(), - Err(e) => format!("[error: {e}]"), - Num(n) => format!("{n}"), - Sym(s) => format!("{s}"), - Key(s) => format!("{s}"), - Str(s) => format!("{s}"), - Exp(_, e) => format!("{e:?}"), - }) - } -} - -impl<'source> Token<'source> { - pub const fn new ( - source: &'source str, start: usize, length: usize, value: Value<'source> - ) -> Self { - Self { source, start, length, value } - } - pub const fn end (&self) -> usize { - self.start.saturating_add(self.length) - } - pub const fn slice (&'source self) -> &'source str { - self.slice_source(self.source) - } - pub const fn slice_source <'range> (&'source self, source: &'range str) -> &'range str { - str_range(source, self.start, self.end()) - } - pub const fn slice_source_exp <'range> (&'source self, source: &'range str) -> &'range str { - str_range(source, self.start.saturating_add(1), self.end()) - } - pub const fn with_value (self, value: Value<'source>) -> Self { - Self { value, ..self } - } - pub const fn value (&self) -> Value { - self.value - } - pub const fn error (self, error: DslError) -> Self { - Self { value: Value::Err(error), ..self } - } - pub const fn grow (self) -> Self { - Self { length: self.length.saturating_add(1), ..self } - } - pub const fn grow_num (self, m: usize, c: char) -> Self { - match to_digit(c) { - Ok(n) => Self { value: Num(10*m+n), ..self.grow() }, - Result::Err(e) => Self { value: Err(e), ..self.grow() }, - } - } - pub const fn grow_key (self) -> Self { - let token = self.grow(); - token.with_value(Key(token.slice_source(self.source))) - } - pub const fn grow_sym (self) -> Self { - let token = self.grow(); - token.with_value(Sym(token.slice_source(self.source))) - } - pub const fn grow_str (self) -> Self { - let token = self.grow(); - token.with_value(Str(token.slice_source(self.source))) - } - pub const fn grow_exp (self) -> Self { - let token = self.grow(); - if let Exp(depth, _) = token.value { - token.with_value(Exp(depth, TokenIter::new(token.slice_source_exp(self.source)))) - } else { - unreachable!() - } - } - pub const fn grow_in (self) -> Self { - let token = self.grow_exp(); - if let Value::Exp(depth, source) = token.value { - token.with_value(Value::Exp(depth.saturating_add(1), source)) - } else { - unreachable!() - } - } - pub const fn grow_out (self) -> Self { - let token = self.grow_exp(); - if let Value::Exp(depth, source) = token.value { - if depth > 0 { - token.with_value(Value::Exp(depth - 1, source)) - } else { - return self.error(Unexpected(')')) - } - } else { - unreachable!() - } - } -} diff --git a/dsl/src/dsl_provide.rs b/dsl/src/dsl_provide.rs index f98130b..4a4e3bd 100644 --- a/dsl/src/dsl_provide.rs +++ b/dsl/src/dsl_provide.rs @@ -1,12 +1,49 @@ 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, + token: &mut TokenIter<'source>, + error: impl Into> + ) -> Usually { + if let Some(value) = Dsl::::take_from(state, token)? { + Ok(value) + } else { + Result::Err(error.into()) + } + } +} + +impl> DslFrom for T {} + +pub trait DslFrom>: Sized { + 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) + } +} + /// 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<$T> for $S { - fn take <'state, 'source> ( - &'state $self, $iter: &mut ::tengri::dsl::TokenIter<'source>, + impl ::tengri::dsl::Dsl<$S> for $T { + fn take_from <'state, 'source: 'state> ( + state: &'state $S, + $iter: &mut ::tengri::dsl::TokenIter<'source>, ) -> ::tengri::Perhaps<$T> { $expr } @@ -14,43 +51,24 @@ use crate::*; } } -/// Maps a sequencer of EDN tokens to parameters of supported types -/// for a given context. -pub trait Dsl: Sized { - fn take <'state, 'source> (&'state self, _: &mut TokenIter<'source>) -> Perhaps { - unimplemented!() - } - fn take_or_fail <'state, 'source> ( - &'state self, - token: &mut TokenIter<'source>, - error: impl Into> - ) -> Usually { - if let Some(value) = Dsl::::take(self, token)? { - Ok(value) - } else { - Result::Err(error.into()) - } - } -} - -pub trait FromDsl<'state, State>: Sized { - fn take_from <'source: 'state> (state: &'state State, _token: &mut TokenIter<'source>) - -> Perhaps - { - unimplemented!() - } - fn take_from_or_fail <'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()) - } - } -} +///// Maps a sequencer of EDN tokens to parameters of supported types +///// for a given context. +//pub trait Dsl: Sized { + //fn take <'state, 'source> (&'state self, _: &mut TokenIter<'source>) -> Perhaps { + //unimplemented!() + //} + //fn take_or_fail <'state, 'source> ( + //&'state self, + //token: &mut TokenIter<'source>, + //error: impl Into> + //) -> Usually { + //if let Some(value) = Dsl::::take(self, token)? { + //Ok(value) + //} else { + //Result::Err(error.into()) + //} + //} +//} //impl, U> Dsl for &T { //fn take <'state, 'source> (&'state self, iter: &mut TokenIter<'source>) -> Perhaps { @@ -64,8 +82,8 @@ pub trait FromDsl<'state, State>: Sized { //} //} -impl<'state, X, Y> Dsl for Y where Y: FromDsl<'state, X> { -} - -//impl> Dsl for T { +//impl<'state, X, Y> Dsl for Y where Y: Dsl<'state, X> { +//} + +//impl> Dsl for T { //} diff --git a/dsl/src/dsl_token.rs b/dsl/src/dsl_token.rs new file mode 100644 index 0000000..d45203b --- /dev/null +++ b/dsl/src/dsl_token.rs @@ -0,0 +1,110 @@ +use crate::*; + +#[derive(Debug, Copy, Clone, Default, PartialEq)] pub struct Token<'source> { + pub source: &'source str, + pub start: usize, + pub length: usize, + pub value: Value<'source>, +} + +#[derive(Debug, Copy, Clone, Default, PartialEq)] pub enum Value<'source> { + #[default] Nil, + Err(DslError), + Num(usize), + Sym(&'source str), + Key(&'source str), + Str(&'source str), + Exp(usize, TokenIter<'source>), +} + +impl<'source> std::fmt::Display for Value<'source> { + fn fmt (&self, out: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + write!(out, "{}", match self { + Nil => String::new(), + Err(e) => format!("[error: {e}]"), + Num(n) => format!("{n}"), + Sym(s) => format!("{s}"), + Key(s) => format!("{s}"), + Str(s) => format!("{s}"), + Exp(_, e) => format!("{e:?}"), + }) + } +} + +impl<'source> Token<'source> { + pub const fn new ( + source: &'source str, start: usize, length: usize, value: Value<'source> + ) -> Self { + Self { source, start, length, value } + } + pub const fn end (&self) -> usize { + self.start.saturating_add(self.length) + } + pub const fn slice (&'source self) -> &'source str { + self.slice_source(self.source) + } + pub const fn slice_source <'range> (&'source self, source: &'range str) -> &'range str { + str_range(source, self.start, self.end()) + } + pub const fn slice_source_exp <'range> (&'source self, source: &'range str) -> &'range str { + str_range(source, self.start.saturating_add(1), self.end()) + } + pub const fn with_value (self, value: Value<'source>) -> Self { + Self { value, ..self } + } + pub const fn value (&self) -> Value { + self.value + } + pub const fn error (self, error: DslError) -> Self { + Self { value: Value::Err(error), ..self } + } + pub const fn grow (self) -> Self { + Self { length: self.length.saturating_add(1), ..self } + } + pub const fn grow_num (self, m: usize, c: char) -> Self { + match to_digit(c) { + Ok(n) => Self { value: Num(10*m+n), ..self.grow() }, + Result::Err(e) => Self { value: Err(e), ..self.grow() }, + } + } + pub const fn grow_key (self) -> Self { + let token = self.grow(); + token.with_value(Key(token.slice_source(self.source))) + } + pub const fn grow_sym (self) -> Self { + let token = self.grow(); + token.with_value(Sym(token.slice_source(self.source))) + } + pub const fn grow_str (self) -> Self { + let token = self.grow(); + token.with_value(Str(token.slice_source(self.source))) + } + pub const fn grow_exp (self) -> Self { + let token = self.grow(); + if let Exp(depth, _) = token.value { + token.with_value(Exp(depth, TokenIter::new(token.slice_source_exp(self.source)))) + } else { + unreachable!() + } + } + pub const fn grow_in (self) -> Self { + let token = self.grow_exp(); + if let Value::Exp(depth, source) = token.value { + token.with_value(Value::Exp(depth.saturating_add(1), source)) + } else { + unreachable!() + } + } + pub const fn grow_out (self) -> Self { + let token = self.grow_exp(); + if let Value::Exp(depth, source) = token.value { + if depth > 0 { + token.with_value(Value::Exp(depth - 1, source)) + } else { + return self.error(Unexpected(')')) + } + } else { + unreachable!() + } + } +} diff --git a/dsl/src/lib.rs b/dsl/src/lib.rs index 9c9b44e..712eced 100644 --- a/dsl/src/lib.rs +++ b/dsl/src/lib.rs @@ -46,6 +46,7 @@ pub(crate) use self::Value::*; pub(crate) use self::DslError::*; mod dsl_error; pub use self::dsl_error::*; +mod dsl_token; pub use self::dsl_token::*; mod dsl_parse; pub use self::dsl_parse::*; mod dsl_provide; pub use self::dsl_provide::*; diff --git a/input/src/input_dsl.rs b/input/src/input_dsl.rs index dfcbd72..67b51ae 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, C: Command, I: DslInput> { +pub trait KeyMap + 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: Dsl, C: Command, I: DslInput> KeyMap for SourceIter<'source> { +impl<'source, S, C: Dsl + 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: Dsl, C: Command, I: DslInput> KeyMap for SourceI match exp_iter.next() { Some(Token { value: Value::Sym(binding), .. }) => { if input.matches_dsl(binding) { - if let Some(command) = Dsl::::take(state, &mut exp_iter)? { + if let Some(command) = Dsl::take_from(state, &mut exp_iter)? { return Ok(Some(command)) } } @@ -38,7 +38,7 @@ impl<'source, S: Dsl, C: Command, I: DslInput> KeyMap for SourceI } /// A [TokenIter] can be a [KeyMap]. -impl<'source, S: Dsl, C: Command, I: DslInput> KeyMap for TokenIter<'source> { +impl<'source, S, C: Dsl + 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: Dsl, C: Command, I: DslInput> KeyMap for TokenIt match e.next() { Some(Token { value: Value::Sym(binding), .. }) => { if input.matches_dsl(binding) { - if let Some(command) = Dsl::::take(state, &mut e)? { + if let Some(command) = C::take_from(state, &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 S: Dsl, C: Command, I: DslInput, M: KeyMap + Send + Sync { +where C: Dsl + Command, I: DslInput, M: KeyMap + Send + Sync { __: PhantomData<(S, C, I)>, pub layers: Vec<(InputLayerCond, M)>, } impl Default for InputMap -where S: Dsl, C: Command, I: DslInput, M: KeyMap + Send + Sync { +where C: Dsl + Command, I: DslInput, M: KeyMap + Send + Sync { fn default () -> Self { Self { __: PhantomData, layers: vec![] } } } -impl InputMap -where S: Dsl + 'static, C: Command, I: DslInput, M: KeyMap + Send + Sync { +impl InputMap +where C: Dsl + Command, I: DslInput, M: KeyMap + Send + Sync { pub fn new (keymap: M) -> Self { Self::default().layer(keymap) } @@ -104,7 +104,7 @@ where S: Dsl + 'static, C: Command, I: DslInput, M: KeyMap + Send } impl std::fmt::Debug for InputMap -where S: Dsl, C: Command, I: DslInput, M: KeyMap + Send + Sync { +where C: Dsl + 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 S: Dsl, C: Command, I: DslInput, M: KeyMap + Send + Sync { /// An [InputMap] can be a [KeyMap]. impl KeyMap for InputMap -where S: Dsl, C: Command, I: DslInput, M: KeyMap + Send + Sync { +where C: Dsl + 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 a35659b..7a9377f 100644 --- a/output/src/ops/align.rs +++ b/output/src/ops/align.rs @@ -37,7 +37,7 @@ pub struct Align(Alignment, A); #[cfg(feature = "dsl")] impl<'state, E: Output + 'state, T: ViewContext<'state, E>> -FromDsl<'state, T> for Align> { +Dsl for Align> { fn take_from <'source: 'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Perhaps { if let Some(Token { value: Value::Key(key), .. }) = iter.peek() { match key { diff --git a/output/src/ops/bsp.rs b/output/src/ops/bsp.rs index 2819bbf..895916c 100644 --- a/output/src/ops/bsp.rs +++ b/output/src/ops/bsp.rs @@ -22,7 +22,7 @@ impl, B: Content> Content for Bsp { } #[cfg(feature = "dsl")] impl<'state, E: Output + 'state, T: ViewContext<'state, E>> -FromDsl<'state, T> for Bsp, RenderBox<'state, E>> { +Dsl for Bsp, RenderBox<'state, E>> { fn take_from <'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"), diff --git a/output/src/ops/cond.rs b/output/src/ops/cond.rs index cfdf2fd..8d8a27e 100644 --- a/output/src/ops/cond.rs +++ b/output/src/ops/cond.rs @@ -20,7 +20,7 @@ impl Either { #[cfg(feature = "dsl")] impl<'state, E: Output + 'state, T: ViewContext<'state, E>> -FromDsl<'state, T> for When> { +Dsl for When> { fn take_from <'source: 'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Perhaps { Ok(if let Some(Token { value: Value::Key("when"), @@ -39,7 +39,7 @@ FromDsl<'state, T> for When> { #[cfg(feature = "dsl")] impl<'state, E: Output + 'state, T: ViewContext<'state, E>> -FromDsl<'state, T> for Either, RenderBox<'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(); diff --git a/output/src/ops/stack.rs b/output/src/ops/stack.rs index 816713c..6498ab0 100644 --- a/output/src/ops/stack.rs +++ b/output/src/ops/stack.rs @@ -1,4 +1,5 @@ use crate::*; +use Direction::*; pub struct Stack { __: PhantomData, @@ -10,68 +11,76 @@ impl Stack { Self { direction, callback, __: Default::default(), } } pub fn north (callback: F) -> Self { - Self::new(Direction::North, callback) + Self::new(North, callback) } pub fn south (callback: F) -> Self { - Self::new(Direction::South, callback) + Self::new(South, callback) } pub fn east (callback: F) -> Self { - Self::new(Direction::East, callback) + Self::new(East, callback) } pub fn west (callback: F) -> Self { - Self::new(Direction::West, callback) + Self::new(West, callback) } } impl)->())->()> Content for Stack { fn layout (&self, mut to: E::Area) -> E::Area { let mut x = to.x(); let mut y = to.y(); - let mut w = to.w(); - let mut h = to.h(); + let (mut w_used, mut w_remaining) = (E::Unit::zero(), to.w()); + let (mut h_used, mut h_remaining) = (E::Unit::zero(), to.h()); (self.callback)(&mut move |component: &dyn Render|{ - let layout = component.layout([x, y, w, h].into()); + let [_, _, w, h] = component.layout([x, y, w_remaining, h_remaining].into()).xywh(); match self.direction { - Direction::North => { - todo!() + South => { + y = y.plus(h); + h_used = h_used.plus(h); + h_remaining = h_remaining.minus(h); + w_used = w_used.max(w); }, - Direction::South => { - y = y + layout.h(); - h = h.minus(layout.h()); + East => { + x = x.plus(w); + w_used = w_used.plus(w); + w_remaining = w_remaining.minus(w); + h_used = h_used.max(h); }, - Direction::East => { - x = x + layout.w(); - w = w.minus(layout.w()); - }, - Direction::West => { + North | West => { todo!() }, _ => unreachable!(), } }); - to + match self.direction { + North | West => { + todo!() + }, + South | East => { + [to.x(), to.y(), w_used.into(), h_used.into()].into() + }, + _ => unreachable!(), + } } fn render (&self, to: &mut E) { let mut x = to.x(); let mut y = to.y(); - let mut w = to.w(); - let mut h = to.h(); + let (mut w_used, mut w_remaining) = (E::Unit::zero(), to.w()); + let (mut h_used, mut h_remaining) = (E::Unit::zero(), to.h()); (self.callback)(&mut move |component: &dyn Render|{ - let layout = component.layout([x, y, w, h].into()); + let layout = component.layout([x, y, w_remaining, h_remaining].into()); match self.direction { - Direction::North => { - todo!() - }, - Direction::South => { - y = y + layout.h(); - h = h.minus(layout.h()); + South => { + y = y.plus(layout.h()); + h_remaining = h_remaining.minus(layout.h()); + h_used = h_used.plus(layout.h()); to.place(layout, component); }, - Direction::East => { - x = x + layout.w(); - w = w.minus(layout.w()); + East => { + x = x.plus(layout.w()); + w_remaining = w_remaining.minus(layout.w()); + w_used = w_used.plus(layout.h()); to.place(layout, component); }, - Direction::West => { + North | West => { todo!() }, _ => unreachable!() diff --git a/output/src/ops/transform.rs b/output/src/ops/transform.rs index 80d50ce..b94def2 100644 --- a/output/src/ops/transform.rs +++ b/output/src/ops/transform.rs @@ -40,7 +40,7 @@ macro_rules! transform_xy { } #[cfg(feature = "dsl")] impl<'state, E: Output + 'state, T: ViewContext<'state, E>> - FromDsl<'state, T> for $Enum> { + Dsl for $Enum> { fn take_from <'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(); @@ -85,7 +85,7 @@ macro_rules! transform_xy_unit { } #[cfg(feature = "dsl")] impl<'state, E: Output + 'state, T: ViewContext<'state, E>> - FromDsl<'state, T> for $Enum> { + Dsl for $Enum> { fn take_from <'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(); diff --git a/output/src/view.rs b/output/src/view.rs index 8f40cc2..460f1c5 100644 --- a/output/src/view.rs +++ b/output/src/view.rs @@ -3,7 +3,7 @@ use crate::*; #[cfg(feature = "dsl")] #[macro_export] macro_rules! try_delegate { ($s:ident, $dsl:expr, $T:ty) => { - let value: Option<$T> = FromDsl::take_from($s, $dsl)?; + let value: Option<$T> = Dsl::take_from($s, $dsl)?; if let Some(value) = value { return Ok(Some(value.boxed())) } @@ -12,10 +12,10 @@ use crate::*; // Provides components to the view. #[cfg(feature = "dsl")] -pub trait ViewContext<'state, E: Output + 'state>: Send + Sync - + Dsl - + Dsl - + 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> diff --git a/proc/src/proc_view.rs b/proc/src/proc_view.rs index 48af79f..6947766 100644 --- a/proc/src/proc_view.rs +++ b/proc/src/proc_view.rs @@ -64,12 +64,39 @@ impl ToTokens for ViewDef { } } /// Generated by [tengri_proc]. - impl<'state> ::tengri::dsl::FromDsl<'state, #view> for ::tengri::output::RenderBox<'state, #output> { + 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> ) -> Perhaps { - Ok(match token.peek() { #(#exposed)* _ => None }) + 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 { + 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>>); + None + }, + #(#exposed),* + _ => None + }) } } } { @@ -135,6 +162,5 @@ impl ToTokens for ViewArm { out.append(Group::new(Delimiter::Parenthesis, TokenStream2::new())); out })); - out.append(Punct::new(',', Alone)); } }