mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-08-28 05:06:56 +02:00
This commit is contained in:
parent
20517f09b4
commit
a9f2fa2cdd
17 changed files with 655 additions and 491 deletions
58
Cargo.lock
generated
58
Cargo.lock
generated
|
|
@ -367,26 +367,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const_panic"
|
name = "const_panic"
|
||||||
version = "0.2.15"
|
version = "0.2.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e262cdaac42494e3ae34c43969f9cdeb7da178bdb4b66fa6a1ea2edb4c8ae652"
|
checksum = "9603f79528ece8163c496f8932121cb36cfe46259e9c907bb3d8205139d7caa3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"const_panic_proc_macros",
|
|
||||||
"typewit",
|
"typewit",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "const_panic_proc_macros"
|
|
||||||
version = "0.2.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "eb0240417fe20ccf13397fa25e6f0a987dbbfaf27d9e13532419df7f593e65e8"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.119",
|
|
||||||
"unicode-xid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "convert_case"
|
name = "convert_case"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
|
@ -617,12 +604,13 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
||||||
name = "dizzle"
|
name = "dizzle"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"const_panic",
|
|
||||||
"dizzle_proc",
|
"dizzle_proc",
|
||||||
"itertools",
|
"itertools",
|
||||||
"konst",
|
"profiling",
|
||||||
"peg",
|
|
||||||
"thiserror 2.0.20",
|
"thiserror 2.0.20",
|
||||||
|
"tracing",
|
||||||
|
"tracing-flame",
|
||||||
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1698,33 +1686,6 @@ dependencies = [
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "peg"
|
|
||||||
version = "0.8.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0aad070be5b63aa72103f2fcdd70a83adbd5e90112ce5b574171ff1c65501773"
|
|
||||||
dependencies = [
|
|
||||||
"peg-macros",
|
|
||||||
"peg-runtime",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "peg-macros"
|
|
||||||
version = "0.8.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ddd8ef6825cae95355031ae26a99b616a2a21f22ba2de0197c43dfb05acbe7ee"
|
|
||||||
dependencies = [
|
|
||||||
"peg-runtime",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "peg-runtime"
|
|
||||||
version = "0.8.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7011d97b484a5ebdc4b1fdb3b12d5e4bbbea56e9d22b688f2e79e04b65a7d8a6"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.2"
|
version = "2.3.2"
|
||||||
|
|
@ -2651,6 +2612,7 @@ dependencies = [
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"dizzle",
|
"dizzle",
|
||||||
"jack",
|
"jack",
|
||||||
|
"konst",
|
||||||
"midly",
|
"midly",
|
||||||
"palette",
|
"palette",
|
||||||
"profiling",
|
"profiling",
|
||||||
|
|
@ -3004,12 +2966,6 @@ version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-xid"
|
|
||||||
version = "0.2.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ term = ["draw", "dep:ratatui", "dep:crossterm"]
|
||||||
anyhow = { version = "1.0" }
|
anyhow = { version = "1.0" }
|
||||||
atomic_float = { version = "1" }
|
atomic_float = { version = "1" }
|
||||||
better-panic = { version = "0.3.0" }
|
better-panic = { version = "0.3.0" }
|
||||||
|
konst = { version = "0.3.16", features = [ "rust_1_83" ] }
|
||||||
|
|
||||||
bumpalo = { optional = true, version = "3.19.0" }
|
bumpalo = { optional = true, version = "3.19.0" }
|
||||||
crossterm = { optional = true, version = "0.29.0" }
|
crossterm = { optional = true, version = "0.29.0" }
|
||||||
|
|
|
||||||
2
dizzle
2
dizzle
|
|
@ -1 +1 @@
|
||||||
Subproject commit 947a2f36a60869ee9aab40aa43d06e1e1c100730
|
Subproject commit 648be30918bef0a975bd225c0499911aaa88bc13
|
||||||
|
|
@ -45,16 +45,20 @@ impl_keywords!(Tui, XYWH<u16>, State [
|
||||||
kw_tui_bg
|
kw_tui_bg
|
||||||
]);
|
]);
|
||||||
|
|
||||||
impl Interpret<Tui, Option<XYWH<u16>>> for State {
|
impl<'a> Interpret<'a, Tui, Option<XYWH<u16>>> for State {
|
||||||
fn interpret_word (&self, to: &mut Tui, sym: &impl Language) -> Perhaps<XYWH<u16>> {
|
fn interpret_word <L: Language<'a> + ?Sized> (&'a self, to: &mut Tui, lang: &'a L)
|
||||||
match sym.src()? {
|
-> Drawn<'a, u16>
|
||||||
|
{
|
||||||
|
match lang.src()? {
|
||||||
Some(":foo") => "foo".draw(to),
|
Some(":foo") => "foo".draw(to),
|
||||||
Some(":bar") => "bar".draw(to),
|
Some(":bar") => "bar".draw(to),
|
||||||
Some(":foobar") => "FOOBAR".draw(to),
|
Some(":foobar") => "FOOBAR".draw(to),
|
||||||
src => todo!("src: {src:?}")
|
src => todo!("src: {src:?}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn interpret_expr (&self, to: &mut Tui, src: &impl Expression) -> Perhaps<XYWH<u16>> {
|
fn interpret_expr <L: Language<'a> + ?Sized> (&self, to: &mut Tui, src: &'a L)
|
||||||
|
-> Drawn<'a, u16>
|
||||||
|
{
|
||||||
if let Some(area) = self.keyword(to, src)? {
|
if let Some(area) = self.keyword(to, src)? {
|
||||||
Ok(Some(area))
|
Ok(Some(area))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
129
src/layout.rs
129
src/layout.rs
|
|
@ -1,44 +1,44 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
impl<S: Screen, T: Draw<S>> Layout<S> for T {}
|
impl<'a, S: Screen, T: Draw<'a, S>> Layout<'a, S> for T {}
|
||||||
|
|
||||||
pub trait Layout<S: Screen>: Draw<S> + Sized {
|
pub trait Layout<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||||
fn origin (self, azimuth: impl Into<Option<Azimuth>>) -> impl Draw<S> {
|
fn origin (self, azimuth: impl Into<Option<Azimuth>>) -> impl Draw<'a, S> {
|
||||||
Origin(azimuth.into(), self)
|
Origin(azimuth.into(), self)
|
||||||
}
|
}
|
||||||
fn origin_c (self) -> impl Draw<S> {
|
fn origin_c (self) -> impl Draw<'a, S> {
|
||||||
Origin(Some(Azimuth::C), self)
|
Origin(Some(Azimuth::C), self)
|
||||||
}
|
}
|
||||||
fn origin_x (self) -> impl Draw<S> {
|
fn origin_x (self) -> impl Draw<'a, S> {
|
||||||
Origin(Some(Azimuth::X), self)
|
Origin(Some(Azimuth::X), self)
|
||||||
}
|
}
|
||||||
fn origin_y (self) -> impl Draw<S> {
|
fn origin_y (self) -> impl Draw<'a, S> {
|
||||||
Origin(Some(Azimuth::Y), self)
|
Origin(Some(Azimuth::Y), self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn origin_n (self) -> impl Draw<S> {
|
fn origin_n (self) -> impl Draw<'a, S> {
|
||||||
Origin(Some(Azimuth::N), self)
|
Origin(Some(Azimuth::N), self)
|
||||||
}
|
}
|
||||||
fn origin_s (self) -> impl Draw<S> {
|
fn origin_s (self) -> impl Draw<'a, S> {
|
||||||
Origin(Some(Azimuth::S), self)
|
Origin(Some(Azimuth::S), self)
|
||||||
}
|
}
|
||||||
fn origin_e (self) -> impl Draw<S> {
|
fn origin_e (self) -> impl Draw<'a, S> {
|
||||||
Origin(Some(Azimuth::E), self)
|
Origin(Some(Azimuth::E), self)
|
||||||
}
|
}
|
||||||
fn origin_w (self) -> impl Draw<S> {
|
fn origin_w (self) -> impl Draw<'a, S> {
|
||||||
Origin(Some(Azimuth::W), self)
|
Origin(Some(Azimuth::W), self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn origin_ne (self) -> impl Draw<S> {
|
fn origin_ne (self) -> impl Draw<'a, S> {
|
||||||
Origin(Some(Azimuth::NE), self)
|
Origin(Some(Azimuth::NE), self)
|
||||||
}
|
}
|
||||||
fn origin_se (self) -> impl Draw<S> {
|
fn origin_se (self) -> impl Draw<'a, S> {
|
||||||
Origin(Some(Azimuth::SE), self)
|
Origin(Some(Azimuth::SE), self)
|
||||||
}
|
}
|
||||||
fn origin_nw (self) -> impl Draw<S> {
|
fn origin_nw (self) -> impl Draw<'a, S> {
|
||||||
Origin(Some(Azimuth::NW), self)
|
Origin(Some(Azimuth::NW), self)
|
||||||
}
|
}
|
||||||
fn origin_sw (self) -> impl Draw<S> {
|
fn origin_sw (self) -> impl Draw<'a, S> {
|
||||||
Origin(Some(Azimuth::SW), self)
|
Origin(Some(Azimuth::SW), self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -76,7 +76,7 @@ impl PartialEq for Sizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sizer {
|
impl Sizer {
|
||||||
pub const fn of <T: Screen> (&self, of: impl Draw<T>) -> impl Draw<T> {
|
pub const fn of <'a, T: Screen> (&self, of: impl Draw<'a, T>) -> impl Draw<'a, T> {
|
||||||
draw(move|to: &mut T|{
|
draw(move|to: &mut T|{
|
||||||
let area = of.draw(to)?;
|
let area = of.draw(to)?;
|
||||||
self.0.store(area.map(|a|a.w()).unwrap_or(T::Unit::zero()).into(), Relaxed);
|
self.0.store(area.map(|a|a.w()).unwrap_or(T::Unit::zero()).into(), Relaxed);
|
||||||
|
|
@ -99,70 +99,13 @@ impl Sizer {
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
|
|
||||||
/// Some layout operations exist in XY, X, and Y variants that take 3 or 2 arguments.
|
|
||||||
/// Their handling in [eval_view] is uniform and goes like this:
|
|
||||||
#[macro_export] macro_rules! eval_xy (
|
|
||||||
// Valueless variant:
|
|
||||||
// (fill/x ...)
|
|
||||||
// (fill/y ...)
|
|
||||||
// (fill/xy ...)
|
|
||||||
(
|
|
||||||
$name:expr => $expr:expr, $head:expr, $output:ident, $state:ident,
|
|
||||||
$variant:expr, $xy:ident, $x:ident, $y:ident, $arg:expr,
|
|
||||||
) => {{
|
|
||||||
// frags.next(): 2nd slash-delimited fragment: /x, /y, /xy
|
|
||||||
let variant = $variant;
|
|
||||||
let thunk = draw(move|screen|$state.interpret(screen, &$arg));
|
|
||||||
match variant {
|
|
||||||
// X variant
|
|
||||||
Some("x") => thunk.$x().draw($output),
|
|
||||||
// Y variant
|
|
||||||
Some("y") => thunk.$y().draw($output),
|
|
||||||
// XY variant (can be omitted)
|
|
||||||
Some("xy") | None => thunk.$xy().draw($output),
|
|
||||||
// Other namespace members are invalid
|
|
||||||
frag => invalid_variant($name, frag, $expr, $head)
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
|
|
||||||
// Variadic variant:
|
|
||||||
// (push/x n ...)
|
|
||||||
// (push/y n ...)
|
|
||||||
// (push/xy n m ...)
|
|
||||||
(
|
|
||||||
$name:expr => $expr:expr, $head:expr, $output:ident, $state:ident,
|
|
||||||
$variant:expr, $xy:ident, $x:ident, $y:ident, $arg0:expr, $arg1:expr, $arg2:expr,
|
|
||||||
) => {{
|
|
||||||
// frags.next(): 2nd slash-delimited fragment: /x, /y, /xy
|
|
||||||
let variant = $variant;
|
|
||||||
let thunk = draw(move|screen|$state.interpret(screen, &match variant {
|
|
||||||
Some("x") | Some("y") => $arg1,
|
|
||||||
Some("xy") | None => $arg2,
|
|
||||||
_ => panic!("{}: unsupported axis {variant:?}; try /x, /y, /xy", $name)
|
|
||||||
}));
|
|
||||||
match variant {
|
|
||||||
// X variant
|
|
||||||
Some("x") => thunk.$x($state.namespace($arg0?)?)
|
|
||||||
.draw($output),
|
|
||||||
// Y variant
|
|
||||||
Some("y") => thunk.$y($state.namespace($arg0?)?)
|
|
||||||
.draw($output),
|
|
||||||
// XY variant (can be omitted)
|
|
||||||
Some("xy") | None => thunk.$xy($state.namespace($arg0?)?, $state.namespace($arg1?)?)
|
|
||||||
.draw($output),
|
|
||||||
// Other namespace members are invalid
|
|
||||||
frag => invalid_variant($name, frag, $expr, $head)
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
);
|
|
||||||
|
|
||||||
#[macro_export] macro_rules! fn_kw_layout {
|
#[macro_export] macro_rules! fn_kw_layout {
|
||||||
($name:ident |$state:ident, $output: ident, $expr:ident| $body:block) => {
|
($name:ident |$state:ident, $output: ident, $expr:ident| $body:block) => {
|
||||||
#[cfg(all(feature = "draw", feature = "eval"))]
|
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||||
pub fn $name <O: Screen, S> (
|
pub fn $name <'a, O: Screen, S> (
|
||||||
$state: &S, $output: &mut O, $expr: &str
|
$state: &'a S, $output: &mut O, $expr: &'a str
|
||||||
) -> Perhaps<XYWH<O::Unit>> where
|
) -> PerhapsRef<'a, XYWH<O::Unit>> where
|
||||||
S: Interpret<O, Option<XYWH<O::Unit>>>
|
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||||
+ Namespace<bool>
|
+ Namespace<bool>
|
||||||
+ Namespace<O::Unit>
|
+ Namespace<O::Unit>
|
||||||
+ Namespace<Option<O::Unit>>
|
+ Namespace<Option<O::Unit>>
|
||||||
|
|
@ -173,10 +116,10 @@ impl Sizer {
|
||||||
#[macro_export] macro_rules! fn_kw_layout_tui {
|
#[macro_export] macro_rules! fn_kw_layout_tui {
|
||||||
($name:ident |$state:ident, $output: ident, $expr:ident| $body:block) => {
|
($name:ident |$state:ident, $output: ident, $expr:ident| $body:block) => {
|
||||||
#[cfg(all(feature = "draw", feature = "eval", feature = "term"))]
|
#[cfg(all(feature = "draw", feature = "eval", feature = "term"))]
|
||||||
pub fn $name <S> (
|
pub fn $name <'a, S> (
|
||||||
$state: &S, $output: &mut Tui, $expr: &str
|
$state: &'a S, $output: &mut Tui, $expr: &'a str
|
||||||
) -> Perhaps<XYWH<u16>> where
|
) -> PerhapsRef<'a, XYWH<u16>> where
|
||||||
S: Interpret<Tui, Option<XYWH<u16>>>
|
S: Interpret<'a, Tui, Option<XYWH<u16>>>
|
||||||
+ Namespace<bool>
|
+ Namespace<bool>
|
||||||
+ Namespace<u16>
|
+ Namespace<u16>
|
||||||
+ Namespace<Option<u16>>
|
+ Namespace<Option<u16>>
|
||||||
|
|
@ -191,9 +134,9 @@ impl Sizer {
|
||||||
$Struct:ident { $X:ident $Y:ident $XY:ident } $kw_name:ident $name:literal
|
$Struct:ident { $X:ident $Y:ident $XY:ident } $kw_name:ident $name:literal
|
||||||
|$self:ident, $to:ident| $body:block
|
|$self:ident, $to:ident| $body:block
|
||||||
) => {
|
) => {
|
||||||
impl<S: Screen, T: Draw<S>> $Trait<S> for T {}
|
impl<S: Screen, T: Draw<'a, S>> $Trait<S> for T {}
|
||||||
|
|
||||||
pub trait $Trait<S: Screen>: Draw<S> + Sized {
|
pub trait $Trait<S: Screen>: Draw<'a, S> + Sized {
|
||||||
fn $fn_x <N: Into<Option<S::Unit>> + Copy> (self, x: N)
|
fn $fn_x <N: Into<Option<S::Unit>> + Copy> (self, x: N)
|
||||||
-> $Struct<S, Self, N> { $Struct::$X(self, x) }
|
-> $Struct<S, Self, N> { $Struct::$X(self, x) }
|
||||||
fn $fn_y <N: Into<Option<S::Unit>> + Copy> (self, y: N)
|
fn $fn_y <N: Into<Option<S::Unit>> + Copy> (self, y: N)
|
||||||
|
|
@ -202,11 +145,11 @@ impl Sizer {
|
||||||
-> $Struct<S, Self, N> { $Struct::$XY(self, x, y) }
|
-> $Struct<S, Self, N> { $Struct::$XY(self, x, y) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum $Struct<S: Screen, I: Draw<S>, X: Into<Option<S::Unit>>> {
|
pub enum $Struct<S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
|
||||||
__(PhantomData<S>), $X(I, X), $Y(I, X), $XY(I, X, X),
|
__(PhantomData<S>), $X(I, X), $Y(I, X), $XY(I, X, X),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <S: Screen, I: Draw<S>, X: Into<Option<S::Unit>> + Copy> Draw<S> for $Struct<S, I, X> {
|
impl <S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>> + Copy> Draw<'a, S> for $Struct<S, I, X> {
|
||||||
fn draw (&$self, $to: &mut S) -> Perhaps<XYWH<S::Unit>> { $body }
|
fn draw (&$self, $to: &mut S) -> Perhaps<XYWH<S::Unit>> { $body }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -216,16 +159,10 @@ impl Sizer {
|
||||||
let mut frags = head.src()?.unwrap_or_default().split("/");
|
let mut frags = head.src()?.unwrap_or_default().split("/");
|
||||||
Ok(matches!(frags.next(), Some($name)).then(||{
|
Ok(matches!(frags.next(), Some($name)).then(||{
|
||||||
#[cfg(feature = "prof")] profiling::scope!(stringify!(inner $kw_name));
|
#[cfg(feature = "prof")] profiling::scope!(stringify!(inner $kw_name));
|
||||||
let args = expr.tail();
|
|
||||||
let arg0 = args.head();
|
|
||||||
let tail0 = args.tail();
|
|
||||||
let arg1 = tail0.head();
|
|
||||||
let tail1 = tail0.tail();
|
|
||||||
let arg2 = tail1.head();
|
|
||||||
eval_xy!(
|
eval_xy!(
|
||||||
$name => expr, head, output, state, frags.next(),
|
$name => expr, head, output, state, frags.next(),
|
||||||
$fn_xy, $fn_x, $fn_y,
|
$fn_xy, $fn_x, $fn_y,
|
||||||
arg0, arg1, arg2,
|
expr.nth(1), expr.nth(2), expr.nth(3),
|
||||||
)
|
)
|
||||||
}).transpose()?.flatten())
|
}).transpose()?.flatten())
|
||||||
});
|
});
|
||||||
|
|
@ -238,9 +175,9 @@ impl Sizer {
|
||||||
$Struct:ident { $X:ident $Y:ident $XY:ident } $kw_name:ident $name:literal
|
$Struct:ident { $X:ident $Y:ident $XY:ident } $kw_name:ident $name:literal
|
||||||
|$self:ident, $to:ident| $body:block
|
|$self:ident, $to:ident| $body:block
|
||||||
) => {
|
) => {
|
||||||
impl<S: Screen, T: Draw<S>> $Trait<S> for T {}
|
impl<S: Screen, T: Draw<'a, S>> $Trait<S> for T {}
|
||||||
|
|
||||||
pub trait $Trait<S: Screen>: Draw<S> + Sized {
|
pub trait $Trait<S: Screen>: Draw<'a, S> + Sized {
|
||||||
fn $fn_x (self) -> $Struct<S, Self> { $Struct::$X(self) }
|
fn $fn_x (self) -> $Struct<S, Self> { $Struct::$X(self) }
|
||||||
fn $fn_y (self) -> $Struct<S, Self> { $Struct::$Y(self) }
|
fn $fn_y (self) -> $Struct<S, Self> { $Struct::$Y(self) }
|
||||||
fn $fn_xy (self) -> $Struct<S, Self> { $Struct::$XY(self) }
|
fn $fn_xy (self) -> $Struct<S, Self> { $Struct::$XY(self) }
|
||||||
|
|
@ -250,7 +187,7 @@ impl Sizer {
|
||||||
__(PhantomData<S>), $X(I), $Y(I), $XY(I),
|
__(PhantomData<S>), $X(I), $Y(I), $XY(I),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <S: Screen, I: Draw<S>> Draw<S> for $Struct<S, I> {
|
impl <'a, S: Screen, I: Draw<'a, S>> Draw<'a, S> for $Struct<S, I> {
|
||||||
fn draw (&$self, $to: &mut S) -> Perhaps<XYWH<S::Unit>> { $body }
|
fn draw (&$self, $to: &mut S) -> Perhaps<XYWH<S::Unit>> { $body }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -260,11 +197,9 @@ impl Sizer {
|
||||||
let mut frags = head.src()?.unwrap_or_default().split("/");
|
let mut frags = head.src()?.unwrap_or_default().split("/");
|
||||||
Ok(matches!(frags.next(), Some($name)).then(||{
|
Ok(matches!(frags.next(), Some($name)).then(||{
|
||||||
#[cfg(feature = "prof")] profiling::scope!(stringify!(inner $kw_name));
|
#[cfg(feature = "prof")] profiling::scope!(stringify!(inner $kw_name));
|
||||||
let args = expr.tail();
|
|
||||||
let arg0 = args.head();
|
|
||||||
eval_xy!(
|
eval_xy!(
|
||||||
$name => expr, head, output, state, frags.next(),
|
$name => expr, head, output, state, frags.next(),
|
||||||
$fn_xy, $fn_x, $fn_y, arg0,
|
$fn_xy, $fn_x, $fn_y, expr.nth(1),
|
||||||
)
|
)
|
||||||
}).transpose()?.flatten())
|
}).transpose()?.flatten())
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,19 @@ use crate::*;
|
||||||
/// let _ = area(XYWH(1, 2, 3, 4), "southeast");
|
/// let _ = area(XYWH(1, 2, 3, 4), "southeast");
|
||||||
/// let _ = area(Some(XYWH(1, 2, 3, 4)), "southeast");
|
/// let _ = area(Some(XYWH(1, 2, 3, 4)), "southeast");
|
||||||
/// ```
|
/// ```
|
||||||
pub fn area <S: Screen, T: Draw<S>, U: Into<Option<XYWH<S::Unit>>>> (
|
pub fn area <'a, S: Screen, T: Draw<'a, S>, U: Into<Option<XYWH<S::Unit>>>> (
|
||||||
origin: U, it: T
|
origin: U, it: T
|
||||||
) -> Area<S, T> {
|
) -> Area<S, T> {
|
||||||
Area(origin.into(), it)
|
Area(origin.into(), it)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Area<S: Screen, T: Draw<S>>(
|
pub struct Area<S: Screen, T>(
|
||||||
pub Option<XYWH<S::Unit>>,
|
pub Option<XYWH<S::Unit>>,
|
||||||
pub T
|
pub T,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl_draw!(<S: Screen, T: Draw<S>,>|self: Area<S, T>, to: S|{
|
impl<'a, S: Screen, T: Draw<'a, S>> Draw<'a, S> for Area<S, T> {
|
||||||
to.draw(self.0, &self.1)
|
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||||
});
|
to.draw(self.0, &self.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,296 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
def_layout_modifier_flat!(
|
pub enum Full<'a, S: Screen, I: Draw<'a, S>> {
|
||||||
LayoutFull (full_w full_h full_wh),
|
__(PhantomData<&'a S>), W(I), H(I), WH(I),
|
||||||
Full { W H WH } kw_full "full" |self, to| {
|
}
|
||||||
|
|
||||||
|
pub enum Exact<'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
|
||||||
|
__(PhantomData<&'a S>), W(I, X), H(I, X), WH(I, X, X),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Push<'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
|
||||||
|
__(PhantomData<&'a S>), X(I, X), Y(I, X), XY(I, X, X),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Pull<'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
|
||||||
|
__(PhantomData<&'a S>), X(I, X), Y(I, X), XY(I, X, X),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Min<'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
|
||||||
|
__(PhantomData<&'a S>), W(I, X), H(I, X), WH(I, X, X),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Max<'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
|
||||||
|
__(PhantomData<&'a S>), W(I, X), H(I, X), WH(I, X, X),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Pad<'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
|
||||||
|
__(PhantomData<&'a S>), X(I, X), Y(I, X), XY(I, X, X),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ```
|
||||||
|
/// # fn test_layout_full () -> Usually<()> {
|
||||||
|
/// assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
|
||||||
|
/// assert_eq!(check_layout("1".full_w())?, Some(XYWH(1u16, 1, 80, 1)));
|
||||||
|
/// assert_eq!(check_layout("1".full_h())?, Some(XYWH(1u16, 1, 1, 25)));
|
||||||
|
/// assert_eq!(check_layout("1".full_wh())?, Some(XYWH(1u16, 1, 80, 25)));
|
||||||
|
/// # Ok(()) }}
|
||||||
|
/// ```
|
||||||
|
pub trait LayoutFull<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||||
|
fn full_w (self) -> Full<'a, S, Self> { Full::W(self) }
|
||||||
|
fn full_h (self) -> Full<'a, S, Self> { Full::H(self) }
|
||||||
|
fn full_wh (self) -> Full<'a, S, Self> { Full::WH(self) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ```
|
||||||
|
/// # fn test_layout_exact () -> Usually<()> {
|
||||||
|
/// assert_eq!(check_layout("FOOBAR\nKILROY")?, Some(XYWH(1, 1, 6, 2)));
|
||||||
|
/// assert_eq!(check_layout("FOOBAR\nKILROY".exact_w(3))?, Some(XYWH(1, 1, 3, 2)));
|
||||||
|
/// assert_eq!(check_layout("FOOBAR\nKILROY".exact_h(1))?, Some(XYWH(1, 1, 6, 1)));
|
||||||
|
/// assert_eq!(check_layout("FOOBAR\nKILROY".exact_wh(2, 1))?, Some(XYWH(1, 1, 2, 1)));
|
||||||
|
/// # Ok(()) }}
|
||||||
|
/// ```
|
||||||
|
pub trait LayoutExact<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||||
|
fn exact_w <X: Into<Option<S::Unit>> + Copy> (self, w: X)
|
||||||
|
-> Exact<'a, S, Self, X> { Exact::W(self, w) }
|
||||||
|
fn exact_h <X: Into<Option<S::Unit>> + Copy> (self, h: X)
|
||||||
|
-> Exact<'a, S, Self, X> { Exact::H(self, h) }
|
||||||
|
fn exact_wh <X: Into<Option<S::Unit>> + Copy> (self, w: X, h: X)
|
||||||
|
-> Exact<'a, S, Self, X> { Exact::WH(self, w, h) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ```
|
||||||
|
/// # fn test_layout_min () -> Usually<()> {
|
||||||
|
/// assert_eq!(check_layout("1".min_w(5))?, Some(XYWH(1u16, 1, 5, 1)));
|
||||||
|
/// assert_eq!(check_layout("1".min_h(5))?, Some(XYWH(1u16, 1, 1, 5)));
|
||||||
|
/// assert_eq!(check_layout("1".min_wh(5, 5))?, Some(XYWH(1u16, 1, 5, 5)));
|
||||||
|
/// assert_eq!(check_layout("123456".min_w(5))?, Some(XYWH(1u16, 1, 6, 1)));
|
||||||
|
/// # Ok(()) }}
|
||||||
|
/// ```
|
||||||
|
pub trait LayoutMin<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||||
|
fn min_w <X: Into<Option<S::Unit>> + Copy> (self, w: X)
|
||||||
|
-> Min<'a, S, Self, X> { Min::W(self, w) }
|
||||||
|
fn min_h <X: Into<Option<S::Unit>> + Copy> (self, h: X)
|
||||||
|
-> Min<'a, S, Self, X> { Min::H(self, h) }
|
||||||
|
fn min_wh <X: Into<Option<S::Unit>> + Copy> (self, w: X, h: X)
|
||||||
|
-> Min<'a, S, Self, X> { Min::WH(self, w, h) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait LayoutMax<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||||
|
fn max_w <X: Into<Option<S::Unit>> + Copy> (self, w: X)
|
||||||
|
-> Max<'a, S, Self, X> { Max::W(self, w) }
|
||||||
|
fn max_h <X: Into<Option<S::Unit>> + Copy> (self, h: X)
|
||||||
|
-> Max<'a, S, Self, X> { Max::H(self, h) }
|
||||||
|
fn max_wh <X: Into<Option<S::Unit>> + Copy> (self, w: X, h: X)
|
||||||
|
-> Max<'a, S, Self, X> { Max::WH(self, w, h) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait LayoutPad<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||||
|
fn pad_w <X: Into<Option<S::Unit>> + Copy> (self, w: X)
|
||||||
|
-> Pad<'a, S, Self, X> { Pad::X(self, w) }
|
||||||
|
fn pad_h <X: Into<Option<S::Unit>> + Copy> (self, h: X)
|
||||||
|
-> Pad<'a, S, Self, X> { Pad::Y(self, h) }
|
||||||
|
fn pad_wh <X: Into<Option<S::Unit>> + Copy> (self, w: X, h: X)
|
||||||
|
-> Pad<'a, S, Self, X> { Pad::XY(self, w, h) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ```
|
||||||
|
/// # fn test_layout_pull () -> Usually<()> {
|
||||||
|
/// assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
|
||||||
|
/// assert_eq!(check_layout("1".push_x(1))?, Some(XYWH(2u16, 1, 1, 1)));
|
||||||
|
/// assert_eq!(check_layout("1".push_y(1))?, Some(XYWH(1u16, 2, 1, 1)));
|
||||||
|
/// assert_eq!(check_layout("1".push_xy(1, 1))?, Some(XYWH(2u16, 2, 1, 1)));
|
||||||
|
/// # Ok(()) }
|
||||||
|
/// ```
|
||||||
|
pub trait LayoutPush<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||||
|
fn push_x <X: Into<Option<S::Unit>> + Copy> (self, w: X)
|
||||||
|
-> Push<'a, S, Self, X> { Push::X(self, w) }
|
||||||
|
fn push_y <X: Into<Option<S::Unit>> + Copy> (self, h: X)
|
||||||
|
-> Push<'a, S, Self, X> { Push::Y(self, h) }
|
||||||
|
fn push_xy <X: Into<Option<S::Unit>> + Copy> (self, w: X, h: X)
|
||||||
|
-> Push<'a, S, Self, X> { Push::XY(self, w, h) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ```
|
||||||
|
/// # fn test_layout_push () -> Usually<()> {
|
||||||
|
/// assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
|
||||||
|
/// assert_eq!(check_layout("1".pull_x(1))?, Some(XYWH(0u16, 1, 1, 1)));
|
||||||
|
/// assert_eq!(check_layout("1".pull_y(1))?, Some(XYWH(1u16, 0, 1, 1)));
|
||||||
|
/// assert_eq!(check_layout("1".pull_xy(1, 1))?, Some(XYWH(0u16, 0, 1, 1)));
|
||||||
|
/// # Ok(()) }
|
||||||
|
/// ```
|
||||||
|
pub trait LayoutPull<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||||
|
fn pull_x <X: Into<Option<S::Unit>> + Copy> (self, w: X)
|
||||||
|
-> Pull<'a, S, Self, X> { Pull::X(self, w) }
|
||||||
|
fn pull_y <X: Into<Option<S::Unit>> + Copy> (self, h: X)
|
||||||
|
-> Pull<'a, S, Self, X> { Pull::Y(self, h) }
|
||||||
|
fn pull_xy <X: Into<Option<S::Unit>> + Copy> (self, w: X, h: X)
|
||||||
|
-> Pull<'a, S, Self, X> { Pull::XY(self, w, h) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||||
|
pub fn kw_full <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||||
|
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||||
|
where
|
||||||
|
O: Screen + 'a,
|
||||||
|
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||||
|
+ Namespace<bool>
|
||||||
|
+ Namespace<O::Unit>
|
||||||
|
+ Namespace<Option<O::Unit>>
|
||||||
|
{
|
||||||
|
let thunk = draw(move|screen|ok_flat(expr.nth(1)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
|
Ok(match expr.head()? {
|
||||||
|
Some("full/x") | Some("full/w") => Full::W(thunk).draw(to)?,
|
||||||
|
Some("full/y") | Some("full/h") => Full::H(thunk).draw(to)?,
|
||||||
|
Some("full/xy") | Some("full/wh") => Full::WH(thunk).draw(to)?,
|
||||||
|
frag => return Err(format!("invalid variant: {frag:?}").into())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||||
|
pub fn kw_exact <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||||
|
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||||
|
where
|
||||||
|
O: Screen + 'a,
|
||||||
|
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||||
|
+ Namespace<bool>
|
||||||
|
+ Namespace<O::Unit>
|
||||||
|
+ Namespace<Option<O::Unit>>
|
||||||
|
{
|
||||||
|
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
|
Ok(match expr.head()? {
|
||||||
|
Some("exact/w") => thunk.exact_w(
|
||||||
|
state.namespace(expr.nth(1)?)?
|
||||||
|
).draw(to)?,
|
||||||
|
Some("exact/h") => thunk.exact_h(
|
||||||
|
state.namespace(expr.nth(1)?)?
|
||||||
|
).draw(to)?,
|
||||||
|
Some("exact/wh") => thunk.exact_wh(
|
||||||
|
state.namespace(expr.nth(1)?)?,
|
||||||
|
state.namespace(expr.nth(2)?)?,
|
||||||
|
).draw(to)?,
|
||||||
|
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||||
|
pub fn kw_min <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||||
|
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||||
|
where
|
||||||
|
O: Screen + 'a,
|
||||||
|
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||||
|
+ Namespace<bool>
|
||||||
|
+ Namespace<O::Unit>
|
||||||
|
+ Namespace<Option<O::Unit>>
|
||||||
|
{
|
||||||
|
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
|
Ok(match expr.head()? {
|
||||||
|
Some("min/w") => thunk.min_w(
|
||||||
|
state.namespace(expr.nth(1)?)?
|
||||||
|
).draw(to)?,
|
||||||
|
Some("min/h") => thunk.min_h(
|
||||||
|
state.namespace(expr.nth(1)?)?
|
||||||
|
).draw(to)?,
|
||||||
|
Some("min/wh") => thunk.min_wh(
|
||||||
|
state.namespace(expr.nth(1)?)?,
|
||||||
|
state.namespace(expr.nth(2)?)?,
|
||||||
|
).draw(to)?,
|
||||||
|
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||||
|
pub fn kw_max <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||||
|
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||||
|
where
|
||||||
|
O: Screen + 'a,
|
||||||
|
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||||
|
+ Namespace<bool>
|
||||||
|
+ Namespace<O::Unit>
|
||||||
|
+ Namespace<Option<O::Unit>>
|
||||||
|
{
|
||||||
|
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
|
Ok(match expr.head()? {
|
||||||
|
Some("max/w") => thunk.max_w(
|
||||||
|
state.namespace(expr.nth(1)?)?
|
||||||
|
).draw(to)?,
|
||||||
|
Some("max/h") => thunk.max_h(
|
||||||
|
state.namespace(expr.nth(1)?)?
|
||||||
|
).draw(to)?,
|
||||||
|
Some("max/wh") => thunk.max_wh(
|
||||||
|
state.namespace(expr.nth(1)?)?,
|
||||||
|
state.namespace(expr.nth(2)?)?,
|
||||||
|
).draw(to)?,
|
||||||
|
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||||
|
pub fn kw_push <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||||
|
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||||
|
where
|
||||||
|
O: Screen + 'a,
|
||||||
|
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||||
|
+ Namespace<bool>
|
||||||
|
+ Namespace<O::Unit>
|
||||||
|
+ Namespace<Option<O::Unit>>
|
||||||
|
{
|
||||||
|
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
|
Ok(match expr.head()? {
|
||||||
|
Some("push/w") => thunk.push_x(state.namespace(expr.nth(1)?)?).draw(to)?,
|
||||||
|
Some("push/h") => thunk.push_y(state.namespace(expr.nth(1)?)?).draw(to)?,
|
||||||
|
Some("push/wh") => thunk.push_xy(state.namespace(expr.nth(1)?)?, state.namespace(expr.nth(2)?)?,).draw(to)?,
|
||||||
|
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||||
|
pub fn kw_pull <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||||
|
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||||
|
where
|
||||||
|
O: Screen + 'a,
|
||||||
|
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||||
|
+ Namespace<bool>
|
||||||
|
+ Namespace<O::Unit>
|
||||||
|
+ Namespace<Option<O::Unit>>
|
||||||
|
{
|
||||||
|
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
|
Ok(match expr.head()? {
|
||||||
|
Some("pull/w") => thunk.pull_x(state.namespace(expr.nth(1)?)?).draw(to)?,
|
||||||
|
Some("pull/h") => thunk.pull_y(state.namespace(expr.nth(1)?)?).draw(to)?,
|
||||||
|
Some("pull/wh") => thunk.pull_xy(state.namespace(expr.nth(1)?)?, state.namespace(expr.nth(2)?)?,).draw(to)?,
|
||||||
|
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||||
|
pub fn kw_pad <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||||
|
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||||
|
where
|
||||||
|
O: Screen + 'a,
|
||||||
|
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||||
|
+ Namespace<bool>
|
||||||
|
+ Namespace<O::Unit>
|
||||||
|
+ Namespace<Option<O::Unit>>
|
||||||
|
{
|
||||||
|
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
|
Ok(match expr.head()? {
|
||||||
|
Some("pad/w") => thunk.pad_w(
|
||||||
|
state.namespace(expr.nth(1)?)?
|
||||||
|
).draw(to)?,
|
||||||
|
Some("pad/h") => thunk.pad_h(
|
||||||
|
state.namespace(expr.nth(1)?)?
|
||||||
|
).draw(to)?,
|
||||||
|
Some("pad/wh") => thunk.pad_wh(
|
||||||
|
state.namespace(expr.nth(1)?)?,
|
||||||
|
state.namespace(expr.nth(2)?)?,
|
||||||
|
).draw(to)?,
|
||||||
|
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <'a, S: Screen, I: Draw<'a, S>> Draw<'a, S> for Full<'a, S, I> {
|
||||||
|
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||||
let XYWH(x0, y0, w0, h0) = to.area();
|
let XYWH(x0, y0, w0, h0) = to.area();
|
||||||
let item = match self {
|
let item = match self {
|
||||||
Self::W(i) => i, Self::H(i) => i, Self::WH(i) => i, _ => unreachable!()
|
Self::W(i) => i, Self::H(i) => i, Self::WH(i) => i, _ => unreachable!()
|
||||||
|
|
@ -17,19 +305,10 @@ def_layout_modifier_flat!(
|
||||||
x1.unwrap_or(x2), y1.unwrap_or(y2), w1.unwrap_or(w2), h1.unwrap_or(h2),
|
x1.unwrap_or(x2), y1.unwrap_or(y2), w1.unwrap_or(w2), h1.unwrap_or(h2),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(test)] #[test] fn test_layout_full () -> Usually<()> {
|
|
||||||
assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
|
|
||||||
assert_eq!(check_layout("1".full_w())?, Some(XYWH(1u16, 1, 80, 1)));
|
|
||||||
assert_eq!(check_layout("1".full_h())?, Some(XYWH(1u16, 1, 1, 25)));
|
|
||||||
assert_eq!(check_layout("1".full_wh())?, Some(XYWH(1u16, 1, 80, 25)));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def_layout_modifier!(
|
impl <'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>> + Copy> Draw<'a, S> for Exact<'a, S, I, X> {
|
||||||
LayoutExact (exact_w exact_h exact_wh),
|
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||||
Exact { W H WH } kw_exact "exact" |self, to| {
|
|
||||||
let XYWH(x0, y0, w0, h0) = to.area();
|
let XYWH(x0, y0, w0, h0) = to.area();
|
||||||
let (item, w1, h1) = match self {
|
let (item, w1, h1) = match self {
|
||||||
Self::W(item, w1) => (item, (*w1).into(), None),
|
Self::W(item, w1) => (item, (*w1).into(), None),
|
||||||
|
|
@ -48,19 +327,10 @@ def_layout_modifier!(
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(test)] #[test] fn test_layout_exact () -> Usually<()> {
|
|
||||||
assert_eq!(check_layout("FOOBAR\nKILROY")?, Some(XYWH(1, 1, 6, 2)));
|
|
||||||
assert_eq!(check_layout("FOOBAR\nKILROY".exact_w(3))?, Some(XYWH(1, 1, 3, 2)));
|
|
||||||
assert_eq!(check_layout("FOOBAR\nKILROY".exact_h(1))?, Some(XYWH(1, 1, 6, 1)));
|
|
||||||
assert_eq!(check_layout("FOOBAR\nKILROY".exact_wh(2, 1))?, Some(XYWH(1, 1, 2, 1)));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def_layout_modifier!(
|
impl <'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>> + Copy> Draw<'a, S> for Min<'a, S, I, X> {
|
||||||
LayoutMin (min_w min_h min_wh),
|
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||||
Min { W H WH } kw_min "min" |self, to| {
|
|
||||||
let XYWH(x0, y0, w0, h0) = to.area();
|
let XYWH(x0, y0, w0, h0) = to.area();
|
||||||
let (item, w1, h1) = match self {
|
let (item, w1, h1) = match self {
|
||||||
Self::W(item, w1) => (item, (*w1).into(), None),
|
Self::W(item, w1) => (item, (*w1).into(), None),
|
||||||
|
|
@ -78,19 +348,10 @@ def_layout_modifier!(
|
||||||
h1.map(|h1|h1.max(h2)).unwrap_or(h2)
|
h1.map(|h1|h1.max(h2)).unwrap_or(h2)
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(test)] #[test] fn test_layout_min () -> Usually<()> {
|
|
||||||
assert_eq!(check_layout("1".min_w(5))?, Some(XYWH(1u16, 1, 5, 1)));
|
|
||||||
assert_eq!(check_layout("1".min_h(5))?, Some(XYWH(1u16, 1, 1, 5)));
|
|
||||||
assert_eq!(check_layout("1".min_wh(5, 5))?, Some(XYWH(1u16, 1, 5, 5)));
|
|
||||||
assert_eq!(check_layout("123456".min_w(5))?, Some(XYWH(1u16, 1, 6, 1)));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def_layout_modifier!(
|
impl <'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>> + Copy> Draw<'a, S> for Max<'a, S, I, X> {
|
||||||
LayoutMax (max_w max_h max_wh),
|
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||||
Max { W H WH } kw_max "max" |self, to| {
|
|
||||||
let XYWH(x, y, w0, h0) = to.area();
|
let XYWH(x, y, w0, h0) = to.area();
|
||||||
let (item, w, h) = match self {
|
let (item, w, h) = match self {
|
||||||
Self::W(item, w) => (item, (*w).into().unwrap_or(w0), h0),
|
Self::W(item, w) => (item, (*w).into().unwrap_or(w0), h0),
|
||||||
|
|
@ -100,31 +361,10 @@ def_layout_modifier!(
|
||||||
};
|
};
|
||||||
to.draw(XYWH(x, y, if w0 > w { w } else { w0 }, if h0 > h { h } else { h0 }), item)
|
to.draw(XYWH(x, y, if w0 > w { w } else { w0 }, if h0 > h { h } else { h0 }), item)
|
||||||
}
|
}
|
||||||
);
|
}
|
||||||
|
|
||||||
def_layout_modifier!(
|
impl <'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>> + Copy> Draw<'a, S> for Push<'a, S, I, X> {
|
||||||
LayoutPad (pad_w pad_h pad_wh),
|
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||||
Pad { X Y XY } kw_pad "pad" |self, to| {
|
|
||||||
let XYWH(x, y, w0, h0) = to.area();
|
|
||||||
let (item, w, h) = match self {
|
|
||||||
Self::X(item, w) => (item, (*w).into().unwrap_or_default(), Default::default()),
|
|
||||||
Self::Y(item, h) => (item, Default::default(), (*h).into().unwrap_or_default()),
|
|
||||||
Self::XY(item, w, h) => (item, (*w).into().unwrap_or_default(),
|
|
||||||
(*h).into().unwrap_or_default()),
|
|
||||||
_ => return Ok(None)
|
|
||||||
};
|
|
||||||
to.draw(XYWH(
|
|
||||||
x.plus(w),
|
|
||||||
y.plus(h),
|
|
||||||
w0.minus(w).minus(w),
|
|
||||||
h0.minus(h).minus(h),
|
|
||||||
), item)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
def_layout_modifier!(
|
|
||||||
LayoutPush (push_x push_y push_xy),
|
|
||||||
Push { X Y XY } kw_push "push" |self, to| {
|
|
||||||
match self {
|
match self {
|
||||||
Self::__(_) => unreachable!(),
|
Self::__(_) => unreachable!(),
|
||||||
Self::X(item, x1) if let Some(XYWH(x, y, w, h)) = to.size(None, item)? => {
|
Self::X(item, x1) if let Some(XYWH(x, y, w, h)) = to.size(None, item)? => {
|
||||||
|
|
@ -139,19 +379,10 @@ def_layout_modifier!(
|
||||||
_ => Ok(None)
|
_ => Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(test)] #[test] fn test_layout_push () -> Usually<()> {
|
|
||||||
assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
|
|
||||||
assert_eq!(check_layout("1".push_x(1))?, Some(XYWH(2u16, 1, 1, 1)));
|
|
||||||
assert_eq!(check_layout("1".push_y(1))?, Some(XYWH(1u16, 2, 1, 1)));
|
|
||||||
assert_eq!(check_layout("1".push_xy(1, 1))?, Some(XYWH(2u16, 2, 1, 1)));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def_layout_modifier!(
|
impl <'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>> + Copy> Draw<'a, S> for Pull<'a, S, I, X> {
|
||||||
LayoutPull (pull_x pull_y pull_xy),
|
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||||
Pull { X Y XY } kw_pull "pull" |self, to| {
|
|
||||||
match self {
|
match self {
|
||||||
Self::__(_) => unreachable!(),
|
Self::__(_) => unreachable!(),
|
||||||
Self::X(item, x1) if let Some(XYWH(x, y, w, h)) = to.size(None, item)? => {
|
Self::X(item, x1) if let Some(XYWH(x, y, w, h)) = to.size(None, item)? => {
|
||||||
|
|
@ -172,16 +403,41 @@ def_layout_modifier!(
|
||||||
_ => Ok(None)
|
_ => Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(test)] #[test] fn test_layout_pull () -> Usually<()> {
|
|
||||||
assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
|
|
||||||
assert_eq!(check_layout("1".pull_x(1))?, Some(XYWH(0u16, 1, 1, 1)));
|
|
||||||
assert_eq!(check_layout("1".pull_y(1))?, Some(XYWH(1u16, 0, 1, 1)));
|
|
||||||
assert_eq!(check_layout("1".pull_xy(1, 1))?, Some(XYWH(0u16, 0, 1, 1)));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)] fn check_layout (t: impl Draw<Tui>) -> Perhaps<XYWH<u16>> {
|
impl <'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>> + Copy> Draw<'a, S> for Pad<'a, S, I, X> {
|
||||||
|
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||||
|
let XYWH(x, y, w0, h0) = to.area();
|
||||||
|
let (item, w, h) = match self {
|
||||||
|
Self::X(item, w) => (item, (*w).into().unwrap_or_default(), Default::default()),
|
||||||
|
Self::Y(item, h) => (item, Default::default(), (*h).into().unwrap_or_default()),
|
||||||
|
Self::XY(item, w, h) => (item, (*w).into().unwrap_or_default(),
|
||||||
|
(*h).into().unwrap_or_default()),
|
||||||
|
_ => return Ok(None)
|
||||||
|
};
|
||||||
|
to.draw(XYWH(
|
||||||
|
x.plus(w),
|
||||||
|
y.plus(h),
|
||||||
|
w0.minus(w).minus(w),
|
||||||
|
h0.minus(h).minus(h),
|
||||||
|
), item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, S: Screen, T: Draw<'a, S>> LayoutFull<'a, S> for T {}
|
||||||
|
|
||||||
|
impl<'a, S: Screen, T: Draw<'a, S>> LayoutExact<'a, S> for T {}
|
||||||
|
|
||||||
|
impl<'a, S: Screen, T: Draw<'a, S>> LayoutMin<'a, S> for T {}
|
||||||
|
|
||||||
|
impl<'a, S: Screen, T: Draw<'a, S>> LayoutMax<'a, S> for T {}
|
||||||
|
|
||||||
|
impl<'a, S: Screen, T: Draw<'a, S>> LayoutPush<'a, S> for T {}
|
||||||
|
|
||||||
|
impl<'a, S: Screen, T: Draw<'a, S>> LayoutPull<'a, S> for T {}
|
||||||
|
|
||||||
|
impl<'a, S: Screen, T: Draw<'a, S>> LayoutPad<'a, S> for T {}
|
||||||
|
|
||||||
|
#[cfg(test)] fn check_layout <'a> (t: impl Draw<'a, Tui>) -> Drawn<'a, u16> {
|
||||||
Tui::Layout(XYWH(1u16, 1, 80, 25)).size(None, t)
|
Tui::Layout(XYWH(1u16, 1, 80, 25)).size(None, t)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,11 @@ pub struct Origin<T>(
|
||||||
pub(crate) T
|
pub(crate) T
|
||||||
);
|
);
|
||||||
|
|
||||||
impl_draw!(<S: Screen, T: Draw<S>,>|self: Origin<T>, _to: S|{
|
impl<'a, S: Screen, T: Draw<'a, S>> Draw<'a, S> for Origin<T> {
|
||||||
todo!()
|
fn draw (&self, _to: &mut S) -> Drawn<'a, S::Unit> {
|
||||||
});
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Something that has `[0, 0]` at a particular point.
|
/// Something that has `[0, 0]` at a particular point.
|
||||||
pub trait HasOrigin {
|
pub trait HasOrigin {
|
||||||
|
|
@ -33,25 +35,47 @@ impl<T: AsRef<Azimuth>> HasOrigin for T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn_kw_layout!(kw_align |state, output, expr| {
|
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||||
let head = expr.head();
|
pub fn kw_align <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||||
let mut frags = head.src()?.unwrap_or_default().split("/");
|
-> Drawn<'a, O::Unit>
|
||||||
Ok(matches!(frags.next(), Some("align")).then(||{
|
where
|
||||||
draw(move|output: &mut O|{state.interpret(output, &expr.tail().head())}).align(
|
O: Screen,
|
||||||
eval_enum!("align", output, state,
|
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||||
expr.head().src()?.unwrap_or_default().split("/").skip(1).next(),
|
+ Namespace<bool>
|
||||||
Azimuth {
|
+ Namespace<O::Unit>
|
||||||
"c" => C, "x" => X, "y" => Y,
|
+ Namespace<Option<O::Unit>>
|
||||||
"n" => N, "s" => S, "e" => E, "w" => W,
|
{
|
||||||
"nw" => NW, "sw" => SW, "ne" => NE, "se" => SE,
|
let thunk = draw(move|screen|ok_flat(expr.nth(1)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
})
|
Ok(match expr.head()? {
|
||||||
).draw(output)
|
Some("align/c") => Align(Some(Azimuth::C), thunk).draw(to)?,
|
||||||
}).transpose()?.flatten())
|
Some("align/x") => Align(Some(Azimuth::X), thunk).draw(to)?,
|
||||||
});
|
Some("align/y") => Align(Some(Azimuth::Y), thunk).draw(to)?,
|
||||||
|
Some("align/n") => Align(Some(Azimuth::N), thunk).draw(to)?,
|
||||||
|
Some("align/s") => Align(Some(Azimuth::S), thunk).draw(to)?,
|
||||||
|
Some("align/e") => Align(Some(Azimuth::E), thunk).draw(to)?,
|
||||||
|
Some("align/w") => Align(Some(Azimuth::W), thunk).draw(to)?,
|
||||||
|
Some("align/nw") => Align(Some(Azimuth::NW), thunk).draw(to)?,
|
||||||
|
Some("align/sw") => Align(Some(Azimuth::SW), thunk).draw(to)?,
|
||||||
|
Some("align/ne") => Align(Some(Azimuth::NE), thunk).draw(to)?,
|
||||||
|
Some("align/se") => Align(Some(Azimuth::SE), thunk).draw(to)?,
|
||||||
|
frag => return Err(format!("invalid variant: {frag:?}").into())
|
||||||
|
})
|
||||||
|
//Ok(matches!(expr.head().src()?.unwrap_or_default().split("/").next(), Some("align")).then(||{
|
||||||
|
//draw(move|output: &mut O|{state.interpret(output, &expr.nth(1))}).align(
|
||||||
|
//eval_enum!("align", output, state,
|
||||||
|
//expr.head().src()?.unwrap_or_default().split("/").skip(1).next(),
|
||||||
|
//Azimuth {
|
||||||
|
//"c" => C, "x" => X, "y" => Y,
|
||||||
|
//"n" => N, "s" => S, "e" => E, "w" => W,
|
||||||
|
//"nw" => NW, "sw" => SW, "ne" => NE, "se" => SE,
|
||||||
|
//})
|
||||||
|
//).draw(output)
|
||||||
|
//}).transpose()?.flatten())
|
||||||
|
}
|
||||||
|
|
||||||
impl<S: Screen, T: Draw<S>> CanAlign<S> for T {}
|
impl<'a, S: Screen, T: Draw<'a, S>> CanAlign<'a, S> for T {}
|
||||||
|
|
||||||
pub trait CanAlign<S: Screen>: Draw<S> + Sized {
|
pub trait CanAlign<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||||
fn align (self, azimuth: impl Into<Option<Azimuth>>) -> Align<Self> {
|
fn align (self, azimuth: impl Into<Option<Azimuth>>) -> Align<Self> {
|
||||||
Align(azimuth.into(), self)
|
Align(azimuth.into(), self)
|
||||||
}
|
}
|
||||||
|
|
@ -95,8 +119,8 @@ pub struct Align<T>(
|
||||||
pub(crate) T,
|
pub(crate) T,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<S: Screen, T: Draw<S>> Draw<S> for Align<T> {
|
impl<'a, S: Screen, T: Draw<'a, S>> Draw<'a, S> for Align<T> {
|
||||||
fn draw (&self, to: &mut S) -> Perhaps<XYWH<S::Unit>> {
|
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||||
let Self(azimuth, item) = self;
|
let Self(azimuth, item) = self;
|
||||||
let area0 = to.area();
|
let area0 = to.area();
|
||||||
let size = to.size(area0, item)?;
|
let size = to.size(area0, item)?;
|
||||||
|
|
@ -133,25 +157,17 @@ fn align <S: Screen> (
|
||||||
}
|
}
|
||||||
|
|
||||||
fn_kw_layout!(kw_split |state, output, expr| {
|
fn_kw_layout!(kw_split |state, output, expr| {
|
||||||
let head = expr.head();
|
let thunk_a = draw(move|screen|ok_flat(expr.nth(1)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
let mut frags = head.src()?.unwrap_or_default().split("/");
|
let thunk_b = draw(move|screen|ok_flat(expr.nth(2)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
Ok(matches!(frags.next(), Some("bsp")).then(||{
|
Ok(match expr.head()? {
|
||||||
eval_enum!("bsp", output, state, frags.next(), Split {
|
Some("bsp/n") => Split::North.stack(thunk_a, thunk_b).draw(output)?,
|
||||||
"n" => North,
|
Some("bsp/s") => Split::South.stack(thunk_a, thunk_b).draw(output)?,
|
||||||
"s" => South,
|
Some("bsp/e") => Split::East.stack(thunk_a, thunk_b).draw(output)?,
|
||||||
"e" => East,
|
Some("bsp/w") => Split::West.stack(thunk_a, thunk_b).draw(output)?,
|
||||||
"w" => West,
|
Some("bsp/a") => Split::Above.stack(thunk_a, thunk_b).draw(output)?,
|
||||||
"a" => Above,
|
Some("bsp/b") => Split::Below.stack(thunk_a, thunk_b).draw(output)?,
|
||||||
"b" => Below
|
frag => return Err(format!("invalid variant: {frag:?}").into())
|
||||||
}).stack(
|
})
|
||||||
draw(move|output: &mut O|{
|
|
||||||
state.interpret(output, &expr.tail().head()?)
|
|
||||||
}),
|
|
||||||
draw(move|output: &mut O|{
|
|
||||||
state.interpret(output, &expr.tail().tail().head()?)
|
|
||||||
}),
|
|
||||||
).draw(output)
|
|
||||||
}).transpose()?.flatten())
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Split along an axis. Direction determines order.
|
/// Split along an axis. Direction determines order.
|
||||||
|
|
@ -165,16 +181,28 @@ fn_kw_layout!(kw_split |state, output, expr| {
|
||||||
#[default] Below
|
#[default] Below
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Pair<S: Screen, A: Draw<S>, B: Draw<S>>(Split, A, B, PhantomData<S>);
|
pub struct Pair<A, B>(Split, A, B);
|
||||||
|
|
||||||
pub fn split <S: Screen, A: Draw<S>, B: Draw<S>> (
|
/// ```
|
||||||
|
/// # fn test_split_stack () -> Usually<()> {
|
||||||
|
/// use Split::*;
|
||||||
|
/// fn size_of <A: Draw<Tui>, B: Draw<Tui>> (stack: &Pair<Tui, A, B>) -> Drawn<'a, S::Unit> {
|
||||||
|
/// Tui::Layout(XYWH(0, 0, 80, 25)).size(None, stack)
|
||||||
|
/// }
|
||||||
|
/// assert_eq!(size_of(&split(East, "foo", "bar"))?, Some(XYWH(0, 0, 6, 1)));
|
||||||
|
/// assert_eq!(size_of(&split(South, "foo", "bar"))?, Some(XYWH(0, 0, 3, 2)));
|
||||||
|
/// assert_eq!(size_of(&split(South, split(East, "foo", "bar"), "baz"))?, Some(XYWH(0, 0, 6, 2)));
|
||||||
|
/// assert_eq!(size_of(&split(East, split(South, "foo", "bar"), "baz"))?, Some(XYWH(0, 0, 6, 2)));
|
||||||
|
/// # return Ok(()); }
|
||||||
|
/// ```
|
||||||
|
pub fn split <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (
|
||||||
split: Split, a: A, b: B
|
split: Split, a: A, b: B
|
||||||
) -> Pair<S, A, B> {
|
) -> Pair<A, B> {
|
||||||
Pair(split, a, b, PhantomData)
|
Pair(split, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Screen, A: Draw<S>, B: Draw<S>> Draw<S> for Pair<S, A, B> {
|
impl<'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> Draw<'a, S> for Pair<A, B> {
|
||||||
fn draw (&self, to: &mut S) -> Drawn<S::Unit> {
|
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||||
let Self(split, a, b, ..) = self;
|
let Self(split, a, b, ..) = self;
|
||||||
let (area_a, area_b) = stack_areas(split, to, a, b)?;
|
let (area_a, area_b) = stack_areas(split, to, a, b)?;
|
||||||
let (drawn_a, drawn_b) = draw_stacks(split, to, a, area_a, None, b, area_b, None)?;
|
let (drawn_a, drawn_b) = draw_stacks(split, to, a, area_a, None, b, area_b, None)?;
|
||||||
|
|
@ -182,16 +210,16 @@ impl<S: Screen, A: Draw<S>, B: Draw<S>> Draw<S> for Pair<S, A, B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_stacks <S: Screen> (
|
fn draw_stacks <'a, S: Screen> (
|
||||||
split: &Split,
|
split: &Split,
|
||||||
to: &mut S,
|
to: &mut S,
|
||||||
a: impl Draw<S>,
|
a: impl Draw<'a, S>,
|
||||||
area_a: impl Into<Option<XYWH<S::Unit>>>,
|
area_a: impl Into<Option<XYWH<S::Unit>>>,
|
||||||
origin_a: impl Into<Option<Azimuth>>,
|
origin_a: impl Into<Option<Azimuth>>,
|
||||||
b: impl Draw<S>,
|
b: impl Draw<'a, S>,
|
||||||
area_b: impl Into<Option<XYWH<S::Unit>>>,
|
area_b: impl Into<Option<XYWH<S::Unit>>>,
|
||||||
origin_b: impl Into<Option<Azimuth>>,
|
origin_b: impl Into<Option<Azimuth>>,
|
||||||
) -> Usually<(Option<XYWH<S::Unit>>, Option<XYWH<S::Unit>>)> {
|
) -> UsuallyRef<'a, (Option<XYWH<S::Unit>>, Option<XYWH<S::Unit>>)> {
|
||||||
let draw_a = |to: &mut S|Ok::<_, Box<dyn Error>>(match origin_a.into() {
|
let draw_a = |to: &mut S|Ok::<_, Box<dyn Error>>(match origin_a.into() {
|
||||||
Some(origin_a) => to.draw(area_a.into(), a.align(origin_a))?,
|
Some(origin_a) => to.draw(area_a.into(), a.align(origin_a))?,
|
||||||
None => to.draw(area_a.into(), a)?
|
None => to.draw(area_a.into(), a)?
|
||||||
|
|
@ -209,12 +237,25 @@ fn draw_stacks <S: Screen> (
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stack_areas <S: Screen> (
|
/// ```
|
||||||
|
/// # fn test_stack_areas () -> Usually<()> {
|
||||||
|
/// let area = XYWH(0u16, 0, 80, 25);
|
||||||
|
/// assert_eq!(stack_areas(&Split::East, &mut Tui::Layout(area), &"foo", &"bar")?, (
|
||||||
|
/// Some(XYWH(0u16, 0, 3, 1)),
|
||||||
|
/// Some(XYWH(3u16, 0, 3, 1)),
|
||||||
|
/// ));
|
||||||
|
/// assert_eq!(stack_areas(&Split::South, &mut Tui::Layout(area), &"foo", &"bar")?, (
|
||||||
|
/// Some(XYWH(0u16, 0, 3, 1)),
|
||||||
|
/// Some(XYWH(0u16, 1, 3, 1)),
|
||||||
|
/// ));
|
||||||
|
/// # Ok(()) }
|
||||||
|
/// ```
|
||||||
|
pub fn stack_areas <'a, S: Screen> (
|
||||||
split: &Split,
|
split: &Split,
|
||||||
to: &mut S,
|
to: &mut S,
|
||||||
a: impl Draw<S>,
|
a: impl Draw<'a, S>,
|
||||||
b: impl Draw<S>,
|
b: impl Draw<'a, S>,
|
||||||
) -> Usually<(Option<XYWH<S::Unit>>, Option<XYWH<S::Unit>>)> {
|
) -> UsuallyRef<'a, (Option<XYWH<S::Unit>>, Option<XYWH<S::Unit>>)> {
|
||||||
let area_a = to.size(None, a)?;
|
let area_a = to.size(None, a)?;
|
||||||
Ok(match split {
|
Ok(match split {
|
||||||
Split::South => (
|
Split::South => (
|
||||||
|
|
@ -289,8 +330,10 @@ impl Split {
|
||||||
/// let _ = Split::East.stack(&"", &"");
|
/// let _ = Split::East.stack(&"", &"");
|
||||||
/// let _ = Split::West.stack(&"", &"");
|
/// let _ = Split::West.stack(&"", &"");
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn stack <S: Screen, A: Draw<S>, B: Draw<S>> (&self, a: A, b: B) -> impl Draw<S> {
|
pub const fn stack <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (&self, a: A, b: B)
|
||||||
Pair(*self, a, b, PhantomData)
|
-> impl Draw<'a, S>
|
||||||
|
{
|
||||||
|
Pair(*self, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
|
|
@ -302,7 +345,9 @@ impl Split {
|
||||||
/// let _ = Split::East.half(&"", &"");
|
/// let _ = Split::East.half(&"", &"");
|
||||||
/// let _ = Split::West.half(&"", &"");
|
/// let _ = Split::West.half(&"", &"");
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn half <S: Screen, A: Draw<S>, B: Draw<S>> (&self, a: &A, b: &B) -> impl Draw<S> {
|
pub const fn half <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (&self, a: &A, b: &B)
|
||||||
|
-> impl Draw<'a, S>
|
||||||
|
{
|
||||||
draw(move|to: &mut S|{
|
draw(move|to: &mut S|{
|
||||||
let (area_a, area_b) = to.xywh().split_half(self);
|
let (area_a, area_b) = to.xywh().split_half(self);
|
||||||
let (origin_a, origin_b) = self.origins();
|
let (origin_a, origin_b) = self.origins();
|
||||||
|
|
@ -356,28 +401,28 @@ impl Split {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn east <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw<S> {
|
pub const fn east <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (a: A, b: B) -> impl Draw<'a, S> {
|
||||||
Pair(Split::East, a, b, PhantomData)
|
Pair(Split::East, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn north <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw<S> {
|
pub const fn north <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (a: A, b: B) -> impl Draw<'a, S> {
|
||||||
Pair(Split::North, a, b, PhantomData)
|
Pair(Split::North, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn west <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw<S> {
|
pub const fn west <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (a: A, b: B) -> impl Draw<'a, S> {
|
||||||
Pair(Split::West, a, b, PhantomData)
|
Pair(Split::West, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn south <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw<S> {
|
pub const fn south <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (a: A, b: B) -> impl Draw<'a, S> {
|
||||||
Pair(Split::South, a, b, PhantomData)
|
Pair(Split::South, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn above <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw<S> {
|
pub const fn above <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (a: A, b: B) -> impl Draw<'a, S> {
|
||||||
Pair(Split::Above, a, b, PhantomData)
|
Pair(Split::Above, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn below <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw<S> {
|
pub const fn below <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (a: A, b: B) -> impl Draw<'a, S> {
|
||||||
Pair(Split::Below, a, b, PhantomData)
|
Pair(Split::Below, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export] macro_rules! north {
|
#[macro_export] macro_rules! north {
|
||||||
|
|
@ -410,38 +455,6 @@ pub const fn below <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw
|
||||||
($head:expr, $($tail:expr),* $(,)?) => { below($head, below!($($tail,)*)) };
|
($head:expr, $($tail:expr),* $(,)?) => { below($head, below!($($tail,)*)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)] #[test] fn test_stack_areas () -> Usually<()> {
|
|
||||||
let area = XYWH(0u16, 0, 80, 25);
|
|
||||||
|
|
||||||
assert_eq!(stack_areas(&Split::East, &mut Tui::Layout(area), &"foo", &"bar")?, (
|
|
||||||
Some(XYWH(0u16, 0, 3, 1)),
|
|
||||||
Some(XYWH(3u16, 0, 3, 1)),
|
|
||||||
));
|
|
||||||
|
|
||||||
assert_eq!(stack_areas(&Split::South, &mut Tui::Layout(area), &"foo", &"bar")?, (
|
|
||||||
Some(XYWH(0u16, 0, 3, 1)),
|
|
||||||
Some(XYWH(0u16, 1, 3, 1)),
|
|
||||||
));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)] #[test] fn test_split_stack () -> Usually<()> {
|
|
||||||
use Split::*;
|
|
||||||
fn size_of <A: Draw<Tui>, B: Draw<Tui>> (stack: &Pair<Tui, A, B>) -> Perhaps<XYWH<u16>> {
|
|
||||||
Tui::Layout(XYWH(0, 0, 80, 25)).size(None, stack)
|
|
||||||
}
|
|
||||||
assert_eq!(size_of(&split(East, "foo", "bar"))?,
|
|
||||||
Some(XYWH(0, 0, 6, 1)));
|
|
||||||
assert_eq!(size_of(&split(South, "foo", "bar"))?,
|
|
||||||
Some(XYWH(0, 0, 3, 2)));
|
|
||||||
assert_eq!(size_of(&split(South, split(East, "foo", "bar"), "baz"))?,
|
|
||||||
Some(XYWH(0, 0, 6, 2)));
|
|
||||||
assert_eq!(size_of(&split(East, split(South, "foo", "bar"), "baz"))?,
|
|
||||||
Some(XYWH(0, 0, 6, 2)));
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)] #[test] fn test_align () -> Usually<()> {
|
#[cfg(test)] #[test] fn test_align () -> Usually<()> {
|
||||||
let mut screen = Tui::Layout(XYWH(0, 0, 80, 25));
|
let mut screen = Tui::Layout(XYWH(0, 0, 80, 25));
|
||||||
assert_eq!("FOOBAR\nKILROY".draw(&mut screen)?, Some(XYWH(0, 0, 6, 2)));
|
assert_eq!("FOOBAR\nKILROY".draw(&mut screen)?, Some(XYWH(0, 0, 6, 2)));
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
fn_kw_layout!(kw_when |state, output, expr| {
|
fn_kw_layout!(kw_when |state, output, expr| {
|
||||||
Ok(matches!(expr.head()?, Some("when")).then(||{
|
let thunk = draw(move|screen|ok_flat(expr.nth(2)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
when(state.namespace(expr.tail().head())?.unwrap(),
|
ok_flat(matches!(expr.head()?, Some("when")).then(||{
|
||||||
draw(move|output: &mut O|{state.interpret(output, &expr.tail().tail().head())})
|
when(state.namespace(expr.nth(1)?)?.unwrap(), thunk) .draw(output)
|
||||||
).draw(output)
|
}))
|
||||||
}).transpose()?.flatten())
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Only render when condition is true.
|
/// Only render when condition is true.
|
||||||
|
|
@ -16,21 +15,16 @@ fn_kw_layout!(kw_when |state, output, expr| {
|
||||||
/// when(true, "Yes")
|
/// when(true, "Yes")
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn when <T: Screen> (condition: bool, item: impl Draw<T>) -> impl Draw<T> {
|
pub const fn when <'a, T: Screen> (condition: bool, item: impl Draw<'a, T>) -> impl Draw<'a, T> {
|
||||||
draw(move|to: &mut T|if condition { item.draw(to) } else { Ok(Default::default()) })
|
draw(move|to: &mut T|if condition { item.draw(to) } else { Ok(Default::default()) })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn_kw_layout!(kw_either |state, output, expr| {
|
fn_kw_layout!(kw_either |state, output, expr| {
|
||||||
Ok(matches!(expr.head()?, Some("either")).then(||{
|
let thunk_a = draw(move|screen|ok_flat(expr.nth(2)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
either(state.namespace(expr.tail().head()?)?.unwrap(),
|
let thunk_b = draw(move|screen|ok_flat(expr.nth(3)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
draw(move|output: &mut O|{
|
ok_flat(matches!(expr.head()?, Some("either")).then(||{
|
||||||
state.interpret(output, &expr.tail().tail().head()?)
|
either(state.namespace(expr.nth(1)?)?.unwrap(), thunk_a, thunk_b).draw(output)
|
||||||
}),
|
}))
|
||||||
draw(move|output: &mut O|{
|
|
||||||
state.interpret(output, &expr.tail().tail().tail().head()?)
|
|
||||||
}),
|
|
||||||
).draw(output)
|
|
||||||
}).transpose()?.flatten())
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Render one thing if a condition is true and another false.
|
/// Render one thing if a condition is true and another false.
|
||||||
|
|
@ -41,6 +35,8 @@ fn_kw_layout!(kw_either |state, output, expr| {
|
||||||
/// either(true, "Yes", "No")
|
/// either(true, "Yes", "No")
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn either <T: Screen> (condition: bool, a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
pub const fn either <'a, T: Screen> (
|
||||||
|
condition: bool, a: impl Draw<'a, T>, b: impl Draw<'a, T>
|
||||||
|
) -> impl Draw<'a, T> {
|
||||||
draw(move|to: &mut T|if condition { a.draw(to) } else { b.draw(to) })
|
draw(move|to: &mut T|if condition { a.draw(to) } else { b.draw(to) })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn iter_south <'a, S: Screen, D: Draw<S>, I: Iterator<Item = D>> (
|
pub fn iter_south <'a, S: Screen, D: Draw<'a, S>, I: Iterator<Item = D>> (
|
||||||
iter: impl Fn()->I
|
iter: impl Fn()->I
|
||||||
) -> impl Draw<S> {
|
) -> impl Draw<'a, S> {
|
||||||
draw(move|to: &mut S|{
|
draw(move|to: &mut S|{
|
||||||
let XYWH(x, y, w, h) = to.area();
|
let XYWH(x, y, w, h) = to.area();
|
||||||
let mut y_next = y;
|
let mut y_next = y;
|
||||||
|
|
@ -22,9 +22,9 @@ pub fn iter_south <'a, S: Screen, D: Draw<S>, I: Iterator<Item = D>> (
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_east <'a, S: Screen, D: Draw<S>, I: Iterator<Item = D>> (
|
pub fn iter_east <'a, S: Screen, D: Draw<'a, S>, I: Iterator<Item = D>> (
|
||||||
iter: impl Fn()->I
|
iter: impl Fn()->I
|
||||||
) -> impl Draw<S> {
|
) -> impl Draw<'a, S> {
|
||||||
draw(move|to: &mut S|{
|
draw(move|to: &mut S|{
|
||||||
let XYWH(x, y, w, h) = to.area();
|
let XYWH(x, y, w, h) = to.area();
|
||||||
let mut x_next = x;
|
let mut x_next = x;
|
||||||
|
|
@ -45,74 +45,75 @@ pub fn iter_east <'a, S: Screen, D: Draw<S>, I: Iterator<Item = D>> (
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over a collection of the same kind of [Draw]able:
|
/// Iterate over a collection of the same kind of [Draw]able:
|
||||||
pub fn iter <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
pub fn iter <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<'a, S>> (
|
||||||
_iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
_iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
||||||
) -> impl Draw<S> {
|
) -> impl Draw<'a, S> {
|
||||||
draw(move|_to: &mut S|{ todo!() })
|
draw(move|_to: &mut S|{ todo!() })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over a collection of the same kind of [Draw]able:
|
/// Iterate over a collection of the same kind of [Draw]able:
|
||||||
pub fn iter_once <'a, S: Screen, D: 'a, U: Draw<S>> (
|
pub fn iter_once <'a, S: Screen, D: 'a, U: Draw<'a, S>> (
|
||||||
_iter: impl Iterator<Item = D>, _draw: impl Fn(D, usize)->U,
|
_iter: impl Iterator<Item = D>, _draw: impl Fn(D, usize)->U,
|
||||||
) -> impl Draw<S> {
|
) -> impl Draw<'a, S> {
|
||||||
draw(move|_to: &mut S|{ todo!() })
|
draw(move|_to: &mut S|{ todo!() })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over a collection of various [Draw]ables:
|
/// Iterate over a collection of various [Draw]ables:
|
||||||
pub fn iter_dyn <
|
pub fn iter_dyn <
|
||||||
|
'a,
|
||||||
S: Screen, // Target screen
|
S: Screen, // Target screen
|
||||||
D, // Input doesn't need to be [Draw]able, output does
|
D, // Input doesn't need to be [Draw]able, output does
|
||||||
V: Fn()->I, // Function that returns the iterator
|
V: Fn()->I, // Function that returns the iterator
|
||||||
I: Iterator<Item = D>, // Type of the iterator
|
I: Iterator<Item = D>, // Type of the iterator
|
||||||
F: Fn(&D, usize)->dyn Draw<S>, // Function that returns [Draw]able from iterator item
|
F: Fn(&D, usize)->dyn Draw<'a, S>, // Function that returns [Draw]able from iterator item
|
||||||
> (_items: V, _cb: F) -> impl Draw<S> {
|
> (_items: V, _cb: F) -> impl Draw<'a, S> {
|
||||||
draw(move|_to: &mut S|{ todo!() })
|
draw(move|_to: &mut S|{ todo!() })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_north <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
pub fn iter_north <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<'a, S>> (
|
||||||
_iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
_iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
||||||
) -> impl Draw<S> {
|
) -> impl Draw<'a, S> {
|
||||||
draw(move|_to: &mut S|{ todo!() })
|
draw(move|_to: &mut S|{ todo!() })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_east_fixed <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
pub fn iter_east_fixed <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<'a, S>> (
|
||||||
_height: S::Unit, _iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
_height: S::Unit, _iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
||||||
) -> impl Draw<S> {
|
) -> impl Draw<'a, S> {
|
||||||
draw(move|_to: &mut S|{ todo!() })
|
draw(move|_to: &mut S|{ todo!() })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_south_fixed <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
pub fn iter_south_fixed <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<'a, S>> (
|
||||||
_height: S::Unit, _iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
_height: S::Unit, _iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
||||||
) -> impl Draw<S> {
|
) -> impl Draw<'a, S> {
|
||||||
draw(move|_to: &mut S|{ todo!() })
|
draw(move|_to: &mut S|{ todo!() })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_west <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
pub fn iter_west <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<'a, S>> (
|
||||||
_iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
_iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
||||||
) -> impl Draw<S> {
|
) -> impl Draw<'a, S> {
|
||||||
draw(move|_to: &mut S|{ todo!() })
|
draw(move|_to: &mut S|{ todo!() })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn row_south <S: Screen> (south: S::Unit, height: S::Unit, content: impl Draw<S>)
|
pub fn row_south <'a, S: Screen + 'a> (south: S::Unit, height: S::Unit, content: impl Draw<'a, S>)
|
||||||
-> impl Draw<S>
|
-> impl Draw<'a, S>
|
||||||
{
|
{
|
||||||
content.exact_h(height).push_y(south)
|
content.exact_h(height).push_y(south)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn row_north <S: Screen> (north: S::Unit, height: S::Unit, content: impl Draw<S>)
|
pub fn row_north <'a, S: Screen + 'a> (north: S::Unit, height: S::Unit, content: impl Draw<'a, S>)
|
||||||
-> impl Draw<S>
|
-> impl Draw<'a, S>
|
||||||
{
|
{
|
||||||
content.exact_h(height).pull_y(north)
|
content.exact_h(height).pull_y(north)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn col_east <S: Screen> (east: S::Unit, width: S::Unit, content: impl Draw<S>)
|
pub fn col_east <'a, S: Screen + 'a> (east: S::Unit, width: S::Unit, content: impl Draw<'a, S>)
|
||||||
-> impl Draw<S>
|
-> impl Draw<'a, S>
|
||||||
{
|
{
|
||||||
content.exact_w(width).push_x(east)
|
content.exact_w(width).push_x(east)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn col_west <S: Screen> (west: S::Unit, width: S::Unit, content: impl Draw<S>)
|
pub fn col_west <'a, S: Screen + 'a> (west: S::Unit, width: S::Unit, content: impl Draw<'a, S>)
|
||||||
-> impl Draw<S>
|
-> impl Draw<'a, S>
|
||||||
{
|
{
|
||||||
content.exact_w(width).pull_x(west)
|
content.exact_w(width).pull_x(west)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
91
src/lib.rs
91
src/lib.rs
|
|
@ -1265,17 +1265,17 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
|
||||||
draw: &impl Fn(&mut Self)->T
|
draw: &impl Fn(&mut Self)->T
|
||||||
) -> T;
|
) -> T;
|
||||||
/// Determine used area without drawing
|
/// Determine used area without drawing
|
||||||
fn size (
|
fn size <'a> (
|
||||||
&mut self,
|
&mut self,
|
||||||
area: impl Into<Option<XYWH<Self::Unit>>>,
|
area: impl Into<Option<XYWH<Self::Unit>>>,
|
||||||
draw: impl Draw<Self>
|
draw: impl Draw<'a, Self>
|
||||||
) -> Perhaps<XYWH<Self::Unit>>;
|
) -> Drawn<'a, Self::Unit>;
|
||||||
/// Draw
|
/// Draw
|
||||||
fn draw (
|
fn draw <'a> (
|
||||||
&mut self,
|
&mut self,
|
||||||
area: impl Into<Option<XYWH<Self::Unit>>>,
|
area: impl Into<Option<XYWH<Self::Unit>>>,
|
||||||
draw: impl Draw<Self>
|
draw: impl Draw<'a, Self>
|
||||||
) -> Perhaps<XYWH<Self::Unit>>;
|
) -> Drawn<'a, Self::Unit>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implement the [Draw] trait for a particular drawable and [Screen].
|
/// Implement the [Draw] trait for a particular drawable and [Screen].
|
||||||
|
|
@ -1290,7 +1290,7 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
|
||||||
#[macro_export] macro_rules! impl_draw (
|
#[macro_export] macro_rules! impl_draw (
|
||||||
($(<$($T:ident: $Trait:path,)+>)?|
|
($(<$($T:ident: $Trait:path,)+>)?|
|
||||||
$self:ident:$Self:path, $to:ident:$To:ty
|
$self:ident:$Self:path, $to:ident:$To:ty
|
||||||
|$draw:block)=>{ impl$(<$($T:$Trait),+>)? Draw<$To> for $Self {
|
|$draw:block)=>{ impl$(<$($T:$Trait),+>)? Draw<'_, $To> for $Self {
|
||||||
fn draw (&$self, $to: &mut $To) -> Perhaps<XYWH<<$To as Screen>::Unit>> $draw
|
fn draw (&$self, $to: &mut $To) -> Perhaps<XYWH<<$To as Screen>::Unit>> $draw
|
||||||
} };
|
} };
|
||||||
($(<$($T:ident: $Trait:path,)+>)?|
|
($(<$($T:ident: $Trait:path,)+>)?|
|
||||||
|
|
@ -1321,8 +1321,8 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub trait Draw<S: Screen> {
|
pub trait Draw<'a, S: Screen> {
|
||||||
fn draw (&self, to: &mut S) -> Drawn<S::Unit>;
|
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit a [Draw]able.
|
/// Emit a [Draw]able.
|
||||||
|
|
@ -1345,14 +1345,14 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
|
||||||
/// let _ = view::<Tui, _, _>(||"drawable");
|
/// let _ = view::<Tui, _, _>(||"drawable");
|
||||||
/// let _ = view::<Tui, _, _>(||Some("drawable"));
|
/// let _ = view::<Tui, _, _>(||Some("drawable"));
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn view <S: Screen, T: Draw<S>, F: Fn()->T> (view: F) -> impl View<S> {
|
pub const fn view <S: Screen, T: for<'a> Draw<'a, S>, F: Fn()->T> (view: F) -> impl View<S> {
|
||||||
ViewThunk(view, PhantomData)
|
ViewThunk(view, PhantomData)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Because we can't implement [Draw] for `F: FnOnce...` without conflicts.
|
/// Because we can't implement [Draw] for `F: FnOnce...` without conflicts.
|
||||||
pub struct ViewThunk<S: Screen, F>(pub F, std::marker::PhantomData<S>);
|
pub struct ViewThunk<S: Screen, F>(pub F, std::marker::PhantomData<S>);
|
||||||
|
|
||||||
impl<S: Screen, T: Draw<S>, F: Fn()->T> View<S> for ViewThunk<S, F> {
|
impl<S: Screen, T: for<'a> Draw<'a, S>, F: Fn()->T> View<S> for ViewThunk<S, F> {
|
||||||
fn view (&self) -> impl Draw<S> {
|
fn view (&self) -> impl Draw<S> {
|
||||||
self.0()
|
self.0()
|
||||||
}
|
}
|
||||||
|
|
@ -1361,8 +1361,8 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
|
||||||
/// Because we can't implement [Draw] for `F: FnOnce...` without conflicts.
|
/// Because we can't implement [Draw] for `F: FnOnce...` without conflicts.
|
||||||
pub struct DrawThunk<S: Screen, F>(pub F, std::marker::PhantomData<S>);
|
pub struct DrawThunk<S: Screen, F>(pub F, std::marker::PhantomData<S>);
|
||||||
|
|
||||||
impl<T: Screen, F: Fn(&mut T)->Perhaps<XYWH<T::Unit>>> Draw<T> for DrawThunk<T, F> {
|
impl<'a, T: Screen, F: Fn(&mut T)->PerhapsRef<'a, XYWH<T::Unit>>> Draw<'a, T> for DrawThunk<T, F> {
|
||||||
fn draw (&self, to: &mut T) -> Perhaps<XYWH<T::Unit>> {
|
fn draw (&self, to: &mut T) -> PerhapsRef<'a, XYWH<T::Unit>> {
|
||||||
to.clip(None, &self.0)
|
to.clip(None, &self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1373,23 +1373,25 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
|
||||||
/// # use tengri::*;
|
/// # use tengri::*;
|
||||||
/// let _ = draw(|to: &mut Tui|Ok(Some(to.area()))); // draws nothing
|
/// let _ = draw(|to: &mut Tui|Ok(Some(to.area()))); // draws nothing
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn draw <T: Screen, F: Fn(&mut T)->Perhaps<XYWH<T::Unit>>> (
|
pub const fn draw <'a, T: Screen, F: Fn(&mut T)->PerhapsRef<'a, XYWH<T::Unit>>> (
|
||||||
item: F
|
item: F
|
||||||
) -> DrawThunk<T, F> {
|
) -> DrawThunk<T, F> {
|
||||||
DrawThunk(item, std::marker::PhantomData)
|
DrawThunk(item, std::marker::PhantomData)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Drawn<U> = Perhaps<XYWH<U>>;
|
pub type Drawn<'a, U> = PerhapsRef<'a, XYWH<U>>;
|
||||||
|
|
||||||
impl<S: Screen> Draw<S> for () {
|
impl<'a, S: Screen> Draw<'a, S> for () {
|
||||||
fn draw (&self, _: &mut S) -> Drawn<S::Unit> {
|
fn draw (&self, _: &mut S) -> Drawn<'a, S::Unit> {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_draw!(<S: Screen, D: Draw<S>,>|self: Option<D>, to: S|{
|
impl<'a, S: Screen, D: Draw<'a, S>> Draw<'a, S> for Option<D> {
|
||||||
self.as_ref().map(|it|it.draw(to)).transpose().map(Option::unwrap_or_default)
|
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||||
});
|
self.as_ref().map(|it|it.draw(to)).transpose().map(Option::unwrap_or_default)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//impl<S: Screen, D: Draw<S>> Draw<S> for RwLock<D> {
|
//impl<S: Screen, D: Draw<S>> Draw<S> for RwLock<D> {
|
||||||
//fn draw (&self, __: &mut S) -> Drawn<S::Unit> {
|
//fn draw (&self, __: &mut S) -> Drawn<S::Unit> {
|
||||||
|
|
@ -1403,8 +1405,8 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
|
|
||||||
impl<T: Screen, V: Draw<T>> Draw<T> for &V {
|
impl<'a, T: Screen, V: Draw<'a, T>> Draw<'a, T> for &V {
|
||||||
fn draw (&self, to: &mut T) -> Perhaps<XYWH<T::Unit>> {
|
fn draw (&self, to: &mut T) -> Drawn<'a, T::Unit> {
|
||||||
(*self).draw(to)
|
(*self).draw(to)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1717,7 +1719,7 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
|
||||||
|
|
||||||
impl ItemTheme {
|
impl ItemTheme {
|
||||||
#[cfg(feature = "term")] pub const G: [Self;256] = {
|
#[cfg(feature = "term")] pub const G: [Self;256] = {
|
||||||
let mut builder = dizzle::konst::array::ArrayBuilder::new();
|
let mut builder = ::konst::array::ArrayBuilder::new();
|
||||||
while !builder.is_full() {
|
while !builder.is_full() {
|
||||||
let index = builder.len() as u8;
|
let index = builder.len() as u8;
|
||||||
let light = (index as f64 * 1.15) as u8;
|
let light = (index as f64 * 1.15) as u8;
|
||||||
|
|
@ -1788,23 +1790,26 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ColorDsl<T>: Sized {
|
pub trait ColorDsl<'a, T>: Sized {
|
||||||
fn new_g (expr: T, try_to_u8: impl Fn(Perhaps<&str>)->Perhaps<u8>) -> Usually<Self>;
|
fn new_g (expr: &'a T, try_to_u8: impl Fn(PerhapsRef<'a, &'a str>)->PerhapsRef<'a, u8>)
|
||||||
fn new_rgb (expr: T, try_to_u8: impl Fn(Perhaps<&str>)->Perhaps<u8>) -> Usually<Self>;
|
-> UsuallyRef<'a, Self>;
|
||||||
|
fn new_rgb (expr: &'a T, try_to_u8: impl Fn(PerhapsRef<'a, &str>)->PerhapsRef<'a, u8>)
|
||||||
|
-> UsuallyRef<'a, Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Expression> ColorDsl<T> for Color {
|
impl<'a, T: Language<'a> + 'a> ColorDsl<'a, T> for Color {
|
||||||
fn new_g (expr: T, try_to_u8: impl Fn(Perhaps<&str>)->Perhaps<u8>) -> Usually<Self> {
|
fn new_g (expr: &'a T, try_to_u8: impl Fn(PerhapsRef<'a, &'a str>)->PerhapsRef<'a, u8>)
|
||||||
|
-> Result<Self, Box<dyn Error + 'a>>
|
||||||
|
{
|
||||||
let n = try_to_u8(expr.tail().map_err(Into::into))?.ok_or(Domain("not gray"))?;
|
let n = try_to_u8(expr.tail().map_err(Into::into))?.ok_or(Domain("not gray"))?;
|
||||||
Ok(Self::Rgb(n, n, n))
|
Ok(Self::Rgb(n, n, n))
|
||||||
}
|
}
|
||||||
fn new_rgb (expr: T, try_to_u8: impl Fn(Perhaps<&str>)->Perhaps<u8>) -> Usually<Self> {
|
fn new_rgb (expr: &'a T, try_to_u8: impl Fn(PerhapsRef<'a, &str>)->PerhapsRef<'a, u8>)
|
||||||
let r = try_to_u8(expr.tail().map_err(Into::into))?
|
-> Result<Self, Box<dyn Error + 'a>>
|
||||||
.ok_or(Domain("not red"))?;
|
{
|
||||||
let g = try_to_u8(expr.tail().tail().head().map_err(Into::into))?
|
let r = try_to_u8(expr.nth(1).map_err(Into::into))?.ok_or(Domain("not red"))?;
|
||||||
.ok_or(Domain("not green"))?;
|
let g = try_to_u8(expr.nth(2).map_err(Into::into))?.ok_or(Domain("not green"))?;
|
||||||
let b = try_to_u8(expr.tail().tail().tail().head().map_err(Into::into))?
|
let b = try_to_u8(expr.nth(3).map_err(Into::into))?.ok_or(Domain("not blue"))?;
|
||||||
.ok_or(Domain("not blue"))?;
|
|
||||||
Ok(Color::Rgb(r, g, b))
|
Ok(Color::Rgb(r, g, b))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1902,7 +1907,7 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// impl Interpret<Tui, Option<XYWH<u16>>> for App {
|
/// impl Interpret<Tui, Option<XYWH<u16>>> for App {
|
||||||
/// fn interpret_expr <'a> (&'a self, to: &mut Tui, lang: &'a impl Expression)
|
/// fn interpret_expr <'a> (&'a self, to: &mut Tui, lang: &'a impl Language)
|
||||||
/// -> Usually<Option<XYWH<u16>>>
|
/// -> Usually<Option<XYWH<u16>>>
|
||||||
/// {
|
/// {
|
||||||
/// self.keyword(to, lang)
|
/// self.keyword(to, lang)
|
||||||
|
|
@ -1931,7 +1936,7 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
|
||||||
/// ```
|
/// ```
|
||||||
pub trait Keywords <U, V>: 'static {
|
pub trait Keywords <U, V>: 'static {
|
||||||
fn keywords () -> impl Iterator<Item = fn(&Self, &mut U, &str) -> Perhaps<V>>;
|
fn keywords () -> impl Iterator<Item = fn(&Self, &mut U, &str) -> Perhaps<V>>;
|
||||||
fn keyword (&self, to: &mut U, expr: &impl Expression) -> Perhaps<V> {
|
fn keyword <'a> (&self, to: &mut U, expr: &'a impl Language<'a>) -> PerhapsRef<'a, V> {
|
||||||
if let Some(expr) = expr.src()? {
|
if let Some(expr) = expr.src()? {
|
||||||
for keyword in Self::keywords() {
|
for keyword in Self::keywords() {
|
||||||
if let Some(result) = keyword(self, to, &expr)? {
|
if let Some(result) = keyword(self, to, &expr)? {
|
||||||
|
|
@ -1954,17 +1959,5 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invalid_variant <T> (
|
|
||||||
name: &str,
|
|
||||||
frag: impl Language,
|
|
||||||
expr: impl Language,
|
|
||||||
head: impl Language,
|
|
||||||
) -> Usually<T> {
|
|
||||||
unimplemented!(
|
|
||||||
"{name}/{frag:?} ({expr:?}) ({head:?}) ({:?})",
|
|
||||||
head.src()?.unwrap_or_default().split("/").next()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "term")] pub use self::term::*;
|
#[cfg(feature = "term")] pub use self::term::*;
|
||||||
#[cfg(feature = "term")] mod term;
|
#[cfg(feature = "term")] mod term;
|
||||||
|
|
|
||||||
47
src/term.rs
47
src/term.rs
|
|
@ -96,14 +96,14 @@ impl Screen for Tui {
|
||||||
fn area (&self) -> XYWH<Self::Unit> {
|
fn area (&self) -> XYWH<Self::Unit> {
|
||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
fn size (
|
fn size <'a> (
|
||||||
&mut self, area: impl Into<Option<XYWH<u16>>>, draw: impl Draw<Self>,
|
&mut self, area: impl Into<Option<XYWH<u16>>>, draw: impl Draw<'a, Self>,
|
||||||
) -> Perhaps<XYWH<Self::Unit>> {
|
) -> Drawn<'a, Self::Unit> {
|
||||||
Self::Layout(self.area()).clip(area, &|to|draw.draw(to))
|
Self::Layout(self.area()).clip(area, &|to|draw.draw(to))
|
||||||
}
|
}
|
||||||
fn draw (
|
fn draw <'a> (
|
||||||
&mut self, area: impl Into<Option<XYWH<u16>>>, draw: impl Draw<Tui>
|
&mut self, area: impl Into<Option<XYWH<u16>>>, draw: impl Draw<'a, Tui>
|
||||||
) -> Perhaps<XYWH<Self::Unit>> {
|
) -> Drawn<'a, Self::Unit> {
|
||||||
self.clip(area, &|to|draw.draw(to))
|
self.clip(area, &|to|draw.draw(to))
|
||||||
}
|
}
|
||||||
fn clip <T> (
|
fn clip <T> (
|
||||||
|
|
@ -289,7 +289,7 @@ impl Tui {
|
||||||
/// let _ = tengri::Tui::catcher(&variant);
|
/// let _ = tengri::Tui::catcher(&variant);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn catcher <T: Draw<Tui>> (result: &Usually<T>) -> impl Draw<Tui> {
|
pub fn catcher <'a, T: Draw<'a, Tui>> (result: &Usually<T>) -> impl Draw<'a, Tui> {
|
||||||
draw(move|to: &mut Tui|match result {
|
draw(move|to: &mut Tui|match result {
|
||||||
Ok(content) => content.draw(to),
|
Ok(content) => content.draw(to),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
@ -369,7 +369,7 @@ impl<'a: 'b, 'b> From<&'a mut Tui> for &'b mut XYWH<u16> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn fill_char (c: char) -> impl Draw<Tui> {
|
pub const fn fill_char <'a> (c: char) -> impl Draw<'a, Tui> {
|
||||||
draw(move|to: &mut Tui|Ok(Some(to.update(&|cell,_,_|{
|
draw(move|to: &mut Tui|Ok(Some(to.update(&|cell,_,_|{
|
||||||
cell.set_char(c);
|
cell.set_char(c);
|
||||||
}))))
|
}))))
|
||||||
|
|
@ -378,8 +378,8 @@ pub const fn fill_char (c: char) -> impl Draw<Tui> {
|
||||||
/// FIXME: Don't use `format!` but implement number blitting
|
/// FIXME: Don't use `format!` but implement number blitting
|
||||||
pub struct ShowSize;
|
pub struct ShowSize;
|
||||||
|
|
||||||
impl Draw<Tui> for ShowSize {
|
impl<'a> Draw<'a, Tui> for ShowSize {
|
||||||
fn draw (&self, to: &mut Tui) -> Drawn<u16> {
|
fn draw (&self, to: &mut Tui) -> Drawn<'a, u16> {
|
||||||
let area = to.area();
|
let area = to.area();
|
||||||
let info = format!("{area:?}");
|
let info = format!("{area:?}");
|
||||||
to.text(&info, area.0, area.1, info.len() as u16)
|
to.text(&info, area.0, area.1, info.len() as u16)
|
||||||
|
|
@ -388,8 +388,8 @@ impl Draw<Tui> for ShowSize {
|
||||||
|
|
||||||
pub struct ShowSizeOf<T>(pub T);
|
pub struct ShowSizeOf<T>(pub T);
|
||||||
|
|
||||||
impl<T: Draw<Tui>> Draw<Tui> for ShowSizeOf<T> {
|
impl<'a, T: Draw<'a, Tui>> Draw<'a, Tui> for ShowSizeOf<T> {
|
||||||
fn draw (&self, to: &mut Tui) -> Drawn<u16> {
|
fn draw (&self, to: &mut Tui) -> Drawn<'a, u16> {
|
||||||
Ok(self.0.draw(to)?.map(|used|{
|
Ok(self.0.draw(to)?.map(|used|{
|
||||||
let _ = to.text(&format!("{used:?}"), used.0, used.1, u16::MAX);
|
let _ = to.text(&format!("{used:?}"), used.0, used.1, u16::MAX);
|
||||||
used
|
used
|
||||||
|
|
@ -398,13 +398,14 @@ impl<T: Draw<Tui>> Draw<Tui> for ShowSizeOf<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "eval")] fn_kw_layout_tui!(kw_tui_text |_state, output, expr| {
|
#[cfg(feature = "eval")] fn_kw_layout_tui!(kw_tui_text |_state, output, expr| {
|
||||||
Ok(matches!(expr.head()?, Some("text")).then(||{
|
Ok(if matches!(expr.head()?, Some("text")) {
|
||||||
if let Some(src) = expr.tail().src()? && src.len() > 0 {
|
expr.tail()?
|
||||||
(&src[1..]).draw(output)
|
.and_then(|src|(src.len() > 0).then(||(&src[1..]).draw(output)))
|
||||||
} else {
|
.transpose()?
|
||||||
return Ok(None)
|
.flatten()
|
||||||
}
|
} else {
|
||||||
}).transpose()?.flatten())
|
None
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
#[cfg(feature = "text")] pub use self::tui_text::*;
|
#[cfg(feature = "text")] pub use self::tui_text::*;
|
||||||
|
|
@ -473,8 +474,8 @@ impl<T: Draw<Tui>> Draw<Tui> for ShowSizeOf<T> {
|
||||||
self.as_ref().draw(to)
|
self.as_ref().draw(to)
|
||||||
});
|
});
|
||||||
|
|
||||||
impl Draw<Tui> for &str {
|
impl<'a> Draw<'a, Tui> for &str {
|
||||||
fn draw (&self, to: &mut Tui) -> Drawn<u16> {
|
fn draw (&self, to: &mut Tui) -> Drawn<'a, u16> {
|
||||||
let XYWH(x, y, w, h) = to.area();
|
let XYWH(x, y, w, h) = to.area();
|
||||||
let mut max_w = 0u16;
|
let mut max_w = 0u16;
|
||||||
let mut max_h = 0u16;
|
let mut max_h = 0u16;
|
||||||
|
|
@ -493,8 +494,8 @@ impl<T: Draw<Tui>> Draw<Tui> for ShowSizeOf<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'t, T: AsRef<str>> Draw<Tui> for TrimStr<'_, T> {
|
impl<'a, T: AsRef<str>> Draw<'a, Tui> for TrimStr<'a, T> {
|
||||||
fn draw (&self, to: &mut Tui) -> Drawn<u16> {
|
fn draw (&self, to: &mut Tui) -> Drawn<'a, u16> {
|
||||||
let text = self.1.as_ref();
|
let text = self.1.as_ref();
|
||||||
let area = layout_text_u16(text, to.area())?.unwrap();
|
let area = layout_text_u16(text, to.area())?.unwrap();
|
||||||
let XYWH(x, y, w, ..) = to.area();
|
let XYWH(x, y, w, ..) = to.area();
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,9 @@ use crate::*;
|
||||||
/// ```
|
/// ```
|
||||||
/// /// TODO
|
/// /// TODO
|
||||||
/// ```
|
/// ```
|
||||||
pub fn border (on: bool, style: impl BorderStyle, item: impl Draw<Tui>) -> impl Draw<Tui> {
|
pub fn border <'a> (
|
||||||
|
on: bool, style: impl BorderStyle<'a>, item: impl Draw<'a, Tui>
|
||||||
|
) -> impl Draw<'a, Tui> {
|
||||||
let content = item.pad_wh(1, 1);
|
let content = item.pad_wh(1, 1);
|
||||||
let outline = when(on, draw(move|to: &mut Tui|{
|
let outline = when(on, draw(move|to: &mut Tui|{
|
||||||
let XYWH(x, y, w, h) = to.area();
|
let XYWH(x, y, w, h) = to.area();
|
||||||
|
|
@ -33,7 +35,7 @@ macro_rules! border {
|
||||||
$nw:literal $n:literal $ne:literal $w:literal $e:literal $sw:literal $s:literal $se:literal
|
$nw:literal $n:literal $ne:literal $w:literal $e:literal $sw:literal $s:literal $se:literal
|
||||||
$($x:tt)*
|
$($x:tt)*
|
||||||
}),+) => {$(
|
}),+) => {$(
|
||||||
impl BorderStyle for $T {
|
impl<'a> BorderStyle<'a> for $T {
|
||||||
const NW: &'static str = $nw;
|
const NW: &'static str = $nw;
|
||||||
const N: &'static str = $n;
|
const N: &'static str = $n;
|
||||||
const NE: &'static str = $ne;
|
const NE: &'static str = $ne;
|
||||||
|
|
@ -47,7 +49,7 @@ macro_rules! border {
|
||||||
}
|
}
|
||||||
#[derive(Copy, Clone)] pub struct $T(pub bool, pub Style);
|
#[derive(Copy, Clone)] pub struct $T(pub bool, pub Style);
|
||||||
//impl Layout<Tui> for $T {}
|
//impl Layout<Tui> for $T {}
|
||||||
impl Draw<Tui> for $T {
|
impl<'a> Draw<'a, Tui> for $T {
|
||||||
fn draw (&self, to: &mut Tui) -> Perhaps<XYWH<u16>> {
|
fn draw (&self, to: &mut Tui) -> Perhaps<XYWH<u16>> {
|
||||||
when(self.enabled(), draw(|to: &mut Tui|BorderStyle::draw(*self, to).map(Some))).draw(to)
|
when(self.enabled(), draw(|to: &mut Tui|BorderStyle::draw(*self, to).map(Some))).draw(to)
|
||||||
}
|
}
|
||||||
|
|
@ -161,7 +163,7 @@ border! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BorderStyle: Draw<Tui> + Copy {
|
pub trait BorderStyle<'a>: Draw<'a, Tui> + Copy {
|
||||||
fn enabled (&self) -> bool;
|
fn enabled (&self) -> bool;
|
||||||
fn border_n (&self) -> &str { Self::N }
|
fn border_n (&self) -> &str { Self::N }
|
||||||
fn border_s (&self) -> &str { Self::S }
|
fn border_s (&self) -> &str { Self::S }
|
||||||
|
|
@ -172,7 +174,7 @@ pub trait BorderStyle: Draw<Tui> + Copy {
|
||||||
fn border_sw (&self) -> &str { Self::SW }
|
fn border_sw (&self) -> &str { Self::SW }
|
||||||
fn border_se (&self) -> &str { Self::SE }
|
fn border_se (&self) -> &str { Self::SE }
|
||||||
|
|
||||||
#[inline] fn draw <'a> (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
#[inline] fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
||||||
if self.enabled() {
|
if self.enabled() {
|
||||||
self.draw_h(to, None)?;
|
self.draw_h(to, None)?;
|
||||||
self.draw_v(to, None)?;
|
self.draw_v(to, None)?;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use ::dizzle::{Language, Symbol, Usually};
|
use ::dizzle::*;
|
||||||
use ::crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState};
|
use ::crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState};
|
||||||
|
|
||||||
/// TUI key spec.
|
/// TUI key spec.
|
||||||
|
|
@ -70,7 +70,7 @@ impl TuiKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "lang")]
|
#[cfg(feature = "lang")]
|
||||||
pub fn from_dsl (dsl: impl Language) -> Usually<Self> {
|
pub fn from_dsl <'a> (dsl: &'a impl Language<'a>) -> UsuallyRef<'a, Self> {
|
||||||
if let Some(word) = dsl.word()? {
|
if let Some(word) = dsl.word()? {
|
||||||
let word = word.trim();
|
let word = word.trim();
|
||||||
Ok(if word == ":char" {
|
Ok(if word == ":char" {
|
||||||
|
|
|
||||||
|
|
@ -2,36 +2,30 @@ use crate::*;
|
||||||
use Color::*;
|
use Color::*;
|
||||||
|
|
||||||
fn_kw_layout_tui!(kw_tui_fg |state, output, expr| {
|
fn_kw_layout_tui!(kw_tui_fg |state, output, expr| {
|
||||||
|
let thunk = draw(move|screen|ok_flat(expr.nth(2)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
Ok(matches!(expr.head()?, Some("fg")).then(||{
|
Ok(matches!(expr.head()?, Some("fg")).then(||{
|
||||||
let args = expr.tail();
|
if let Some(color) = state.namespace(expr.nth(1)?.expect("fg: expected arg 0 (color)"))? {
|
||||||
let arg0 = args.head();
|
fg(color, thunk).draw(output)
|
||||||
let tail0 = args.tail();
|
|
||||||
let arg1 = tail0.head();
|
|
||||||
if let Some(color) = state.namespace(arg0?.expect("fg: expected arg 0 (color)"))? {
|
|
||||||
fg(color, draw(move|to: &mut Tui|state.interpret(to, &arg1))).draw(output)
|
|
||||||
} else {
|
} else {
|
||||||
return Err(format!("fg: {arg0:?}: not a color").into())
|
return Err(format!("fg: {:?}: not a color", expr.nth(1)).into())
|
||||||
}
|
}
|
||||||
}).transpose()?.flatten())
|
}).transpose()?.flatten())
|
||||||
});
|
});
|
||||||
|
|
||||||
fn_kw_layout_tui!(kw_tui_bg |state, output, expr| {
|
fn_kw_layout_tui!(kw_tui_bg |state, output, expr| {
|
||||||
|
let thunk = draw(move|screen|ok_flat(expr.nth(2)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||||
Ok(matches!(expr.head()?, Some("bg")).then(||{
|
Ok(matches!(expr.head()?, Some("bg")).then(||{
|
||||||
let args = expr.tail();
|
if let Some(color) = state.namespace(expr.nth(1)?.expect("bg: expected arg 0 (color)"))? {
|
||||||
let arg0 = args.head();
|
bg(color, thunk).draw(output)
|
||||||
let tail0 = args.tail();
|
|
||||||
let arg1 = tail0.head();
|
|
||||||
if let Some(color) = state.namespace(arg0?.expect("bg: expected arg 0 (color)"))? {
|
|
||||||
bg(color, draw(move|to: &mut Tui|state.interpret(to, &arg1))).draw(output)
|
|
||||||
} else {
|
} else {
|
||||||
return Err(format!("bg: {arg0:?}: not a color").into())
|
return Err(format!("bg: {:?}: not a color", expr.nth(1)?).into())
|
||||||
}
|
}
|
||||||
}).transpose()?.flatten())
|
}).transpose()?.flatten())
|
||||||
});
|
});
|
||||||
|
|
||||||
impl Tui {
|
impl Tui {
|
||||||
pub fn eval_color_expr (state: &impl Namespace<u8>, src: impl Language)
|
pub fn eval_color_expr <'a> (state: &impl Namespace<u8>, src: &'a impl Language<'a>)
|
||||||
-> Perhaps<Color>
|
-> Result<Option<Color>, Box<dyn Error + 'a>>
|
||||||
{
|
{
|
||||||
if let Some(expr) = src.expr()? {
|
if let Some(expr) = src.expr()? {
|
||||||
match (expr.head()?, expr.tail()?) {
|
match (expr.head()?, expr.tail()?) {
|
||||||
|
|
@ -63,7 +57,9 @@ impl Tui {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply foreground color.
|
/// Apply foreground color.
|
||||||
pub const fn fg (fg: Color, item: impl Draw<Tui>) -> impl Draw<Tui> {
|
pub const fn fg <'a> (fg: Color, item: impl Draw<'a, Tui>)
|
||||||
|
-> impl Draw<'a, Tui>
|
||||||
|
{
|
||||||
draw(move|to: &mut Tui|{
|
draw(move|to: &mut Tui|{
|
||||||
if let Some(size) = to.size(None, &item)? {
|
if let Some(size) = to.size(None, &item)? {
|
||||||
to.draw(Some(size), draw(|to: &mut Tui|{
|
to.draw(Some(size), draw(|to: &mut Tui|{
|
||||||
|
|
@ -77,7 +73,9 @@ pub const fn fg (fg: Color, item: impl Draw<Tui>) -> impl Draw<Tui> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply background color.
|
/// Apply background color.
|
||||||
pub const fn bg (bg: Color, item: impl Draw<Tui>) -> impl Draw<Tui> {
|
pub const fn bg <'a> (bg: Color, item: impl Draw<'a, Tui>)
|
||||||
|
-> impl Draw<'a, Tui>
|
||||||
|
{
|
||||||
draw(move|to: &mut Tui|{
|
draw(move|to: &mut Tui|{
|
||||||
if let Some(size) = to.size(None, &item)? {
|
if let Some(size) = to.size(None, &item)? {
|
||||||
let _ = to.draw(Some(size), draw(|to: &mut Tui|{
|
let _ = to.draw(Some(size), draw(|to: &mut Tui|{
|
||||||
|
|
@ -90,7 +88,9 @@ pub const fn bg (bg: Color, item: impl Draw<Tui>) -> impl Draw<Tui> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn fg_bg (fg: Color, bg: Color, item: impl Draw<Tui>) -> impl Draw<Tui> {
|
pub const fn fg_bg <'a> (fg: Color, bg: Color, item: impl Draw<'a, Tui>)
|
||||||
|
-> impl Draw<'a, Tui>
|
||||||
|
{
|
||||||
draw(move|to: &mut Tui|{
|
draw(move|to: &mut Tui|{
|
||||||
if let Some(size) = to.size(None, &item)? {
|
if let Some(size) = to.size(None, &item)? {
|
||||||
let _ = to.draw(Some(size), draw(|to: &mut Tui|{
|
let _ = to.draw(Some(size), draw(|to: &mut Tui|{
|
||||||
|
|
@ -104,14 +104,16 @@ pub const fn fg_bg (fg: Color, bg: Color, item: impl Draw<Tui>) -> impl Draw<Tui
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw contents with modifier applied.
|
/// Draw contents with modifier applied.
|
||||||
pub const fn modify (on: bool, modifier: Modifier, item: impl Draw<Tui>) -> impl Draw<Tui> {
|
pub const fn modify <'a> (on: bool, modifier: Modifier, item: impl Draw<'a, Tui>)
|
||||||
|
-> impl Draw<'a, Tui>
|
||||||
|
{
|
||||||
draw(move|to: &mut Tui|{
|
draw(move|to: &mut Tui|{
|
||||||
fill_mod(on, modifier).draw(to)?;
|
fill_mod(on, modifier).draw(to)?;
|
||||||
item.draw(to)
|
item.draw(to)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn fill_mod (on: bool, modifier: Modifier) -> impl Draw<Tui> {
|
pub const fn fill_mod <'a> (on: bool, modifier: Modifier) -> impl Draw<'a, Tui> {
|
||||||
draw(move|to: &mut Tui|Ok(Some({
|
draw(move|to: &mut Tui|Ok(Some({
|
||||||
if on {
|
if on {
|
||||||
to.update(&|cell,_,_|cell.modifier.insert(modifier))
|
to.update(&|cell,_,_|cell.modifier.insert(modifier))
|
||||||
|
|
@ -122,11 +124,11 @@ pub const fn fill_mod (on: bool, modifier: Modifier) -> impl Draw<Tui> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw contents with bold modifier applied.
|
/// Draw contents with bold modifier applied.
|
||||||
pub const fn bold (on: bool, item: impl Draw<Tui>) -> impl Draw<Tui> {
|
pub const fn bold <'a> (on: bool, item: impl Draw<'a, Tui>) -> impl Draw<'a, Tui> {
|
||||||
modify(on, Modifier::BOLD, item)
|
modify(on, Modifier::BOLD, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn fill_ul (color: Option<Color>) -> impl Draw<Tui> {
|
pub const fn fill_ul <'a> (color: Option<Color>) -> impl Draw<'a, Tui> {
|
||||||
draw(move|to: &mut Tui|Ok(Some(if let Some(color) = color {
|
draw(move|to: &mut Tui|Ok(Some(if let Some(color) = color {
|
||||||
to.update(&|cell,_,_|{
|
to.update(&|cell,_,_|{
|
||||||
cell.modifier.insert(Modifier::UNDERLINED);
|
cell.modifier.insert(Modifier::UNDERLINED);
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,9 @@ use crate::*;
|
||||||
/// ```
|
/// ```
|
||||||
/// /// TODO
|
/// /// TODO
|
||||||
/// ```
|
/// ```
|
||||||
pub fn phat (w: u16, h: u16, [fg, bg, hi, lo]: [Color;4], draw: impl Draw<Tui>) -> impl Draw<Tui> {
|
pub fn phat <'a> (
|
||||||
|
w: u16, h: u16, [fg, bg, hi, lo]: [Color;4], draw: impl Draw<'a, Tui>
|
||||||
|
) -> impl Draw<'a, Tui> {
|
||||||
let top = phat_lo(bg, hi).exact_h(1);
|
let top = phat_lo(bg, hi).exact_h(1);
|
||||||
let low = phat_hi(bg, lo).exact_h(1);
|
let low = phat_hi(bg, lo).exact_h(1);
|
||||||
let draw = fg_bg(fg, bg, draw);
|
let draw = fg_bg(fg, bg, draw);
|
||||||
|
|
@ -17,11 +19,11 @@ pub const LO: &'static str = "▄";
|
||||||
pub const HI: &'static str = "▀";
|
pub const HI: &'static str = "▀";
|
||||||
|
|
||||||
/// A phat line
|
/// A phat line
|
||||||
fn phat_lo (fg: Color, bg: Color) -> impl Draw<Tui> {
|
fn phat_lo <'a> (fg: Color, bg: Color) -> impl Draw<'a, Tui> {
|
||||||
fg_bg(fg, bg, x_repeat(LO)).exact_h(1)
|
fg_bg(fg, bg, x_repeat(LO)).exact_h(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A phat line
|
/// A phat line
|
||||||
fn phat_hi (fg: Color, bg: Color) -> impl Draw<Tui> {
|
fn phat_hi <'a> (fg: Color, bg: Color) -> impl Draw<'a, Tui> {
|
||||||
fg_bg(fg, bg, x_repeat(HI)).exact_h(1)
|
fg_bg(fg, bg, x_repeat(HI)).exact_h(1)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ pub const ICON_INC_V: &[char] = &['▼'];
|
||||||
pub const ICON_DEC_H: &[char] = &[' ', '🞀', ' '];
|
pub const ICON_DEC_H: &[char] = &[' ', '🞀', ' '];
|
||||||
pub const ICON_INC_H: &[char] = &[' ', '🞂', ' '];
|
pub const ICON_INC_H: &[char] = &[' ', '🞂', ' '];
|
||||||
|
|
||||||
pub fn x_scroll () -> impl Draw<Tui> {
|
pub fn x_scroll <'a> () -> impl Draw<'a, Tui> {
|
||||||
draw(|to: &mut Tui|{
|
draw(|to: &mut Tui|{
|
||||||
let XYWH(x1, y1, w, _h) = to.area();
|
let XYWH(x1, y1, w, _h) = to.area();
|
||||||
let x2 = x1 + w;
|
let x2 = x1 + w;
|
||||||
|
|
@ -37,7 +37,7 @@ pub fn x_scroll () -> impl Draw<Tui> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn y_scroll () -> impl Draw<Tui> {
|
pub fn y_scroll <'a> () -> impl Draw<'a, Tui> {
|
||||||
draw(|to: &mut Tui|{
|
draw(|to: &mut Tui|{
|
||||||
let XYWH(x1, y1, _w, h) = to.area();
|
let XYWH(x1, y1, _w, h) = to.area();
|
||||||
let y2 = y1 + h;
|
let y2 = y1 + h;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue