diff --git a/Justfile b/Justfile index e17aef3..3dbff77 100644 --- a/Justfile +++ b/Justfile @@ -1,17 +1,29 @@ -covfig := "CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' RUSTDOCFLAGS='-Cinstrument-coverage' LLVM_PROFILE_FILE='cov/cargo-test-%p-%m.profraw'" +export LLVM_PROFILE_FILE := "cov/cargo-test-%p-%m.profraw" grcov-binary := "--binary-path ./target/coverage/deps/" grcov-ignore := "--ignore-not-existing --ignore '../*' --ignore \"/*\" --ignore 'target/*'" + bacon: - {{covfig}} bacon -s + bacon -s + cov: - {{covfig}} time cargo test -j4 --workspace --profile coverage + CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' \ + time cargo test -j4 --workspace --profile coverage rm -rf target/coverage/html || true - {{covfig}} time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t html -o target/coverage/html + time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t html -o target/coverage/html + cov-md: - {{covfig}} time cargo test -j4 --workspace --profile coverage - {{covfig}} time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t markdown | sort + CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' \ + time cargo test -j4 --workspace --profile coverage + time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t markdown | sort + cov-md-ci: - {{covfig}} time cargo test -j4 --workspace --profile coverage -- --skip test_tui_engine - {{covfig}} time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t markdown | sort + CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' \ + time cargo test -j4 --workspace --profile coverage -- --skip test_tui_engine + time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t markdown | sort + doc: - cargo doc + CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' RUSTDOCFLAGS='-Cinstrument-coverage' \ + cargo doc + +example-tui: + cargo run -p tengri_tui --example tui diff --git a/core/src/lib.rs b/core/src/lib.rs index 0c63c05..3a51258 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,13 +1,18 @@ mod core_macros; pub(crate) use std::error::Error; + /// Standard result type. pub type Usually = Result>; + /// Standard optional result type. pub type Perhaps = Result, Box>; + /// Type-dispatched `get` and `get_mut`. pub trait Has: Send + Sync { fn get (&self) -> &T; fn get_mut (&mut self) -> &mut T; } + /// Type-dispatched `get` and `get_mut` that return an [Option]-wrapped result. pub trait MaybeHas: Send + Sync { fn get (&self) -> Option<&T>; fn get_mut (&mut self) -> Option<&mut T>; } + /// May compute a `RetVal` from `Args`. pub trait Eval { /// A custom operation on [Args] that may return [Result::Err] or [Option::None]. @@ -22,3 +27,11 @@ pub trait Eval { } } } + +#[macro_export] macro_rules! as_ref { + ($T:ty: |$self:ident : $S:ty| $x:expr) => { + impl AsRef<$T> for $S { + fn as_ref (&$self) -> &$T { &$x } + } + }; +} diff --git a/dsl/src/dsl_expr.rs b/dsl/src/dsl_expr.rs index 4179f94..92b093e 100644 --- a/dsl/src/dsl_expr.rs +++ b/dsl/src/dsl_expr.rs @@ -63,7 +63,7 @@ dsl_type!(DslExpr { ).into()) }; )* - Ok(Some($body as $Type)) + Ok(Some($body/* as $Type*/)) }; ($name, get) }),* )? ]; @@ -74,12 +74,14 @@ pub trait DslNsExprs<'a, T: 'a>: 'a { const EXPRS: DslExprs<'a, Self, T> = &[]; /// Resolve an expression if known. fn from_expr (&'a self, dsl: impl DslExpr + 'a) -> Perhaps { - let head = dsl.head()?; - for (key, get) in Self::EXPRS.iter() { - if Some(*key) == head { - return get(self, dsl.tail()?.unwrap_or("")) + if let Some(dsl) = dsl.expr()? { + let head = dsl.head()?; + for (key, get) in Self::EXPRS.iter() { + if Some(*key) == head { + return get(self, dsl.tail()?.unwrap_or("")) + } } } - return Ok(None) + Ok(None) } } diff --git a/dsl/src/dsl_ns.rs b/dsl/src/dsl_ns.rs index f17c283..c8b701f 100644 --- a/dsl/src/dsl_ns.rs +++ b/dsl/src/dsl_ns.rs @@ -16,3 +16,31 @@ pub trait DslNs<'a, T: 'a>: DslNsWords<'a, T> + DslNsExprs<'a, T> { Ok(None) } } + +#[macro_export] macro_rules! dsl_ns { + ($State:ty: $Type:ty { + $(literal = |$dsl:ident| $literal:expr;)? + $(word = |$state_w:ident| { + $($word:literal => $body_w:expr),* $(,)? + };)? + $(expr = |$state_e:ident| { + $($head:literal $args:tt => $body_e:expr),* $(,)? + };)? + }) => { + impl<'a> DslNs<'a, $Type> for $State { + $(fn from_literal (&self, $dsl: impl Dsl) -> Perhaps<$Type> { + $literal + })? + } + impl<'a> DslNsWords<'a, $Type> for $State { + $(dsl_words! { 'a |$state_w| -> $Type { + $($word => $body_w),* + } })? + } + impl<'a> DslNsExprs<'a, $Type> for $State { + $(dsl_exprs! { 'a |$state_e| -> $Type { + $($head $args => $body_e),* + } })? + } + } +} diff --git a/output/src/draw.rs b/output/src/draw.rs index 02b82bb..f78574d 100644 --- a/output/src/draw.rs +++ b/output/src/draw.rs @@ -4,37 +4,6 @@ use crate::*; pub trait Draw { /// Write data to display. fn draw (&self, to: &mut O); - - fn boxed <'a> (self) -> Box + 'a> where Self: Sized + 'a { - Box::new(self) as Box + 'a> - } - fn rc <'a> (self) -> Rc + 'a> where Self: Sized + 'a { - Rc::new(self) as Rc + 'a> - } -} - -impl Draw for () { - fn draw (&self, _: &mut O) {} -} - -impl> Draw for &T { - fn draw (&self, to: &mut O) { - (*self).draw(to) - } -} - -impl> Draw for &mut T { - fn draw (&self, to: &mut O) { - (**self).draw(to) - } -} - -impl> Draw for [T] { - fn draw (&self, to: &mut O) { - for draw in self.iter() { - draw.draw(to) - } - } } impl Draw for fn(&mut O) { @@ -43,6 +12,12 @@ impl Draw for fn(&mut O) { } } +impl Draw for () { fn draw (&self, _: &mut O) {} } + +impl> Draw for &T { + fn draw (&self, to: &mut O) { (*self).draw(to) } +} + impl<'x, O: Out> Draw for &(dyn Draw + 'x) { fn draw (&self, to: &mut O) { (*self).draw(to) @@ -55,6 +30,32 @@ impl<'x, O: Out> Draw for &mut (dyn Draw + 'x) { } } +impl> Draw for RwLock { + fn draw (&self, to: &mut O) { self.read().unwrap().draw(to) } +} + +impl> Draw for [T] { + fn draw (&self, to: &mut O) { + for draw in self.iter() { + draw.draw(to) + } + } +} + +//impl> Draw for &mut T { + //fn draw (&self, to: &mut O) { + //(**self).draw(to) + //} +//} + +//impl, U: Draw> Draw for &mut T { + //fn draw (&self, to: &mut O) { + //for draw in *self { + //draw.draw(to) + //} + //} +//} + /// Implement custom drawing for a struct. #[macro_export] macro_rules! draw { @@ -82,4 +83,12 @@ impl<'x, O: Out> Draw for &mut (dyn Draw + 'x) { draw!(|self: Arc>, to|(**self).draw(to)); draw!(|self: Box>, to|(**self).draw(to)); -draw!(|self: Option>, to|if let Some(draw) = self { draw.draw(to) }); +//draw!(|self: Option>, to|if let Some(draw) = self { draw.draw(to) }); + +impl> Draw for Option { + fn draw (&self, to: &mut O) { + if let Some(draw) = self { + draw.draw(to) + } + } +} diff --git a/output/src/group.rs b/output/src/group.rs new file mode 100644 index 0000000..4c949c7 --- /dev/null +++ b/output/src/group.rs @@ -0,0 +1,12 @@ +#[allow(unused)] use crate::*; + +pub struct Group(T); + +impl Group { + pub const fn new () -> Group<()> { + Group(()) + } + pub const fn add (self, value: U) -> Group<(T, U)> { + Group((self.0, value)) + } +} diff --git a/output/src/layout.rs b/output/src/layout.rs index 3f231d7..ec42644 100644 --- a/output/src/layout.rs +++ b/output/src/layout.rs @@ -32,7 +32,7 @@ pub trait Layout { } } -macro_rules! layout { +#[macro_export] macro_rules! layout { // Implement for all [Out] backends. (|$self:ident:$Struct:ident $(< $($L:lifetime),* $($T:ident $(:$Trait:path)?),* @@ -63,12 +63,24 @@ impl Layout for () {} impl> Layout for &L { /*FIXME*/ } +impl> Layout for RwLock { /*FIXME*/ } + +impl> Layout for Option { /*FIXME*/ } + +//impl Layout for fn(&mut O) {} + impl> Layout for Arc { fn layout (&self, to: O::Area) -> O::Area { (**self).layout(to) } } +impl<'x, O: Out> Layout for &(dyn Draw + 'x) { + fn layout (&self, to: O::Area) -> O::Area { + Fill::xy(self).layout(to) + } +} + mod layout_align; pub use self::layout_align::*; mod layout_bsp; pub use self::layout_bsp::*; mod layout_cond; pub use self::layout_cond::*; @@ -83,4 +95,4 @@ mod layout_padding; pub use self::layout_padding::*; mod layout_pull; pub use self::layout_pull::*; mod layout_push; pub use self::layout_push::*; mod layout_shrink; pub use self::layout_shrink::*; -mod layout_stack; pub use self::layout_stack::*; +mod layout_stack; //pub use self::layout_stack::*; diff --git a/output/src/layout/layout_align.rs b/output/src/layout/layout_align.rs index 9fbcd45..c8f0922 100644 --- a/output/src/layout/layout_align.rs +++ b/output/src/layout/layout_align.rs @@ -32,32 +32,32 @@ use crate::*; #[derive(Debug, Copy, Clone, Default)] pub enum Alignment { #[default] Center, X, Y, NW, N, NE, E, SE, S, SW, W } -pub struct Align(Alignment, A); +pub struct Align(Alignment, T); -impl Align { - #[inline] pub const fn c (a: A) -> Self { Self(Alignment::Center, a) } - #[inline] pub const fn x (a: A) -> Self { Self(Alignment::X, a) } - #[inline] pub const fn y (a: A) -> Self { Self(Alignment::Y, a) } - #[inline] pub const fn n (a: A) -> Self { Self(Alignment::N, a) } - #[inline] pub const fn s (a: A) -> Self { Self(Alignment::S, a) } - #[inline] pub const fn e (a: A) -> Self { Self(Alignment::E, a) } - #[inline] pub const fn w (a: A) -> Self { Self(Alignment::W, a) } - #[inline] pub const fn nw (a: A) -> Self { Self(Alignment::NW, a) } - #[inline] pub const fn sw (a: A) -> Self { Self(Alignment::SW, a) } - #[inline] pub const fn ne (a: A) -> Self { Self(Alignment::NE, a) } - #[inline] pub const fn se (a: A) -> Self { Self(Alignment::SE, a) } +impl Align { + #[inline] pub const fn c (a: T) -> Self { Self(Alignment::Center, a) } + #[inline] pub const fn x (a: T) -> Self { Self(Alignment::X, a) } + #[inline] pub const fn y (a: T) -> Self { Self(Alignment::Y, a) } + #[inline] pub const fn n (a: T) -> Self { Self(Alignment::N, a) } + #[inline] pub const fn s (a: T) -> Self { Self(Alignment::S, a) } + #[inline] pub const fn e (a: T) -> Self { Self(Alignment::E, a) } + #[inline] pub const fn w (a: T) -> Self { Self(Alignment::W, a) } + #[inline] pub const fn nw (a: T) -> Self { Self(Alignment::NW, a) } + #[inline] pub const fn sw (a: T) -> Self { Self(Alignment::SW, a) } + #[inline] pub const fn ne (a: T) -> Self { Self(Alignment::NE, a) } + #[inline] pub const fn se (a: T) -> Self { Self(Alignment::SE, a) } } -impl> Draw for Align { - fn draw (&self, to: &mut E) { - self.1.draw(to) - } -} -impl> Layout for Align { +impl> Layout for Align { fn layout (&self, on: E::Area) -> E::Area { self.0.align(on, &self.1) } } +impl + Layout> Draw for Align { + fn draw (&self, to: &mut E) { + to.place_at(self.layout(to.area()), &self.1) + } +} impl Alignment { fn align (&self, on: E::Area, content: &impl Layout) -> E::Area { diff --git a/output/src/layout/layout_bsp.rs b/output/src/layout/layout_bsp.rs index a1c367a..ff3e4aa 100644 --- a/output/src/layout/layout_bsp.rs +++ b/output/src/layout/layout_bsp.rs @@ -2,26 +2,29 @@ use crate::*; use Direction::*; /// A split or layer. -pub struct Bsp( +pub struct Bsp( pub(crate) Direction, - pub(crate) A, - pub(crate) B, + /// First element. + pub(crate) Head, + /// Second element. + pub(crate) Tail, ); -impl Bsp { - #[inline] pub const fn n (a: A, b: B) -> Self { Self(North, a, b) } - #[inline] pub const fn s (a: A, b: B) -> Self { Self(South, a, b) } - #[inline] pub const fn e (a: A, b: B) -> Self { Self(East, a, b) } - #[inline] pub const fn w (a: A, b: B) -> Self { Self(West, a, b) } - #[inline] pub const fn a (a: A, b: B) -> Self { Self(Above, a, b) } - #[inline] pub const fn b (a: A, b: B) -> Self { Self(Below, a, b) } + +impl Bsp { + #[inline] pub const fn n (a: Head, b: Tail) -> Self { Self(North, a, b) } + #[inline] pub const fn s (a: Head, b: Tail) -> Self { Self(South, a, b) } + #[inline] pub const fn e (a: Head, b: Tail) -> Self { Self(East, a, b) } + #[inline] pub const fn w (a: Head, b: Tail) -> Self { Self(West, a, b) } + #[inline] pub const fn a (a: Head, b: Tail) -> Self { Self(Above, a, b) } + #[inline] pub const fn b (a: Head, b: Tail) -> Self { Self(Below, a, b) } } -impl, B: Layout> Layout for Bsp { - fn layout (&self, area: E::Area) -> E::Area { - bsp_areas(area, self.0, &self.1, &self.2)[2] - } -} -impl + Layout, B: Draw + Layout> Draw for Bsp { - fn draw (&self, to: &mut E) { + +impl< + O: Out, + Head: Draw + Layout, + Tail: Draw + Layout +> Draw for Bsp { + fn draw (&self, to: &mut O) { let [a, b, _] = bsp_areas(to.area(), self.0, &self.1, &self.2); if self.0 == Below { to.place_at(a, &self.1); @@ -32,9 +35,16 @@ impl + Layout, B: Draw + Layout> Draw for Bsp ( - area: E::Area, direction: Direction, a: &impl Layout, b: &impl Layout, -) -> [E::Area;3] { + +impl, Tail: Layout> Layout for Bsp { + fn layout (&self, area: O::Area) -> O::Area { + bsp_areas(area, self.0, &self.1, &self.2)[2] + } +} + +fn bsp_areas ( + area: O::Area, direction: Direction, a: &impl Layout, b: &impl Layout, +) -> [O::Area;3] { let [x, y, w, h] = area.xywh(); let [aw, ah] = a.layout(area).wh(); let [bw, bh] = b.layout(match direction { diff --git a/output/src/layout/layout_cond.rs b/output/src/layout/layout_cond.rs index 20bc3d9..103166f 100644 --- a/output/src/layout/layout_cond.rs +++ b/output/src/layout/layout_cond.rs @@ -28,20 +28,22 @@ impl> Draw for When { } /// Show one item if a condition is true and another if the condition is false -pub struct Either(pub bool, pub A, pub B); -impl Either { +pub struct Either + Layout, B: Draw + Layout>(pub bool, pub A, pub B, pub PhantomData); +impl + Layout, B: Draw + Layout> Either { /// Create a ternary view condition. - pub const fn new (c: bool, a: A, b: B) -> Self { Self(c, a, b) } + pub const fn new (c: bool, a: A, b: B) -> Self { + Self(c, a, b, PhantomData) + } } -impl, B: Layout> Layout for Either { +impl + Layout, B: Draw + Layout> Layout for Either { fn layout (&self, to: E::Area) -> E::Area { - let Self(cond, a, b) = self; + let Self(cond, a, b, ..) = self; if *cond { a.layout(to) } else { b.layout(to) } } } -impl, B: Draw> Draw for Either { +impl + Layout, B: Draw + Layout> Draw for Either { fn draw (&self, to: &mut E) { - let Self(cond, a, b) = self; + let Self(cond, a, b, ..) = self; if *cond { a.draw(to) } else { b.draw(to) } } } diff --git a/output/src/layout/layout_fill.rs b/output/src/layout/layout_fill.rs index cea4076..6287714 100644 --- a/output/src/layout/layout_fill.rs +++ b/output/src/layout/layout_fill.rs @@ -1,8 +1,11 @@ use crate::*; pub enum Fill { + /// Use maximum width of area. X(A), + /// Use maximum height of area. Y(A), + /// Use maximum width and height of area. XY(A) } @@ -28,25 +31,25 @@ impl Fill { } } -impl + Layout> Layout for Fill { - fn min_w (&self, area: E::Area) -> E::Unit { - if self.has_x() { - area.w() - } else { - self.content().min_w(area) - } - } - fn min_h (&self, area: E::Area) -> E::Unit { - if self.has_y() { - area.h() - } else { - self.content().min_h(area) - } - } -} - -impl + Layout> Draw for Fill { - fn draw (&self, to: &mut E) { +impl> Draw for Fill { + fn draw (&self, to: &mut O) { to.place_at(self.layout(to.area()), &self.content()) } } + +impl> Layout for Fill { + fn min_w (&self, area: O::Area) -> O::Unit { + if self.has_x() { + area.w() + } else { + 0.into() + } + } + fn min_h (&self, area: O::Area) -> O::Unit { + if self.has_y() { + area.h() + } else { + 0.into() + } + } +} diff --git a/output/src/layout/layout_fixed.rs b/output/src/layout/layout_fixed.rs index a6db193..1d6eb1d 100644 --- a/output/src/layout/layout_fixed.rs +++ b/output/src/layout/layout_fixed.rs @@ -29,25 +29,19 @@ impl Fixed { } } -impl + Layout> Draw for Fixed { - fn draw (&self, to: &mut E) { - to.place_at(self.layout(to.area()), &self.content()) +impl> Draw for Fixed { + fn draw (&self, to: &mut O) { + let area = Layout::::layout(&self, to.area()); + to.place_at(area, &self.content()) } } -impl> Layout for Fixed { - fn layout (&self, area: E::Area) -> E::Area { - let [x, y, w, h] = area.xywh(); - let [x, y, w, h] = self.content().layout(match self { - Self::X(fw, _) => [x, y, *fw, h], - Self::Y(fh, _) => [x, y, w, *fh], - Self::XY(fw, fh, _) => [x, y, *fw, *fh], - }.into()).xywh(); - let fixed_area = match self { - Self::X(fw, _) => [x, y, *fw, h], - Self::Y(fh, _) => [x, y, w, *fh], - Self::XY(fw, fh, _) => [x, y, *fw, *fh], - }; - fixed_area.into() +impl Layout for Fixed { + fn layout (&self, area: O::Area) -> O::Area { + [area.x(), area.y(), match self { + Fixed::X(w, _) | Fixed::XY(w, _, _) => *w, _ => area.w() + }, match self { + Fixed::Y(h, _) | Fixed::XY(_, h, _) => *h, _ => area.h() + }].into() } } diff --git a/output/src/layout/layout_map.rs b/output/src/layout/layout_map.rs index 7dbdaab..cb230e2 100644 --- a/output/src/layout/layout_map.rs +++ b/output/src/layout/layout_map.rs @@ -1,19 +1,19 @@ use crate::*; /// Draws items from an iterator. -pub struct Map +pub struct Map where I: Iterator + Send + Sync, F: Fn() -> I + Send + Sync, { - __: PhantomData<(E, B)>, + __: PhantomData<(O, B)>, /// Function that returns iterator over stacked components get_iter: F, /// Function that returns each stacked component get_item: G, } -impl<'a, E, A, B, I, F, G> Map where +impl<'a, O, A, B, I, F, G> Map where I: Iterator + Send + Sync + 'a, F: Fn() -> I + Send + Sync + 'a, { @@ -27,30 +27,30 @@ impl<'a, E, A, B, I, F, G> Map where } macro_rules! impl_map_direction (($name:ident, $axis:ident, $align:ident)=>{ - impl<'a, E, A, B, I, F> Map< - E, A, Push>>>, I, F, fn(A, usize)->B + impl<'a, O, A, B, I, F> Map< + O, A, Push>>>, I, F, fn(A, usize)->B > where - E: Out, - B: Draw, + O: Out, + B: Draw + Layout, I: Iterator + Send + Sync + 'a, F: Fn() -> I + Send + Sync + 'a { pub const fn $name ( - size: E::Unit, + size: O::Unit, get_iter: F, get_item: impl Fn(A, usize)->B + Send + Sync ) -> Map< - E, A, - Push>>, + O, A, + Push>>, I, F, - impl Fn(A, usize)->Push>> + Send + Sync + impl Fn(A, usize)->Push>> + Send + Sync > { Map { __: PhantomData, get_iter, get_item: move |item: A, index: usize|{ // FIXME: multiply - let mut push: E::Unit = E::Unit::from(0u16); + let mut push: O::Unit = O::Unit::from(0u16); for _ in 0..index { push = push + size; } @@ -66,14 +66,14 @@ impl_map_direction!(south, y, n); impl_map_direction!(west, x, e); impl_map_direction!(north, y, s); -impl<'a, E, A, B, I, F, G> Layout for Map where - E: Out, - B: Draw + Layout, +impl<'a, O, A, B, I, F, G> Layout for Map where + O: Out, + B: Draw + Layout, I: Iterator + Send + Sync + 'a, F: Fn() -> I + Send + Sync + 'a, G: Fn(A, usize)->B + Send + Sync { - fn layout (&self, area: E::Area) -> E::Area { + fn layout (&self, area: O::Area) -> O::Area { let Self { get_iter, get_item, .. } = self; let mut index = 0; let [mut min_x, mut min_y] = area.center(); @@ -92,14 +92,14 @@ impl<'a, E, A, B, I, F, G> Layout for Map where area.center_xy([w.into(), h.into()].into()).into() } } -impl<'a, E, A, B, I, F, G> Draw for Map where - E: Out, - B: Draw + Layout, +impl<'a, O, A, B, I, F, G> Draw for Map where + O: Out, + B: Draw + Layout, I: Iterator + Send + Sync + 'a, F: Fn() -> I + Send + Sync + 'a, G: Fn(A, usize)->B + Send + Sync { - fn draw (&self, to: &mut E) { + fn draw (&self, to: &mut O) { let Self { get_iter, get_item, .. } = self; let mut index = 0; let area = self.layout(to.area()); diff --git a/output/src/output.rs b/output/src/output.rs index f745960..29ff6b2 100644 --- a/output/src/output.rs +++ b/output/src/output.rs @@ -7,6 +7,7 @@ mod content; pub use self::content::*; mod draw; pub use self::draw::*; +mod group; pub use self::group::*; mod layout; pub use self::layout::*; mod space; pub use self::space::*; mod thunk; pub use self::thunk::*; @@ -14,11 +15,9 @@ mod widget; pub use self::widget::*; pub(crate) use self::Direction::*; pub(crate) use std::fmt::{Debug, Display}; pub(crate) use std::marker::PhantomData; -pub(crate) use std::ops::{Add, Sub, Mul, Div, Deref}; -pub(crate) use std::rc::Rc; +pub(crate) use std::ops::{Add, Sub, Mul, Div}; pub(crate) use std::sync::{Arc, RwLock, atomic::{AtomicUsize, Ordering::Relaxed}}; pub(crate) use tengri_core::*; -#[cfg(feature = "dsl")] pub(crate) use ::tengri_dsl::*; /// Draw target. pub trait Out: Send + Sync + Sized { diff --git a/output/src/thunk.rs b/output/src/thunk.rs index b3ceb91..da2d84e 100644 --- a/output/src/thunk.rs +++ b/output/src/thunk.rs @@ -1,39 +1,28 @@ use crate::*; -pub struct Group(T); - -impl Group { - pub const fn new () -> Group<()> { - Group(()) - } - pub const fn add (self, value: U) -> Group<(T, U)> { - Group((self.0, value)) - } -} - /// Lazily-evaluated [Draw]able. -pub struct Thunk, F: Fn()->T>( - PhantomData, - F -); -impl, F: Fn()->T> Thunk { +pub struct Lazy(PhantomData<(E, T)>, F); +impl + Layout, F: Fn()->T> Lazy { pub const fn new (thunk: F) -> Self { Self(PhantomData, thunk) } } -impl + Layout, F: Fn()->T> Content for Thunk { +impl + Layout, F: Fn()->T> Content for Lazy { fn content (&self) -> impl Draw + Layout + '_ { (self.1)() } } -pub struct ThunkDraw(PhantomData, F); -impl ThunkDraw { - pub fn new (render: F) -> Self { Self(PhantomData, render) } +pub struct Thunk(PhantomData, F); +impl Thunk { + pub const fn new (draw: F) -> Self { Self(PhantomData, draw) } } -impl Draw for ThunkDraw { +impl Draw for Thunk { fn draw (&self, to: &mut E) { (self.1)(to) } } +impl Layout for Thunk { + fn layout (&self, to: E::Area) -> E::Area { to } +} #[derive(Debug, Default)] pub struct Memo { pub value: T, @@ -47,10 +36,10 @@ impl Memo { pub fn update ( &mut self, newval: T, - render: impl Fn(&mut U, &T, &T)->R + draw: impl Fn(&mut U, &T, &T)->R ) -> Option { if newval != self.value { - let result = render(&mut*self.view.write().unwrap(), &newval, &self.value); + let result = draw(&mut*self.view.write().unwrap(), &newval, &self.value); self.value = newval; return Some(result); } diff --git a/proc/Cargo.toml b/proc/Cargo.toml index d7c3a9a..19fe50c 100644 --- a/proc/Cargo.toml +++ b/proc/Cargo.toml @@ -13,3 +13,6 @@ syn = { workspace = true } quote = { workspace = true } proc-macro2 = { workspace = true } heck = { workspace = true } + +[target.'cfg(target_os = "linux")'] +rustflags = ["-C", "link-arg=-fuse-ld=mold"] diff --git a/proc/src/proc_expose.rs b/proc/src/proc_expose.rs index cdef432..2756b28 100644 --- a/proc/src/proc_expose.rs +++ b/proc/src/proc_expose.rs @@ -9,8 +9,8 @@ pub(crate) struct ExposeMeta; #[derive(Debug, Clone)] pub(crate) struct ExposeImpl(ItemImpl, BTreeMap>); -#[derive(Debug, Clone)] -struct ExposeSym(LitStr); +//#[derive(Debug, Clone)] +//struct ExposeSym(LitStr); #[derive(Debug, Clone)] struct ExposeType(Box); @@ -169,33 +169,33 @@ impl ExposeImpl { } } -impl From for ExposeSym { fn from (this: LitStr) -> Self { Self(this) } } +//impl From for ExposeSym { fn from (this: LitStr) -> Self { Self(this) } } -impl PartialOrd for ExposeSym { - fn partial_cmp (&self, other: &Self) -> Option { - let this = &self.0; - let that = &other.0; - Some(format!("{}", quote! { #this }).cmp(&format!("{}", quote! { #that }))) - } -} +//impl PartialOrd for ExposeSym { + //fn partial_cmp (&self, other: &Self) -> Option { + //let this = &self.0; + //let that = &other.0; + //Some(format!("{}", quote! { #this }).cmp(&format!("{}", quote! { #that }))) + //} +//} -impl Ord for ExposeSym { - fn cmp (&self, other: &Self) -> Ordering { - let this = &self.0; - let that = &other.0; - format!("{}", quote! { #this }).cmp(&format!("{}", quote! { #that })) - } -} +//impl Ord for ExposeSym { + //fn cmp (&self, other: &Self) -> Ordering { + //let this = &self.0; + //let that = &other.0; + //format!("{}", quote! { #this }).cmp(&format!("{}", quote! { #that })) + //} +//} -impl PartialEq for ExposeSym { - fn eq (&self, other: &Self) -> bool { - let this = &self.0; - let that = &other.0; - format!("{}", quote! { #this }) == format!("{}", quote! { #that }) - } -} +//impl PartialEq for ExposeSym { + //fn eq (&self, other: &Self) -> bool { + //let this = &self.0; + //let that = &other.0; + //format!("{}", quote! { #this }) == format!("{}", quote! { #that }) + //} +//} -impl Eq for ExposeSym {} +//impl Eq for ExposeSym {} impl From for ExposeType { fn from (this: Type) -> Self { Self(Box::new(this)) } } diff --git a/shell.nix b/shell.nix index a84dcd7..a4c3248 100644 --- a/shell.nix +++ b/shell.nix @@ -2,10 +2,10 @@ {pkgs?import{}}:let stdenv = pkgs.clang19Stdenv; name = "tengri"; - nativeBuildInputs = with pkgs; [ pkg-config libclang ]; - buildInputs = with pkgs; [ libclang ]; + nativeBuildInputs = [ pkgs.pkg-config pkgs.libclang pkgs.mold ]; + buildInputs = [ pkgs.libclang ]; LIBCLANG_PATH = "${pkgs.libclang.lib.outPath}/lib"; - LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath (with pkgs; []); + LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath []; in pkgs.mkShell.override { inherit stdenv; } { diff --git a/tengri/Cargo.toml b/tengri/Cargo.toml index c14cdf8..74b46ad 100644 --- a/tengri/Cargo.toml +++ b/tengri/Cargo.toml @@ -22,3 +22,6 @@ tengri_tui = { optional = true, path = "../tui" } tengri_proc = { path = "../proc" } tengri = { path = ".", features = [ "dsl" ] } crossterm = { workspace = true } + +[target.'cfg(target_os = "linux")'] +rustflags = ["-C", "link-arg=-fuse-ld=mold"] diff --git a/tui/examples/tui.rs b/tui/examples/tui.rs index 62dbfe8..323dc9b 100644 --- a/tui/examples/tui.rs +++ b/tui/examples/tui.rs @@ -63,6 +63,7 @@ impl ExampleCommand { } } +tui_draw!(|self: Example, to|to.place(&self.content())); content!(TuiOut: |self: Example|{ let index = self.0 + 1; let wh = self.1.wh(); diff --git a/tui/src/tui_content.rs b/tui/src/tui_content.rs index a89f14e..34d5697 100644 --- a/tui/src/tui_content.rs +++ b/tui/src/tui_content.rs @@ -21,7 +21,7 @@ impl Tui { } } -macro_rules! tui_layout ((|$self:ident:$Self:ty, $to:ident|$expr:expr)=>{ +#[macro_export] macro_rules! tui_layout ((|$self:ident:$Self:ty, $to:ident|$expr:expr)=>{ impl Layout for $Self { fn layout (&$self, $to: [u16;4]) -> [u16;4] { $expr @@ -29,7 +29,7 @@ macro_rules! tui_layout ((|$self:ident:$Self:ty, $to:ident|$expr:expr)=>{ } }); -macro_rules! tui_draw ((|$self:ident:$Self:ty, $to:ident|$expr:expr)=>{ +#[macro_export] macro_rules! tui_draw ((|$self:ident:$Self:ty, $to:ident|$expr:expr)=>{ impl Draw for $Self { fn draw (&$self, $to: &mut TuiOut) { $expr @@ -37,19 +37,74 @@ macro_rules! tui_draw ((|$self:ident:$Self:ty, $to:ident|$expr:expr)=>{ } }); -mod tui_border; pub use self::tui_border::*; -mod tui_button; //pub use self::tui_button::*; -mod tui_color; pub use self::tui_color::*; -mod tui_error; pub use self::tui_error::*; -mod tui_field; pub use self::tui_field::*; +mod tui_border; pub use self::tui_border::*; +mod tui_button; pub use self::tui_button::*; +mod tui_color; pub use self::tui_color::*; +mod tui_error; pub use self::tui_error::*; +mod tui_field; pub use self::tui_field::*; +mod tui_phat; pub use self::tui_phat::*; +mod tui_repeat; pub use self::tui_repeat::*; +mod tui_scroll; pub use self::tui_scroll::*; +mod tui_string; pub use self::tui_string::*; + mod tui_number; //pub use self::tui_number::*; -mod tui_phat; pub use self::tui_phat::*; -mod tui_repeat; pub use self::tui_repeat::*; -mod tui_scroll; pub use self::tui_scroll::*; -mod tui_string; pub use self::tui_string::*; -mod tui_style; pub use self::tui_style::*; mod tui_tryptich; //pub use self::tui_tryptich::*; +pub struct TuiForeground(pub(crate) Foreground); +pub struct TuiBackground(pub(crate) Background); +pub struct Modify(pub bool, pub Modifier, pub T); +pub struct Styled(pub Option