mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 03:36:42 +01:00
This commit is contained in:
parent
90f5699fff
commit
f08593f0f8
5 changed files with 64 additions and 89 deletions
|
|
@ -16,19 +16,35 @@ use crate::*;
|
|||
|
||||
/// Maps a sequencer of EDN tokens to parameters of supported types
|
||||
/// for a given context.
|
||||
pub trait Dsl<U>: Sized {
|
||||
fn take <'state, 'source> (
|
||||
&'state self,
|
||||
_: &mut TokenIter<'source>
|
||||
) -> Perhaps<U> {
|
||||
pub trait Dsl<Value>: Sized {
|
||||
fn take <'state, 'source> (&'state self, _: &mut TokenIter<'source>) -> Perhaps<Value> {
|
||||
unimplemented!()
|
||||
}
|
||||
fn take_or_fail <'state, 'source> (
|
||||
&'state self,
|
||||
token: &mut TokenIter<'source>,
|
||||
error: impl Into<Box<dyn std::error::Error>>
|
||||
) -> Usually<U> {
|
||||
if let Some(value) = Dsl::<U>::take(self, token)? {
|
||||
) -> Usually<Value> {
|
||||
if let Some(value) = Dsl::<Value>::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<Self>
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
fn take_from_or_fail <'source: 'state> (
|
||||
state: &'state State,
|
||||
token: &mut TokenIter<'source>,
|
||||
error: impl Into<Box<dyn std::error::Error>>
|
||||
) -> Usually<Self> {
|
||||
if let Some(value) = FromDsl::<State>::take_from(state, token)? {
|
||||
Ok(value)
|
||||
} else {
|
||||
Result::Err(error.into())
|
||||
|
|
@ -53,23 +69,3 @@ impl<'state, X, Y> Dsl<X> for Y where Y: FromDsl<'state, X> {
|
|||
|
||||
//impl<T, U: FromDsl<T>> Dsl<U> for T {
|
||||
//}
|
||||
|
||||
pub trait FromDsl<'state, T>: Sized {
|
||||
fn take_from <'source: 'state> (
|
||||
state: &'state T,
|
||||
_token: &mut TokenIter<'source>
|
||||
) -> Perhaps<Self> {
|
||||
unimplemented!()
|
||||
}
|
||||
fn take_from_or_fail <'source: 'state> (
|
||||
state: &'state T,
|
||||
token: &mut TokenIter<'source>,
|
||||
error: impl Into<Box<dyn std::error::Error>>
|
||||
) -> Usually<Self> {
|
||||
if let Some(value) = FromDsl::<T>::take_from(state, token)? {
|
||||
Ok(value)
|
||||
} else {
|
||||
Result::Err(error.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ impl<E: Output> Measure<E> {
|
|||
pub fn format (&self) -> Arc<str> {
|
||||
format!("{}x{}", self.w(), self.h()).into()
|
||||
}
|
||||
pub fn of <T: Content<E>> (&self, item: T) -> Bsp<Fill<&Self>, T> {
|
||||
pub fn of <T: Render<E>> (&self, item: T) -> Bsp<Fill<&Self>, T> {
|
||||
Bsp::b(Fill::xy(self), item)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,12 @@
|
|||
use crate::*;
|
||||
|
||||
#[macro_export] macro_rules! view {
|
||||
($Output:ty: |$self:ident: $State:ty| $expr:expr; {
|
||||
$($sym:literal => $body:expr),* $(,)?
|
||||
}) => {
|
||||
impl Content<$Output> for $State {
|
||||
fn content (&$self) -> impl Render<$Output> { $expr }
|
||||
}
|
||||
impl<'a> ViewContext<'a, $Output> for $State {
|
||||
fn get_content_sym (&'a $self, iter: &Value<'a>) -> Perhaps<RenderBox<'a, $Output>> {
|
||||
Ok(if let Value::Sym(s) = value {
|
||||
match *s {
|
||||
$($sym => Some($body.boxed()),)*
|
||||
_ => None
|
||||
}
|
||||
} else {
|
||||
return Err(format!("expected content, got: {iter:?}").into())
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// An ephemeral wrapper around view state and view description,
|
||||
// that is meant to be constructed and returned from [Content::content].
|
||||
#[cfg(feature = "dsl")]
|
||||
pub struct View<'a, T>(
|
||||
pub &'a T,
|
||||
pub TokenIter<'a>
|
||||
);
|
||||
|
||||
#[cfg(feature = "dsl")]
|
||||
impl<'a, O: Output + 'a, T: ViewContext<'a, O>> Content<O> for View<'a, T> {
|
||||
fn content (&self) -> impl Render<O> {
|
||||
let mut iter = self.1.clone();
|
||||
while let Some(Token { value, .. }) = iter.peek() {
|
||||
if let Ok(Some(content)) = self.0.get_content(&mut iter) {
|
||||
return Some(content)
|
||||
// TODO handle errors here, how?
|
||||
// error receiver trait in viewcontext?
|
||||
}
|
||||
#[macro_export] macro_rules! try_delegate {
|
||||
($s:ident, $dsl:expr, $T:ty) => {
|
||||
let value: Option<$T> = FromDsl::take_from($s, $dsl)?;
|
||||
if let Some(value) = value {
|
||||
return Ok(Some(value.boxed()))
|
||||
}
|
||||
return None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,13 +61,3 @@ pub trait ViewContext<'state, E: Output + 'state>: Send + Sync
|
|||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dsl")]
|
||||
#[macro_export] macro_rules! try_delegate {
|
||||
($s:ident, $dsl:expr, $T:ty) => {
|
||||
let value: Option<$T> = FromDsl::take_from($s, $dsl)?;
|
||||
if let Some(value) = value {
|
||||
return Ok(Some(value.boxed()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ impl Parse for ViewImpl {
|
|||
impl ToTokens for ViewDef {
|
||||
fn to_tokens (&self, out: &mut TokenStream2) {
|
||||
let Self(ViewMeta { output }, ViewImpl { block, exposed }) = self;
|
||||
let ident = &block.self_ty;
|
||||
let view = &block.self_ty;
|
||||
let mut available = vec![];
|
||||
let exposed: Vec<_> = exposed.iter().map(|(k,v)|{
|
||||
available.push(k.clone());
|
||||
|
|
@ -52,24 +52,24 @@ impl ToTokens for ViewDef {
|
|||
}).collect();
|
||||
let available: String = available.join(", ");
|
||||
let error_msg = LitStr::new(
|
||||
&format!("expected Sym(content), got: {{iter:?}}, available: {available}"),
|
||||
&format!("expected Sym(content), got: {{token:?}}, available: {available}"),
|
||||
Span::call_site()
|
||||
);
|
||||
for token in quote! {
|
||||
#block
|
||||
/// Generated by [tengri_proc].
|
||||
impl ::tengri::output::Content<#output> for #ident {
|
||||
impl ::tengri::output::Content<#output> for #view {
|
||||
fn content (&self) -> impl Render<#output> {
|
||||
// TODO move to self.view()
|
||||
self.size.of(::tengri::output::View(self, self.config.view))
|
||||
self.view()
|
||||
}
|
||||
}
|
||||
/// Generated by [tengri_proc].
|
||||
impl<'state> ::tengri::output::ViewContext<'state, #output> for #ident {
|
||||
fn get_content_sym <'source: 'state> (&'state self, iter: &mut TokenIter<'source>)
|
||||
-> ::tengri::Perhaps<RenderBox<'state, #output>>
|
||||
{
|
||||
Ok(match iter.peek() { #(#exposed)* _ => panic!(#error_msg) })
|
||||
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<Self> {
|
||||
Ok(match token.peek() { #(#exposed)* _ => None })
|
||||
}
|
||||
}
|
||||
} {
|
||||
|
|
@ -126,7 +126,7 @@ impl ToTokens for ViewArm {
|
|||
out.append(Ident::new("Some", Span::call_site()));
|
||||
out.append(Group::new(Delimiter::Parenthesis, {
|
||||
let mut out = TokenStream2::new();
|
||||
out.append(Ident::new("self", Span::call_site()));
|
||||
out.append(Ident::new("state", Span::call_site()));
|
||||
out.append(Punct::new('.', Alone));
|
||||
out.append(value.clone());
|
||||
out.append(Group::new(Delimiter::Parenthesis, TokenStream2::new()));
|
||||
|
|
|
|||
|
|
@ -21,6 +21,30 @@ impl<T: Content<TuiOut>> Content<TuiOut> for std::sync::Arc<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Content<TuiOut>> Content<TuiOut> for Result<T, Box<dyn std::error::Error>> {
|
||||
fn content (&self) -> impl Render<TuiOut> {
|
||||
Bsp::a(self.as_ref().ok(), self.as_ref().err()
|
||||
.map(|e|Tui::fg_bg(Color::Rgb(255,255,255), Color::Rgb(32,32,32), e.to_string())))
|
||||
}
|
||||
}
|
||||
|
||||
//impl<T: Render<TuiOut>> Render<TuiOut> for Result<T, Box<dyn std::error::Error>> {
|
||||
//fn layout (&self, to: [u16;4]) -> [u16;4] {
|
||||
//match self {
|
||||
//Ok(content) => content.layout(to),
|
||||
//Err(e) => [0, 0, to.w(), to.h()]
|
||||
//}
|
||||
//}
|
||||
//fn render (&self, to: &mut TuiOut) {
|
||||
//match self {
|
||||
//Ok(content) => content.render(to),
|
||||
//Err(e) => to.blit(&e.to_string(), 0, 0, Some(Style::default()
|
||||
//.bg(Color::Rgb(32,32,32))
|
||||
//.fg(Color::Rgb(255,255,255))))
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
|
||||
mod tui_border; pub use self::tui_border::*;
|
||||
mod tui_button; pub use self::tui_button::*;
|
||||
mod tui_color; pub use self::tui_color::*;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue