mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 11:46: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
|
/// Maps a sequencer of EDN tokens to parameters of supported types
|
||||||
/// for a given context.
|
/// for a given context.
|
||||||
pub trait Dsl<U>: Sized {
|
pub trait Dsl<Value>: Sized {
|
||||||
fn take <'state, 'source> (
|
fn take <'state, 'source> (&'state self, _: &mut TokenIter<'source>) -> Perhaps<Value> {
|
||||||
&'state self,
|
|
||||||
_: &mut TokenIter<'source>
|
|
||||||
) -> Perhaps<U> {
|
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn take_or_fail <'state, 'source> (
|
fn take_or_fail <'state, 'source> (
|
||||||
&'state self,
|
&'state self,
|
||||||
token: &mut TokenIter<'source>,
|
token: &mut TokenIter<'source>,
|
||||||
error: impl Into<Box<dyn std::error::Error>>
|
error: impl Into<Box<dyn std::error::Error>>
|
||||||
) -> Usually<U> {
|
) -> Usually<Value> {
|
||||||
if let Some(value) = Dsl::<U>::take(self, token)? {
|
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)
|
Ok(value)
|
||||||
} else {
|
} else {
|
||||||
Result::Err(error.into())
|
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 {
|
//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> {
|
pub fn format (&self) -> Arc<str> {
|
||||||
format!("{}x{}", self.w(), self.h()).into()
|
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)
|
Bsp::b(Fill::xy(self), item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,13 @@
|
||||||
use crate::*;
|
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")]
|
#[cfg(feature = "dsl")]
|
||||||
pub struct View<'a, T>(
|
#[macro_export] macro_rules! try_delegate {
|
||||||
pub &'a T,
|
($s:ident, $dsl:expr, $T:ty) => {
|
||||||
pub TokenIter<'a>
|
let value: Option<$T> = FromDsl::take_from($s, $dsl)?;
|
||||||
);
|
if let Some(value) = value {
|
||||||
|
return Ok(Some(value.boxed()))
|
||||||
#[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?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provides components to the view.
|
// Provides components to the view.
|
||||||
|
|
@ -96,13 +61,3 @@ pub trait ViewContext<'state, E: Output + 'state>: Send + Sync
|
||||||
Ok(None)
|
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 {
|
impl ToTokens for ViewDef {
|
||||||
fn to_tokens (&self, out: &mut TokenStream2) {
|
fn to_tokens (&self, out: &mut TokenStream2) {
|
||||||
let Self(ViewMeta { output }, ViewImpl { block, exposed }) = self;
|
let Self(ViewMeta { output }, ViewImpl { block, exposed }) = self;
|
||||||
let ident = &block.self_ty;
|
let view = &block.self_ty;
|
||||||
let mut available = vec![];
|
let mut available = vec![];
|
||||||
let exposed: Vec<_> = exposed.iter().map(|(k,v)|{
|
let exposed: Vec<_> = exposed.iter().map(|(k,v)|{
|
||||||
available.push(k.clone());
|
available.push(k.clone());
|
||||||
|
|
@ -52,24 +52,24 @@ impl ToTokens for ViewDef {
|
||||||
}).collect();
|
}).collect();
|
||||||
let available: String = available.join(", ");
|
let available: String = available.join(", ");
|
||||||
let error_msg = LitStr::new(
|
let error_msg = LitStr::new(
|
||||||
&format!("expected Sym(content), got: {{iter:?}}, available: {available}"),
|
&format!("expected Sym(content), got: {{token:?}}, available: {available}"),
|
||||||
Span::call_site()
|
Span::call_site()
|
||||||
);
|
);
|
||||||
for token in quote! {
|
for token in quote! {
|
||||||
#block
|
#block
|
||||||
/// Generated by [tengri_proc].
|
/// Generated by [tengri_proc].
|
||||||
impl ::tengri::output::Content<#output> for #ident {
|
impl ::tengri::output::Content<#output> for #view {
|
||||||
fn content (&self) -> impl Render<#output> {
|
fn content (&self) -> impl Render<#output> {
|
||||||
// TODO move to self.view()
|
self.view()
|
||||||
self.size.of(::tengri::output::View(self, self.config.view))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Generated by [tengri_proc].
|
/// Generated by [tengri_proc].
|
||||||
impl<'state> ::tengri::output::ViewContext<'state, #output> for #ident {
|
impl<'state> ::tengri::dsl::FromDsl<'state, #view> for ::tengri::output::RenderBox<'state, #output> {
|
||||||
fn get_content_sym <'source: 'state> (&'state self, iter: &mut TokenIter<'source>)
|
fn take_from <'source: 'state> (
|
||||||
-> ::tengri::Perhaps<RenderBox<'state, #output>>
|
state: &'state #view,
|
||||||
{
|
token: &mut ::tengri::dsl::TokenIter<'source>
|
||||||
Ok(match iter.peek() { #(#exposed)* _ => panic!(#error_msg) })
|
) -> 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(Ident::new("Some", Span::call_site()));
|
||||||
out.append(Group::new(Delimiter::Parenthesis, {
|
out.append(Group::new(Delimiter::Parenthesis, {
|
||||||
let mut out = TokenStream2::new();
|
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(Punct::new('.', Alone));
|
||||||
out.append(value.clone());
|
out.append(value.clone());
|
||||||
out.append(Group::new(Delimiter::Parenthesis, TokenStream2::new()));
|
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_border; pub use self::tui_border::*;
|
||||||
mod tui_button; pub use self::tui_button::*;
|
mod tui_button; pub use self::tui_button::*;
|
||||||
mod tui_color; pub use self::tui_color::*;
|
mod tui_color; pub use self::tui_color::*;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue