mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-07-17 07:56:56 +02:00
add origin and align methods to Layout trait
This commit is contained in:
parent
09463649c6
commit
13c886d9e0
18 changed files with 333 additions and 248 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
use ::{
|
use ::{
|
||||||
std::{io::stdout, sync::{Arc, RwLock}},
|
std::{io::stdout, sync::{Arc, RwLock}},
|
||||||
tengri::{*, term::*, lang::*, keys::*, draw::*, space::*, lang::*},
|
|
||||||
ratatui::style::Color,
|
ratatui::style::Color,
|
||||||
|
tengri::{*, lang::*},
|
||||||
};
|
};
|
||||||
|
|
||||||
tui_main!(State {
|
tui_main!(State {
|
||||||
|
|
@ -18,10 +18,10 @@ tui_view!(|self: State| {
|
||||||
let wh = (self.size.w(), self.size.h());
|
let wh = (self.size.w(), self.size.h());
|
||||||
let src = VIEWS.get(self.cursor).unwrap_or(&"");
|
let src = VIEWS.get(self.cursor).unwrap_or(&"");
|
||||||
let heading = format!("State {}/{} in {:?}", index, VIEWS.len(), &wh);
|
let heading = format!("State {}/{} in {:?}", index, VIEWS.len(), &wh);
|
||||||
let title = bg(Color::Rgb(60, 10, 10), y_push(1, align_n(heading)));
|
let title = bg(Color::Rgb(60, 10, 10), heading.align_n().push_y(1));
|
||||||
let code = bg(Color::Rgb(10, 60, 10), y_push(2, align_n(format!("{}", src))));
|
let code = bg(Color::Rgb(10, 60, 10), format!("{}", src).align_n().push_y(2));
|
||||||
//let content = ;//();//bg(Color::Rgb(10, 10, 60), View(self, CstIter::new(src)));
|
//let content = ;//();//bg(Color::Rgb(10, 10, 60), View(self, CstIter::new(src)));
|
||||||
let widget = thunk(move|to: &mut Tui|self.interpret(to, &src));
|
let widget = thunk(move|to: &mut Tui|self.interpret(to, &src).map(Some));
|
||||||
self.size.of(south(title, north(code, widget)))
|
self.size.of(south(title, north(code, widget)))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ struct State {
|
||||||
/** User-controllable value. */
|
/** User-controllable value. */
|
||||||
cursor: usize,
|
cursor: usize,
|
||||||
/** Rendered window size. */
|
/** Rendered window size. */
|
||||||
size: crate::space::Size,
|
size: Sizer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpret<Tui, XYWH<u16>> for State {
|
impl Interpret<Tui, XYWH<u16>> for State {
|
||||||
|
|
|
||||||
36
src/draw.rs
36
src/draw.rs
|
|
@ -3,32 +3,34 @@ use crate::*;
|
||||||
/// Output target.
|
/// Output target.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use tengri::{*, draw::*};
|
/// use tengri::*;
|
||||||
///
|
/// struct TestOut { w: u16, h: u16 };
|
||||||
/// struct TestOut<T: Screen<Unit = u16>>(T);
|
/// impl Wide<u16> for TestOut {}
|
||||||
///
|
/// impl Tall<u16> for TestOut {}
|
||||||
/// impl<T: Screen<Unit = u16>> Screen for TestOut {
|
/// impl Xy<u16> for TestOut { fn x (&self) -> u16 { 0 } fn y (&self) -> u16 { 0 } }
|
||||||
|
/// impl Screen for TestOut {
|
||||||
/// type Unit = u16;
|
/// type Unit = u16;
|
||||||
/// fn show <D: Draw<Self> + ?Sized> (&mut self, _: D) {
|
/// fn show <D: Draw<Self>> (&mut self, _: D) -> Drawn<u16> {
|
||||||
/// println!("placed");
|
/// println!("placed");
|
||||||
/// ()
|
/// Ok(None)
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// impl_draw!(|self: String, to: TestOut<u16>|{
|
/// impl_draw!(|self: String, to: TestOut|{
|
||||||
/// to.area_mut().set_w(self.len() as u16);
|
/// to.w = self.len() as u16;
|
||||||
|
/// Ok(None)
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
pub trait Screen: Xy<Self::Unit> + Wh<Self::Unit> + Send + Sync + Sized {
|
pub trait Screen: Xy<Self::Unit> + Wh<Self::Unit> + Send + Sync + Sized {
|
||||||
type Unit: Coord;
|
type Unit: Coord;
|
||||||
/// Render drawable in subarea specified by `area`
|
/// Render drawable in subarea specified by `area`
|
||||||
fn show <'t, T: Draw<Self>> (&mut self, content: T) -> Perhaps<XYWH<Self::Unit>>;
|
fn show <T: Draw<Self>> (&mut self, content: T) -> Perhaps<XYWH<Self::Unit>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implement the [Draw] trait for a particular drawable and [Screen].
|
/// Implement the [Draw] trait for a particular drawable and [Screen].
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use tengri::{*, draw::*, term::*};
|
/// use tengri::*;
|
||||||
/// struct MyDrawable;
|
/// struct MyDrawable;
|
||||||
/// impl_draw!(|self: MyDrawable, to: Tui|{
|
/// impl_draw!(|self: MyDrawable, to: Tui|{
|
||||||
/// todo!("your draw logic")
|
/// todo!("your draw logic")
|
||||||
|
|
@ -60,7 +62,7 @@ pub trait Screen: Xy<Self::Unit> + Wh<Self::Unit> + Send + Sync + Sized {
|
||||||
/// a [Draw]able.
|
/// a [Draw]able.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use tengri::{*, draw::*, term::*};
|
/// use tengri::*;
|
||||||
/// struct MyWidget(bool);
|
/// struct MyWidget(bool);
|
||||||
/// impl Draw<Tui> for MyWidget {
|
/// impl Draw<Tui> for MyWidget {
|
||||||
/// fn draw (self, to: &mut Tui) -> Perhaps<XYWH<u16>> {
|
/// fn draw (self, to: &mut Tui) -> Perhaps<XYWH<u16>> {
|
||||||
|
|
@ -106,6 +108,12 @@ pub trait View<T: Screen> {
|
||||||
fn view (&self) -> impl Draw<T>;
|
fn view (&self) -> impl Draw<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Screen> View<T> for () {
|
||||||
|
fn view (&self) -> impl Draw<T> {
|
||||||
|
()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Screen, V: View<T>> Draw<T> for &V {
|
impl<T: Screen, V: View<T>> Draw<T> for &V {
|
||||||
fn draw (self, to: &mut T) -> Perhaps<XYWH<T::Unit>> {
|
fn draw (self, to: &mut T) -> Perhaps<XYWH<T::Unit>> {
|
||||||
self.view().draw(to)
|
self.view().draw(to)
|
||||||
|
|
@ -114,15 +122,11 @@ impl<T: Screen, V: View<T>> Draw<T> for &V {
|
||||||
|
|
||||||
features! {
|
features! {
|
||||||
"draw": [
|
"draw": [
|
||||||
align,
|
|
||||||
area,
|
|
||||||
azimuth,
|
|
||||||
color,
|
color,
|
||||||
coord,
|
coord,
|
||||||
iter,
|
iter,
|
||||||
layout,
|
layout,
|
||||||
lrtb,
|
lrtb,
|
||||||
origin,
|
|
||||||
sizer,
|
sizer,
|
||||||
space,
|
space,
|
||||||
split,
|
split,
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
pub struct Align<T>(Option<Azimuth>, T);
|
|
||||||
|
|
||||||
impl_draw!(<S: Screen, T: Draw<S>,>|self: Align<T>, to: S|{
|
|
||||||
todo!()
|
|
||||||
});
|
|
||||||
|
|
||||||
/// ```
|
|
||||||
/// use tengri::*;
|
|
||||||
/// let _ = align(None, "unaligned");
|
|
||||||
/// let _ = align(Azimuth::SE, "southeast");
|
|
||||||
/// let _ = align(Some(Azimuth::SE), "southeast");
|
|
||||||
/// ```
|
|
||||||
pub fn align <S: Screen, T: Draw<S>, U: Into<Option<Azimuth>>> (origin: U, it: T) -> Align<T> {
|
|
||||||
Align(origin.into(), it)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn align_c <S: Screen, T: Draw<S>> (it: T) -> Align<T> { Align(Some(Azimuth::C), it) }
|
|
||||||
pub fn align_x <S: Screen, T: Draw<S>> (it: T) -> Align<T> { Align(Some(Azimuth::X), it) }
|
|
||||||
pub fn align_y <S: Screen, T: Draw<S>> (it: T) -> Align<T> { Align(Some(Azimuth::Y), it) }
|
|
||||||
|
|
||||||
pub fn align_n <S: Screen, T: Draw<S>> (it: T) -> Align<T> { Align(Some(Azimuth::N), it) }
|
|
||||||
pub fn align_s <S: Screen, T: Draw<S>> (it: T) -> Align<T> { Align(Some(Azimuth::S), it) }
|
|
||||||
pub fn align_e <S: Screen, T: Draw<S>> (it: T) -> Align<T> { Align(Some(Azimuth::E), it) }
|
|
||||||
pub fn align_w <S: Screen, T: Draw<S>> (it: T) -> Align<T> { Align(Some(Azimuth::W), it) }
|
|
||||||
|
|
||||||
pub fn align_ne <S: Screen, T: Draw<S>> (it: T) -> Align<T> { Align(Some(Azimuth::NE), it) }
|
|
||||||
pub fn align_se <S: Screen, T: Draw<S>> (it: T) -> Align<T> { Align(Some(Azimuth::SE), it) }
|
|
||||||
pub fn align_nw <S: Screen, T: Draw<S>> (it: T) -> Align<T> { Align(Some(Azimuth::NW), it) }
|
|
||||||
pub fn align_sw <S: Screen, T: Draw<S>> (it: T) -> Align<T> { Align(Some(Azimuth::SW), it) }
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
/// ```
|
|
||||||
/// use tengri::*;
|
|
||||||
/// let _ = area(None, "unareaed");
|
|
||||||
/// let _ = area([1, 2, 3, 4], "southeast");
|
|
||||||
/// let _ = area(Some([1, 2, 3, 4]), "southeast");
|
|
||||||
/// ```
|
|
||||||
pub fn area <S: Screen, T: Draw<S>, U: Into<Option<XYWH<S::Unit>>>> (
|
|
||||||
origin: U, it: T
|
|
||||||
) -> Area<S, T> {
|
|
||||||
Area(origin.into(), it)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Area<S: Screen, T: Draw<S>>(Option<XYWH<S::Unit>>, T);
|
|
||||||
|
|
||||||
impl_draw!(<S: Screen, T: Draw<S>,>|self: Area<S, T>, to: S|{ todo!() });
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
/// Where is [0, 0] located?
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use tengri::draw::Azimuth;
|
|
||||||
/// let _ = Azimuth::NW.align(());
|
|
||||||
/// ```
|
|
||||||
#[cfg_attr(test, derive(Arbitrary))]
|
|
||||||
#[derive(Debug, Copy, Clone, Default)] pub enum Azimuth {
|
|
||||||
#[default] C, X, Y, NW, N, NE, E, SE, S, SW, W
|
|
||||||
}
|
|
||||||
|
|
@ -6,7 +6,7 @@ use super::*;
|
||||||
/// FIXME: Use AsRef/AsMut?
|
/// FIXME: Use AsRef/AsMut?
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use tengri::draw::Coord;
|
/// use tengri::*;
|
||||||
/// let a: u16 = Coord::zero();
|
/// let a: u16 = Coord::zero();
|
||||||
/// let b: u16 = a.plus(1);
|
/// let b: u16 = a.plus(1);
|
||||||
/// let c: u16 = a.minus(2);
|
/// let c: u16 = a.minus(2);
|
||||||
|
|
|
||||||
|
|
@ -15,15 +15,6 @@ pub fn iter_once <'a, S: Screen, D: 'a, U: Draw<S>> (
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over a collection of various [Draw]ables:
|
/// Iterate over a collection of various [Draw]ables:
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use tengri::draw::{Origin::*, Split::*};
|
|
||||||
/// let _ = Below.iter([
|
|
||||||
/// NW.align(W(15).max(W(10).min("Leftbar"))),
|
|
||||||
/// NE.align(W(12).max(W(10).min("Rightbar"))),
|
|
||||||
/// Center.align(W(40).max(H(20.max("Center"))))
|
|
||||||
/// ].iter(), |x|x);
|
|
||||||
/// ```
|
|
||||||
pub fn iter_dyn <
|
pub fn iter_dyn <
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -70,11 +70,96 @@ pub trait Layout<S: Screen>: Draw<S> + Sized {
|
||||||
fn push_xy <N: Into<Option<S::Unit>>> (self, x: N, y: N) -> impl Draw<S> {
|
fn push_xy <N: Into<Option<S::Unit>>> (self, x: N, y: N) -> impl Draw<S> {
|
||||||
Push::XY(self, x.into(), y.into())
|
Push::XY(self, x.into(), y.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn align (self, azimuth: impl Into<Option<Azimuth>>) -> impl Draw<S> {
|
||||||
|
Align(azimuth.into(), self)
|
||||||
|
}
|
||||||
|
fn align_c (self) -> impl Draw<S> {
|
||||||
|
Align(Some(Azimuth::C), self)
|
||||||
|
}
|
||||||
|
fn align_x (self) -> impl Draw<S> {
|
||||||
|
Align(Some(Azimuth::X), self)
|
||||||
|
}
|
||||||
|
fn align_y (self) -> impl Draw<S> {
|
||||||
|
Align(Some(Azimuth::Y), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn align_n (self) -> impl Draw<S> {
|
||||||
|
Align(Some(Azimuth::N), self)
|
||||||
|
}
|
||||||
|
fn align_s (self) -> impl Draw<S> {
|
||||||
|
Align(Some(Azimuth::S), self)
|
||||||
|
}
|
||||||
|
fn align_e (self) -> impl Draw<S> {
|
||||||
|
Align(Some(Azimuth::E), self)
|
||||||
|
}
|
||||||
|
fn align_w (self) -> impl Draw<S> {
|
||||||
|
Align(Some(Azimuth::W), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn align_ne (self) -> impl Draw<S> {
|
||||||
|
Align(Some(Azimuth::NE), self)
|
||||||
|
}
|
||||||
|
fn align_se (self) -> impl Draw<S> {
|
||||||
|
Align(Some(Azimuth::SE), self)
|
||||||
|
}
|
||||||
|
fn align_nw (self) -> impl Draw<S> {
|
||||||
|
Align(Some(Azimuth::NW), self)
|
||||||
|
}
|
||||||
|
fn align_sw (self) -> impl Draw<S> {
|
||||||
|
Align(Some(Azimuth::SW), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn origin (self, azimuth: impl Into<Option<Azimuth>>) -> impl Draw<S> {
|
||||||
|
Origin(azimuth.into(), self)
|
||||||
|
}
|
||||||
|
fn origin_c (self) -> impl Draw<S> {
|
||||||
|
Origin(Some(Azimuth::C), self)
|
||||||
|
}
|
||||||
|
fn origin_x (self) -> impl Draw<S> {
|
||||||
|
Origin(Some(Azimuth::X), self)
|
||||||
|
}
|
||||||
|
fn origin_y (self) -> impl Draw<S> {
|
||||||
|
Origin(Some(Azimuth::Y), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn origin_n (self) -> impl Draw<S> {
|
||||||
|
Origin(Some(Azimuth::N), self)
|
||||||
|
}
|
||||||
|
fn origin_s (self) -> impl Draw<S> {
|
||||||
|
Origin(Some(Azimuth::S), self)
|
||||||
|
}
|
||||||
|
fn origin_e (self) -> impl Draw<S> {
|
||||||
|
Origin(Some(Azimuth::E), self)
|
||||||
|
}
|
||||||
|
fn origin_w (self) -> impl Draw<S> {
|
||||||
|
Origin(Some(Azimuth::W), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn origin_ne (self) -> impl Draw<S> {
|
||||||
|
Origin(Some(Azimuth::NE), self)
|
||||||
|
}
|
||||||
|
fn origin_se (self) -> impl Draw<S> {
|
||||||
|
Origin(Some(Azimuth::SE), self)
|
||||||
|
}
|
||||||
|
fn origin_nw (self) -> impl Draw<S> {
|
||||||
|
Origin(Some(Azimuth::NW), self)
|
||||||
|
}
|
||||||
|
fn origin_sw (self) -> impl Draw<S> {
|
||||||
|
Origin(Some(Azimuth::SW), self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Screen, T: Draw<S>> Layout<S> for T {}
|
impl<S: Screen, T: Draw<S>> Layout<S> for T {}
|
||||||
|
|
||||||
/// Use whole drawing area along one or both axes.
|
/// Use whole drawing area along one or both axes.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use tengri::Layout;
|
||||||
|
/// let _ = "".full_w();
|
||||||
|
/// let _ = "".full_h();
|
||||||
|
/// let _ = "".full_wh();
|
||||||
|
/// ```
|
||||||
pub enum Full<T: Screen, I: Draw<T>> {
|
pub enum Full<T: Screen, I: Draw<T>> {
|
||||||
__(PhantomData<T>),
|
__(PhantomData<T>),
|
||||||
W(I),
|
W(I),
|
||||||
|
|
@ -82,14 +167,17 @@ pub enum Full<T: Screen, I: Draw<T>> {
|
||||||
WH(I),
|
WH(I),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_draw!(<T: Screen, I: Draw<T>,>|self: Full<T, I>, to: T|{
|
impl_draw!(<T: Screen, I: Draw<T>,>|self: Full<T, I>, _to: T|{
|
||||||
todo!()
|
todo!()
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Only draw content if area is above a certain size.
|
/// Move content in the positive direction of one or both axes.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let min = tengri::wh_min(3, 5, "Hello"); // 5x5
|
/// use tengri::Layout;
|
||||||
|
/// let _ = "".push_x(1);
|
||||||
|
/// let _ = "".push_y(1);
|
||||||
|
/// let _ = "".push_xy(1, 1);
|
||||||
/// ```
|
/// ```
|
||||||
pub enum Push<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
pub enum Push<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
__(PhantomData<T>),
|
__(PhantomData<T>),
|
||||||
|
|
@ -98,14 +186,17 @@ pub enum Push<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
XY(I, X, X),
|
XY(I, X, X),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Push<T, I, X>, to: T|{
|
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Push<T, I, X>, _to: T|{
|
||||||
todo!()
|
todo!()
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Only draw content if area is above a certain size.
|
/// Move content in the negative direction of one or both axes.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let min = tengri::wh_min(3, 5, "Hello"); // 5x5
|
/// use tengri::Layout;
|
||||||
|
/// let _ = "".pull_x(1);
|
||||||
|
/// let _ = "".pull_y(1);
|
||||||
|
/// let _ = "".pull_xy(1, 1);
|
||||||
/// ```
|
/// ```
|
||||||
pub enum Pull<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
pub enum Pull<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
__(PhantomData<T>),
|
__(PhantomData<T>),
|
||||||
|
|
@ -114,14 +205,17 @@ pub enum Pull<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
XY(I, X, X),
|
XY(I, X, X),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Pull<T, I, X>, to: T|{
|
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Pull<T, I, X>, _to: T|{
|
||||||
todo!()
|
todo!()
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Only draw content if area is above a certain size.
|
/// Only draw content if area is above a certain size.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let min = tengri::wh_min(3, 5, "Hello"); // 5x5
|
/// use tengri::Layout;
|
||||||
|
/// let _ = "".min_w(1);
|
||||||
|
/// let _ = "".min_h(1);
|
||||||
|
/// let _ = "".min_wh(1, 1);
|
||||||
/// ```
|
/// ```
|
||||||
pub enum Min<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
pub enum Min<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
__(PhantomData<T>),
|
__(PhantomData<T>),
|
||||||
|
|
@ -130,16 +224,17 @@ pub enum Min<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
WH(I, X, X),
|
WH(I, X, X),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Min<T, I, X>, to: T|{
|
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Min<T, I, X>, _to: T|{
|
||||||
todo!()
|
todo!()
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Set maximum size of of drawing area.
|
/// Set maximum size of of drawing area.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let max = tengri::w_max(3, "Hello");
|
/// use tengri::Layout;
|
||||||
/// let max = tengri::w_max(None, "Hello");
|
/// let _ = "".max_w(1);
|
||||||
/// let max = tengri::w_max(Some(3), "Hello");
|
/// let _ = "".max_h(1);
|
||||||
|
/// let _ = "".max_wh(1, 1);
|
||||||
/// ```
|
/// ```
|
||||||
pub enum Max<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
pub enum Max<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
__(PhantomData<T>),
|
__(PhantomData<T>),
|
||||||
|
|
@ -148,16 +243,17 @@ pub enum Max<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
WH(I, X, X),
|
WH(I, X, X),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Max<T, I, X>, to: T|{
|
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Max<T, I, X>, _to: T|{
|
||||||
todo!()
|
todo!()
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Set size of of drawing area.
|
/// Set size of of drawing area.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let max = tengri::w_max(3, "Hello");
|
/// use tengri::Layout;
|
||||||
/// let max = tengri::w_max(None, "Hello");
|
/// let _ = "".exact_w(1);
|
||||||
/// let max = tengri::w_max(Some(3), "Hello");
|
/// let _ = "".exact_h(1);
|
||||||
|
/// let _ = "".exact_wh(1, 1);
|
||||||
/// ```
|
/// ```
|
||||||
pub enum Exact<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
pub enum Exact<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
__(PhantomData<T>),
|
__(PhantomData<T>),
|
||||||
|
|
@ -166,16 +262,17 @@ pub enum Exact<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
WH(I, X, X),
|
WH(I, X, X),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Exact<T, I, X>, to: T|{
|
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Exact<T, I, X>, _to: T|{
|
||||||
todo!()
|
todo!()
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Define inner drawing area.
|
/// Define inner drawing area.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let max = tengri::w_max(3, "Hello");
|
/// use tengri::Layout;
|
||||||
/// let max = tengri::w_max(None, "Hello");
|
/// let _ = "".pad_w(1);
|
||||||
/// let max = tengri::w_max(Some(3), "Hello");
|
/// let _ = "".pad_h(1);
|
||||||
|
/// let _ = "".pad_wh(1, 1);
|
||||||
/// ```
|
/// ```
|
||||||
pub enum Pad<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
pub enum Pad<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
__(PhantomData<T>),
|
__(PhantomData<T>),
|
||||||
|
|
@ -184,6 +281,59 @@ pub enum Pad<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
WH(I, X, X),
|
WH(I, X, X),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Pad<T, I, X>, to: T|{
|
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Pad<T, I, X>, _to: T|{
|
||||||
todo!()
|
todo!()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pub struct Align<T>(Option<Azimuth>, T);
|
||||||
|
|
||||||
|
impl_draw!(<S: Screen, T: Draw<S>,>|self: Align<T>, _to: S|{
|
||||||
|
todo!()
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Where is [0, 0] located?
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use tengri::*;
|
||||||
|
/// use Azimuth::*;
|
||||||
|
/// let _ = "".align(NW);
|
||||||
|
/// ```
|
||||||
|
#[cfg_attr(test, derive(Arbitrary))]
|
||||||
|
#[derive(Debug, Copy, Clone, Default)] pub enum Azimuth {
|
||||||
|
#[default] C, X, Y, NW, N, NE, E, SE, S, SW, W
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ```
|
||||||
|
/// use tengri::*;
|
||||||
|
/// let _ = area(None, "unareaed");
|
||||||
|
/// let _ = area(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>>>> (
|
||||||
|
origin: U, it: T
|
||||||
|
) -> Area<S, T> {
|
||||||
|
Area(origin.into(), it)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Area<S: Screen, T: Draw<S>>(Option<XYWH<S::Unit>>, T);
|
||||||
|
|
||||||
|
impl_draw!(<S: Screen, T: Draw<S>,>|self: Area<S, T>, _to: S|{
|
||||||
|
todo!()
|
||||||
|
});
|
||||||
|
|
||||||
|
pub struct Origin<T>(Option<Azimuth>, T);
|
||||||
|
|
||||||
|
impl_draw!(<S: Screen, T: Draw<S>,>|self: Origin<T>, _to: S|{
|
||||||
|
todo!()
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Something that has `[0, 0]` at a particular point.
|
||||||
|
pub trait HasOrigin {
|
||||||
|
fn origin (&self) -> Azimuth;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsRef<Azimuth>> HasOrigin for T {
|
||||||
|
fn origin (&self) -> Azimuth {
|
||||||
|
*self.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
pub struct Origin<T>(Option<Azimuth>, T);
|
|
||||||
|
|
||||||
impl_draw!(<S: Screen, T: Draw<S>,>|self: Origin<T>, to: S|{
|
|
||||||
todo!()
|
|
||||||
});
|
|
||||||
|
|
||||||
/// ```
|
|
||||||
/// use tengri::*;
|
|
||||||
/// let _ = origin(None, "origin unspecified");
|
|
||||||
/// let _ = origin(Azimuth::SE, "southeast");
|
|
||||||
/// let _ = origin(Some(Azimuth::SE), "southeast");
|
|
||||||
/// ```
|
|
||||||
pub fn origin <S: Screen, T: Draw<S>, U: Into<Option<Azimuth>>> (origin: U, it: T) -> Origin<T> {
|
|
||||||
Origin(origin.into(), it)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn origin_c <S: Screen, T: Draw<S>> (it: T) -> Origin<T> { Origin(Some(Azimuth::C), it) }
|
|
||||||
pub fn origin_x <S: Screen, T: Draw<S>> (it: T) -> Origin<T> { Origin(Some(Azimuth::X), it) }
|
|
||||||
pub fn origin_y <S: Screen, T: Draw<S>> (it: T) -> Origin<T> { Origin(Some(Azimuth::Y), it) }
|
|
||||||
|
|
||||||
pub fn origin_n <S: Screen, T: Draw<S>> (it: T) -> Origin<T> { Origin(Some(Azimuth::N), it) }
|
|
||||||
pub fn origin_s <S: Screen, T: Draw<S>> (it: T) -> Origin<T> { Origin(Some(Azimuth::S), it) }
|
|
||||||
pub fn origin_e <S: Screen, T: Draw<S>> (it: T) -> Origin<T> { Origin(Some(Azimuth::E), it) }
|
|
||||||
pub fn origin_w <S: Screen, T: Draw<S>> (it: T) -> Origin<T> { Origin(Some(Azimuth::W), it) }
|
|
||||||
|
|
||||||
pub fn origin_ne <S: Screen, T: Draw<S>> (it: T) -> Origin<T> { Origin(Some(Azimuth::NE), it) }
|
|
||||||
pub fn origin_se <S: Screen, T: Draw<S>> (it: T) -> Origin<T> { Origin(Some(Azimuth::SE), it) }
|
|
||||||
pub fn origin_nw <S: Screen, T: Draw<S>> (it: T) -> Origin<T> { Origin(Some(Azimuth::NW), it) }
|
|
||||||
pub fn origin_sw <S: Screen, T: Draw<S>> (it: T) -> Origin<T> { Origin(Some(Azimuth::SW), it) }
|
|
||||||
|
|
||||||
/// Something that has `[0, 0]` at a particular point.
|
|
||||||
pub trait HasOrigin {
|
|
||||||
fn origin (&self) -> Azimuth;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: AsRef<Azimuth>> HasOrigin for T {
|
|
||||||
fn origin (&self) -> Azimuth {
|
|
||||||
*self.as_ref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -39,20 +39,20 @@ pub const fn below <T: Screen> (a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T
|
||||||
impl Split {
|
impl Split {
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use tengri::draw::Split::*;
|
/// use tengri::*;
|
||||||
/// let _ = Above.half("", "");
|
/// let _ = Split::Above.half("", "");
|
||||||
/// let _ = Below.half("", "");
|
/// let _ = Split::Below.half("", "");
|
||||||
/// let _ = North.half("", "");
|
/// let _ = Split::North.half("", "");
|
||||||
/// let _ = South.half("", "");
|
/// let _ = Split::South.half("", "");
|
||||||
/// let _ = East.half("", "");
|
/// let _ = Split::East.half("", "");
|
||||||
/// let _ = West.half("", "");
|
/// let _ = Split::West.half("", "");
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn half <T: Screen> (&self, a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
pub const fn half <T: Screen> (&self, a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||||
thunk(move|to: &mut T|{
|
thunk(move|to: &mut T|{
|
||||||
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();
|
||||||
let a = align(origin_a, a);
|
let a = a.align(origin_a);
|
||||||
let b = align(origin_b, b);
|
let b = b.align(origin_b);
|
||||||
match self {
|
match self {
|
||||||
Self::Below => {
|
Self::Below => {
|
||||||
to.show(area(area_b, b))?;
|
to.show(area(area_b, b))?;
|
||||||
|
|
@ -95,6 +95,21 @@ impl Split {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///// ```
|
||||||
|
///// use tengri::*;
|
||||||
|
///// let _ = Split::Below.iter([
|
||||||
|
///// "Leftbar"
|
||||||
|
///// .min_w(10).max_w(15).align(Azimuth::NW),
|
||||||
|
///// "Rightbar"
|
||||||
|
///// .min_w(10).max_w(12).align(Azimuth::NE),
|
||||||
|
///// "Center"
|
||||||
|
///// .min_w(20).max_w(40).align(Azimuth::C),
|
||||||
|
///// ].iter());
|
||||||
|
///// ```
|
||||||
|
//pub fn iter <S: Screen, T: Draw<S>> (&self, _: impl Iterator<Item = T>) {
|
||||||
|
//todo!()
|
||||||
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export] macro_rules! north {
|
#[macro_export] macro_rules! north {
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@ impl<T: Screen, F: FnOnce(&mut T)->Perhaps<XYWH<T::Unit>>> Draw<T> for Thunk<T,
|
||||||
/// Basic [Draw]able closure.
|
/// Basic [Draw]able closure.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use tengri::{draw::*, term::*};
|
/// # use tengri::*;
|
||||||
/// # fn test () -> impl tengri::draw::Draw<tengri::term::Tui> {
|
/// # fn test () -> impl Draw<Tui> {
|
||||||
/// thunk(|to: &mut Tui|Ok(to.1))
|
/// thunk(|to: &mut Tui|Ok(Some(to.1)))
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn thunk <T: Screen, F: FnOnce(&mut T)->Perhaps<XYWH<T::Unit>>> (
|
pub const fn thunk <T: Screen, F: FnOnce(&mut T)->Perhaps<XYWH<T::Unit>>> (
|
||||||
|
|
@ -26,8 +26,8 @@ pub const fn thunk <T: Screen, F: FnOnce(&mut T)->Perhaps<XYWH<T::Unit>>> (
|
||||||
/// Only render when condition is true.
|
/// Only render when condition is true.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use tengri::{draw::*, term::*};
|
/// # use tengri::*;
|
||||||
/// # fn test () -> impl tengri::draw::Draw<tengri::term::Tui> {
|
/// # fn test () -> impl Draw<Tui> {
|
||||||
/// when(true, "Yes")
|
/// when(true, "Yes")
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
@ -38,8 +38,8 @@ pub const fn when <T: Screen> (condition: bool, draw: impl Draw<T>) -> impl Draw
|
||||||
/// Render one thing if a condition is true and another false.
|
/// Render one thing if a condition is true and another false.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use tengri::{draw::*, term::*};
|
/// # use tengri::*;
|
||||||
/// # fn test () -> impl tengri::draw::Draw<tengri::term::Tui> {
|
/// # fn test () -> impl Draw<Tui> {
|
||||||
/// either(true, "Yes", "No")
|
/// either(true, "Yes", "No")
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,9 @@ pub trait Tall<N: Coord> {
|
||||||
/// Point with size.
|
/// Point with size.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use tengri::space::{XY, XYWH};
|
/// # use tengri::*;
|
||||||
/// let xywh = XYWH(0u16, 0, 0, 0);
|
/// let xywh = XYWH(0u16, 0, 0, 0);
|
||||||
/// assert_eq!(XYWH(10u16, 10, 20, 20).center(), XY(20, 20));
|
/// assert_eq!(XYWH(10u16, 10, 20, 20).center(), (20, 20));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// * [ ] TODO: origin field (determines at which corner/side is X0 Y0)
|
/// * [ ] TODO: origin field (determines at which corner/side is X0 Y0)
|
||||||
|
|
|
||||||
104
src/eval.rs
104
src/eval.rs
|
|
@ -63,18 +63,19 @@ macro_rules! eval_enum ((
|
||||||
/// Interpret layout operation.
|
/// Interpret layout operation.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use tengri::{lang::*, draw::*, eval::*, term::*};
|
/// # use tengri::{*, lang::*};
|
||||||
///
|
///
|
||||||
/// struct State {/*app-specific*/}
|
/// struct State {/*app-specific*/}
|
||||||
/// impl<'b> Namespace<'b, bool> for State {}
|
|
||||||
/// impl<'b> Namespace<'b, u16> for State {}
|
/// impl<'b> Namespace<'b, u16> for State {}
|
||||||
/// impl Interpret<Tui, XYWH<u16>> for State {}
|
/// impl<'b> Namespace<'b, bool> for State {}
|
||||||
|
/// impl<'b> Namespace<'b, Option<u16>> for State {}
|
||||||
|
/// impl Interpret<Tui, Option<XYWH<u16>>> for State {}
|
||||||
///
|
///
|
||||||
/// # fn main () -> tengri::Usually<()> {
|
/// # fn main () -> tengri::Usually<()> {
|
||||||
/// let state = State {};
|
/// let state = State {};
|
||||||
/// let mut target = Tui::new(80, 25);
|
/// let mut target = Tui::new(80, 25);
|
||||||
/// eval_view(&state, &mut target, &"")?;
|
/// eval_view(&state, &mut target, &"")?;
|
||||||
/// eval_view(&state, &mut target, &"(when true (text hello))")?;
|
/// eval_view(&state, &mut target, &"(whe true (text hello))")?;
|
||||||
/// eval_view(&state, &mut target, &"(either true (text hello) (text world))")?;
|
/// eval_view(&state, &mut target, &"(either true (text hello) (text world))")?;
|
||||||
/// // TODO test all
|
/// // TODO test all
|
||||||
/// # Ok(()) }
|
/// # Ok(()) }
|
||||||
|
|
@ -108,43 +109,33 @@ pub fn eval_view <'a, O: Screen + 'a, S> (
|
||||||
|
|
||||||
Some("when") => when(
|
Some("when") => when(
|
||||||
state.namespace(arg0?)?.unwrap(),
|
state.namespace(arg0?)?.unwrap(),
|
||||||
thunk(move|output: &mut O|{
|
thunk(move|output: &mut O|{state.interpret(output, &arg1)})
|
||||||
state.interpret(output, &arg1)
|
|
||||||
})
|
|
||||||
).draw(output),
|
).draw(output),
|
||||||
|
|
||||||
Some("either") => either(
|
Some("either") => either(
|
||||||
state.namespace(arg0?)?.unwrap(),
|
state.namespace(arg0?)?.unwrap(),
|
||||||
thunk(move|output: &mut O|{
|
thunk(move|output: &mut O|{state.interpret(output, &arg1)}),
|
||||||
state.interpret(output, &arg1)
|
thunk(move|output: &mut O|{state.interpret(output, &arg2)}),
|
||||||
}),
|
|
||||||
thunk(move|output: &mut O|{
|
|
||||||
state.interpret(output, &arg2)
|
|
||||||
}),
|
|
||||||
).draw(output),
|
).draw(output),
|
||||||
|
|
||||||
// Second `frags.next()` calls returns the namespace member.
|
// Second `frags.next()` calls returns the namespace member.
|
||||||
Some("bsp") => {
|
Some("bsp") => {
|
||||||
let direction = eval_enum!("bsp", output, state, frags.next(), arg0, Split {
|
eval_enum!("bsp", output, state, frags.next(), arg0, Split {
|
||||||
"n" => North,
|
"n" => North,
|
||||||
"s" => South,
|
"s" => South,
|
||||||
"e" => East,
|
"e" => East,
|
||||||
"w" => West,
|
"w" => West,
|
||||||
"a" => Above,
|
"a" => Above,
|
||||||
"b" => Below
|
"b" => Below
|
||||||
});
|
}).half(
|
||||||
direction.half(
|
thunk(move|output: &mut O|{state.interpret(output, &arg0)}),
|
||||||
thunk(move|output: &mut O|{
|
thunk(move|output: &mut O|{state.interpret(output, &arg1)}),
|
||||||
state.interpret(output, &arg0)
|
|
||||||
}),
|
|
||||||
thunk(move|output: &mut O|{
|
|
||||||
state.interpret(output, &arg1)
|
|
||||||
}),
|
|
||||||
).draw(output)
|
).draw(output)
|
||||||
},
|
},
|
||||||
|
|
||||||
Some("align") => {
|
Some("align") => {
|
||||||
let alignment = eval_enum!("align", output, state, frags.next(), arg0, Azimuth {
|
let content = thunk(move|output: &mut O|{state.interpret(output, &arg0)});
|
||||||
|
content.align(eval_enum!("align", output, state, frags.next(), arg0, Azimuth {
|
||||||
"c" => C,
|
"c" => C,
|
||||||
"n" => N,
|
"n" => N,
|
||||||
"s" => S,
|
"s" => S,
|
||||||
|
|
@ -152,11 +143,7 @@ pub fn eval_view <'a, O: Screen + 'a, S> (
|
||||||
"w" => W,
|
"w" => W,
|
||||||
"x" => X,
|
"x" => X,
|
||||||
"y" => Y
|
"y" => Y
|
||||||
});
|
})).draw(output)
|
||||||
let content = thunk(move|output: &mut O|{
|
|
||||||
state.interpret(output, &arg0)
|
|
||||||
});
|
|
||||||
align(alignment, content).draw(output)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
Some("exact") => eval_xy!(
|
Some("exact") => eval_xy!(
|
||||||
|
|
@ -187,21 +174,50 @@ pub fn eval_view <'a, O: Screen + 'a, S> (
|
||||||
/// Interpret TUI-specific layout operation.
|
/// Interpret TUI-specific layout operation.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use tengri::{lang::*, term::*, eval::*, ratatui::prelude::Color};
|
/// use tengri::{*, lang::*, ratatui::prelude::Color};
|
||||||
///
|
///
|
||||||
|
/// #[namespace(bool {})]
|
||||||
|
/// #[namespace(u8: try_to_u8)]
|
||||||
|
/// #[namespace(u16: try_to_u16)]
|
||||||
|
/// #[namespace(Color: try_to_color)]
|
||||||
|
/// #[interpret(Tui -> Option<XYWH<u16>>: try_eval_tui)]
|
||||||
/// struct State;
|
/// struct State;
|
||||||
/// impl<'b> Namespace<'b, bool> for State {}
|
/// tengri::lang::primitive!(u8: try_to_u8);
|
||||||
/// impl<'b> Namespace<'b, u16> for State {}
|
/// tengri::lang::primitive!(u16: try_to_u16);
|
||||||
/// impl<'b> Namespace<'b, Color> for State {}
|
/// tengri::lang::namespace!(State: bool {
|
||||||
/// impl Interpret<Tui, ()> for State {}
|
/// });
|
||||||
|
/// tengri::lang::namespace!(State: u8 {
|
||||||
|
/// literal = |x|try_to_u8(x);
|
||||||
|
/// });
|
||||||
|
/// tengri::lang::namespace!(State: u16 {
|
||||||
|
/// literal = |x|try_to_u16(x);
|
||||||
|
/// });
|
||||||
|
/// tengri::lang::namespace!(State: Color {
|
||||||
|
/// expression = |_state| {
|
||||||
|
/// "g" (x: u8) => { ItemTheme::G[x as usize].base.term }
|
||||||
|
/// };
|
||||||
|
/// });
|
||||||
|
/// tengri::lang::interpret!(|self: State, context: Tui, lang|->Option<XYWH<u16>>{
|
||||||
|
/// expression = {
|
||||||
|
/// "text" (...rest) => { todo!() }
|
||||||
|
/// }
|
||||||
|
/// });
|
||||||
|
/// impl Interpret<Tui, Option<XYWH<u16>>> for State {
|
||||||
|
/// fn interpret_expr <'a> (&'a self, _: &mut Tui, lang: &'a impl Expression)
|
||||||
|
/// -> Usually<Option<XYWH<u16>>>
|
||||||
|
/// {
|
||||||
|
/// Ok(None)
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
/// # fn main () -> tengri::Usually<()> {
|
/// # fn main () -> tengri::Usually<()> {
|
||||||
/// let state = State;
|
/// let state = State;
|
||||||
/// let mut out = Tui::default();
|
/// let mut out = Tui::new(80, 25);
|
||||||
/// tengri::eval::eval_view_tui(&state, &mut out, "")?;
|
/// eval_view_tui(&state, &mut out, "")?;
|
||||||
/// tengri::eval::eval_view_tui(&state, &mut out, "text Hello world!")?;
|
/// eval_view_tui(&state, &mut out, "text Hello world!")?;
|
||||||
/// tengri::eval::eval_view_tui(&state, &mut out, "fg (g 0) (text Hello world!)")?;
|
/// eval_view_tui(&state, &mut out, "fg (g 0) (text Hello world!)")?;
|
||||||
/// tengri::eval::eval_view_tui(&state, &mut out, "bg (g 2) (text Hello world!)")?;
|
/// eval_view_tui(&state, &mut out, "bg (g 2) (text Hello world!)")?;
|
||||||
/// tengri::eval::eval_view_tui(&state, &mut out, "(bg (g 3) (fg (g 4) (text Hello world!)))")?;
|
/// eval_view_tui(&state, &mut out, "(bg (g 3) (fg (g 4) (text Hello world!)))")?;
|
||||||
/// # Ok(()) }
|
/// # Ok(()) }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn eval_view_tui <'a, S> (
|
pub fn eval_view_tui <'a, S> (
|
||||||
|
|
@ -231,22 +247,28 @@ pub fn eval_view_tui <'a, S> (
|
||||||
|
|
||||||
Some("fg") => {
|
Some("fg") => {
|
||||||
let arg0 = arg0?.expect("fg: expected arg 0 (color)");
|
let arg0 = arg0?.expect("fg: expected arg 0 (color)");
|
||||||
let color = Namespace::namespace(state, arg0)?.unwrap_or_else(||panic!("fg: {arg0:?}: not a color"));
|
if let Some(color) = Namespace::namespace(state, arg0)? {
|
||||||
output.show(fg(color, thunk(move|output: &mut Tui|{
|
output.show(fg(color, thunk(move|output: &mut Tui|{
|
||||||
state.interpret(output, &arg1)?;
|
state.interpret(output, &arg1)?;
|
||||||
// FIXME?: don't max out the used area?
|
// FIXME?: don't max out the used area?
|
||||||
Ok(Some(output.area().into()))
|
Ok(Some(output.area().into()))
|
||||||
})))
|
})))
|
||||||
|
} else {
|
||||||
|
return Err(format!("fg: {arg0:?}: not a color").into())
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Some("bg") => {
|
Some("bg") => {
|
||||||
let arg0 = arg0?.expect("bg: expected arg 0 (color)");
|
let arg0 = arg0?.expect("bg: expected arg 0 (color)");
|
||||||
let color = Namespace::namespace(state, arg0)?.unwrap_or_else(||panic!("bg: {arg0:?}: not a color"));
|
if let Some(color) = Namespace::namespace(state, arg0)? {
|
||||||
output.show(bg(color, thunk(move|output: &mut Tui|{
|
output.show(bg(color, thunk(move|output: &mut Tui|{
|
||||||
state.interpret(output, &arg1)?;
|
state.interpret(output, &arg1)?;
|
||||||
// FIXME?: don't max out the used area?
|
// FIXME?: don't max out the used area?
|
||||||
Ok(Some(output.area().into()))
|
Ok(Some(output.area().into()))
|
||||||
})))
|
})))
|
||||||
|
} else {
|
||||||
|
return Err(format!("bg: {arg0:?}: not a color").into())
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_ => return Ok(None)
|
_ => return Ok(None)
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ pub type BoxedAudioHandler<'j> =
|
||||||
/// Things that can provide a [jack::Client] reference.
|
/// Things that can provide a [jack::Client] reference.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use tengri::sing::{Jack, HasJack};
|
/// use tengri::*;
|
||||||
///
|
///
|
||||||
/// let jack: &Jack = Jacked::default().jack();
|
/// let jack: &Jack = Jacked::default().jack();
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{*, sing::*, time::PerfModel};
|
use crate::{*, PerfModel};
|
||||||
pub use ::jack::{*, contrib::{*, ClosureProcessHandler}};
|
pub use ::jack::{*, contrib::{*, ClosureProcessHandler}};
|
||||||
|
|
||||||
use JackState::*;
|
use JackState::*;
|
||||||
|
|
@ -6,7 +6,7 @@ use JackState::*;
|
||||||
/// Wraps [JackState], and through it [jack::Client] when connected.
|
/// Wraps [JackState], and through it [jack::Client] when connected.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let jack = tengri::sing::Jack::default();
|
/// let jack = tengri::Jack::default();
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Clone, Debug, Default)] pub struct Jack<'j> (
|
#[derive(Clone, Debug, Default)] pub struct Jack<'j> (
|
||||||
pub(crate) Arc<RwLock<JackState<'j>>>
|
pub(crate) Arc<RwLock<JackState<'j>>>
|
||||||
|
|
@ -17,7 +17,7 @@ use JackState::*;
|
||||||
/// [jack::Client], which you can use to talk to the JACK API.
|
/// [jack::Client], which you can use to talk to the JACK API.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let state = tengri::sing::JackState::default();
|
/// let state = tengri::JackState::default();
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Default)] pub enum JackState<'j> {
|
#[derive(Debug, Default)] pub enum JackState<'j> {
|
||||||
/// Unused
|
/// Unused
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ pub use ::jack::{*, contrib::{*, ClosureProcessHandler}};
|
||||||
/// Event enum for JACK events.
|
/// Event enum for JACK events.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let event = tengri::sing::JackEvent::XRun; // kerpop
|
/// let event = tengri::JackEvent::XRun; // kerpop
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Clone, PartialEq)] pub enum JackEvent {
|
#[derive(Debug, Clone, PartialEq)] pub enum JackEvent {
|
||||||
ThreadInit,
|
ThreadInit,
|
||||||
|
|
@ -22,7 +22,7 @@ pub use ::jack::{*, contrib::{*, ClosureProcessHandler}};
|
||||||
/// Generic notification handler that emits [JackEvent]
|
/// Generic notification handler that emits [JackEvent]
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let notify = tengri::sing::JackNotify(|_|{});
|
/// let notify = tengri::JackNotify(|_|{});
|
||||||
/// ```
|
/// ```
|
||||||
pub struct JackNotify<T: Fn(JackEvent) + Send>(pub T);
|
pub struct JackNotify<T: Fn(JackEvent) + Send>(pub T);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ impl Tui {
|
||||||
/// Implement standard [main] entrypoint for TUI apps.
|
/// Implement standard [main] entrypoint for TUI apps.
|
||||||
#[macro_export] macro_rules! tui_main {
|
#[macro_export] macro_rules! tui_main {
|
||||||
($state:expr) => {
|
($state:expr) => {
|
||||||
pub fn main () -> Usually<()> { tui_run_main($state) }
|
pub fn main () -> Usually<()> { tui_run_main(Arc::new(RwLock::new($state))) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
use crate::{*, lang::*};
|
use crate::*;
|
||||||
use ratatui::{prelude::{Style, Position, Backend, Color}};
|
use ratatui::{prelude::{Style, Position, Backend, Color}};
|
||||||
|
|
||||||
/// TUI works in u16 coordinates.
|
/// TUI works in u16 coordinates.
|
||||||
impl Coord for u16 { fn plus (self, other: Self) -> Self { self.saturating_add(other) } }
|
impl Coord for u16 { fn plus (self, other: Self) -> Self { self.saturating_add(other) } }
|
||||||
impl_draw!(|self: u64, _to: Tui|{ todo!() });
|
|
||||||
impl_draw!(|self: f64, _to: Tui|{ todo!() });
|
|
||||||
|
|
||||||
impl Screen for Tui {
|
impl Screen for Tui {
|
||||||
type Unit = u16;
|
type Unit = u16;
|
||||||
|
|
@ -37,8 +35,15 @@ impl Screen for Tui {
|
||||||
/// Spawn the TUI output thread which writes colored characters to the terminal.
|
/// Spawn the TUI output thread which writes colored characters to the terminal.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let state = Arc::new(RwLock::new(()));
|
/// let state = std::sync::Arc::new(std::sync::RwLock::new(()));
|
||||||
/// Exit::run(|exit|tui_output(exit, state, sleep, stdout()))
|
/// let _ = tengri::Exit::run(|exit|{
|
||||||
|
/// tengri::tui_output(
|
||||||
|
/// exit.as_ref(),
|
||||||
|
/// &state,
|
||||||
|
/// std::time::Duration::from_millis(10),
|
||||||
|
/// std::io::stdout()
|
||||||
|
/// )
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn tui_output <
|
pub fn tui_output <
|
||||||
W: Write + Send + Sync + 'static, T: View<Tui> + Send + Sync + 'static
|
W: Write + Send + Sync + 'static, T: View<Tui> + Send + Sync + 'static
|
||||||
|
|
@ -68,7 +73,7 @@ pub fn tui_output <
|
||||||
})?)
|
})?)
|
||||||
}
|
}
|
||||||
|
|
||||||
use self::colors::*; mod colors {
|
pub use self::colors::*; mod colors {
|
||||||
use ratatui::prelude::Color;
|
use ratatui::prelude::Color;
|
||||||
pub const fn tui_color_bg () -> Color { Color::Rgb(28, 35, 25) }
|
pub const fn tui_color_bg () -> Color { Color::Rgb(28, 35, 25) }
|
||||||
pub const fn tui_bg0 () -> Color { Color::Rgb(20, 20, 20) }
|
pub const fn tui_bg0 () -> Color { Color::Rgb(20, 20, 20) }
|
||||||
|
|
@ -259,7 +264,7 @@ pub fn phat (w: u16, h: u16, [fg, bg, hi, lo]: [Color;4], draw: impl Draw<Tui>)
|
||||||
south(top, north(low, draw)).min_wh(w, h)
|
south(top, north(low, draw)).min_wh(w, h)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn x_scroll () -> impl Draw<Tui> {
|
pub fn x_scroll () -> impl Draw<Tui> {
|
||||||
thunk(|Tui(buf, XYWH(x1, y1, w, h)): &mut Tui|{
|
thunk(|Tui(buf, XYWH(x1, y1, w, h)): &mut Tui|{
|
||||||
let x2 = *x1 + *w;
|
let x2 = *x1 + *w;
|
||||||
for (i, x) in (*x1..=x2).enumerate() {
|
for (i, x) in (*x1..=x2).enumerate() {
|
||||||
|
|
@ -287,7 +292,7 @@ fn x_scroll () -> impl Draw<Tui> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn y_scroll () -> impl Draw<Tui> {
|
pub fn y_scroll () -> impl Draw<Tui> {
|
||||||
thunk(|Tui(buf, XYWH(x1, y1, w, h)): &mut Tui|{
|
thunk(|Tui(buf, XYWH(x1, y1, w, h)): &mut Tui|{
|
||||||
let y2 = *y1 + *h;
|
let y2 = *y1 + *h;
|
||||||
for (i, y) in (*y1..=y2).enumerate() {
|
for (i, y) in (*y1..=y2).enumerate() {
|
||||||
|
|
@ -315,19 +320,16 @@ fn y_scroll () -> impl Draw<Tui> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tui_update (
|
|
||||||
Tui(buf, ..): &mut Tui,
|
|
||||||
area: XYWH<u16>,
|
|
||||||
callback: &impl Fn(&mut Cell, u16, u16)
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Draw TUI content or its error message.
|
/// Draw TUI content or its error message.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let _ = tengri::term::catcher(Ok(Some("hello")));
|
/// for variant in [
|
||||||
/// let _ = tengri::term::catcher(Ok(None));
|
/// Ok(Some("hello")),
|
||||||
/// let _ = tengri::term::catcher(Err("draw fail".into()));
|
/// Ok(None),
|
||||||
|
/// Err("fail".into()),
|
||||||
|
/// ] {
|
||||||
|
/// let _ = tengri::catcher(variant);
|
||||||
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn catcher <T: Draw<Tui>> (result: Usually<T>) -> impl Draw<Tui> {
|
pub fn catcher <T: Draw<Tui>> (result: Usually<T>) -> impl Draw<Tui> {
|
||||||
thunk(move|to: &mut Tui|match result {
|
thunk(move|to: &mut Tui|match result {
|
||||||
|
|
@ -341,3 +343,6 @@ pub fn catcher <T: Draw<Tui>> (result: Usually<T>) -> impl Draw<Tui> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_draw!(|self: u64, _to: Tui|{ todo!() });
|
||||||
|
impl_draw!(|self: f64, _to: Tui|{ todo!() });
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue