mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
the wild Layout trait appears
This commit is contained in:
parent
7c652135ad
commit
d37bd3e0c5
7 changed files with 576 additions and 595 deletions
|
|
@ -46,13 +46,13 @@ pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
||||||
fn area_mut (&mut self) -> &mut [u16;4] {
|
fn area_mut (&mut self) -> &mut [u16;4] {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
}
|
}
|
||||||
fn render_in (&mut self, _: [u16;4], _: &dyn Render<TestEngine>) -> Usually<()> {
|
fn render_in (&mut self, _: [u16;4], _: &impl Render<TestEngine>) -> Usually<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Render<TestEngine> for String {
|
impl Render<TestEngine> for String {
|
||||||
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
|
fn render (&self, to: &mut TestOutput) {
|
||||||
Ok(Some([self.len() as u16, 1]))
|
to.area_mut().set_w(self.len() as u16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -62,9 +62,9 @@ pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
||||||
use crate::tui::*;
|
use crate::tui::*;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
struct TestComponent(String);
|
struct TestComponent(String);
|
||||||
impl Content<Tui> for TestComponent {
|
impl Layout<Tui> for TestComponent {
|
||||||
fn content (&self) -> Option<impl Render<Tui>> {
|
fn layout (&self) -> Option<impl Render<Tui>> {
|
||||||
Some(&self.0)
|
Some(self.0.as_str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Handle<Tui> for TestComponent {
|
impl Handle<Tui> for TestComponent {
|
||||||
|
|
|
||||||
|
|
@ -7,158 +7,212 @@ pub trait Output<E: Engine> {
|
||||||
fn area (&self) -> E::Area;
|
fn area (&self) -> E::Area;
|
||||||
/// Mutable pointer to area
|
/// Mutable pointer to area
|
||||||
fn area_mut (&mut self) -> &mut E::Area;
|
fn area_mut (&mut self) -> &mut E::Area;
|
||||||
/// Render widget in area
|
///// Render widget in area
|
||||||
fn render_in (&mut self, area: E::Area, widget: &impl Render<E>) -> Usually<()>;
|
fn render_in (&mut self, area: E::Area, widget: &impl Render<E>) -> Usually<()>;
|
||||||
|
|
||||||
|
#[inline] fn x (&self) -> E::Unit { self.area().x() }
|
||||||
|
#[inline] fn y (&self) -> E::Unit { self.area().y() }
|
||||||
|
#[inline] fn w (&self) -> E::Unit { self.area().w() }
|
||||||
|
#[inline] fn h (&self) -> E::Unit { self.area().h() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Something that can be represented by a renderable component.
|
pub trait Layout<E: Engine>: Send + Sync {
|
||||||
pub trait Content<E: Engine>: Send + Sync {
|
fn layout (&self) -> Option<impl Render<E>> {
|
||||||
fn content (&self) -> Option<impl Render<E>>;
|
None::<()>
|
||||||
}
|
|
||||||
impl<E: Engine, C: Content<E>> Content<E> for &C {
|
|
||||||
fn content (&self) -> Option<impl Render<E>> {
|
|
||||||
(*self).content()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Something that writes to an [Output].
|
impl<E: Engine> Layout<E> for () {}
|
||||||
|
|
||||||
|
impl<E: Engine, L: Layout<E>> Layout<E> for &L {}
|
||||||
|
|
||||||
pub trait Render<E: Engine>: Send + Sync {
|
pub trait Render<E: Engine>: Send + Sync {
|
||||||
/// Minimum size to use
|
fn render (&self, _: &mut E::Output);
|
||||||
fn min_size (&self, _: E::Size) -> Perhaps<E::Size> {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
/// Draw to output render target
|
|
||||||
fn render (&self, _: &mut E::Output) -> Usually<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl<E: Engine> Render<E> for &dyn Render<E> {
|
|
||||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> { (*self).min_size(to) }
|
impl<E: Engine, L: Layout<E>> Render<E> for L {
|
||||||
fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) }
|
fn render (&self, to: &mut E::Output) {
|
||||||
}
|
if let Some(content) = self.layout() {
|
||||||
impl<E: Engine, R: Render<E>> Render<E> for &R {
|
content.render(to)
|
||||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> { (*self).min_size(to) }
|
|
||||||
fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) }
|
|
||||||
}
|
|
||||||
impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
|
|
||||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
|
||||||
if let Some(content) = self {
|
|
||||||
content.min_size(to)
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
||||||
if let Some(content) = self {
|
|
||||||
content.render(to)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Define custom content for a struct.
|
//impl<E: Engine, L: Layout<E>> Layout<E> for &L {}
|
||||||
///
|
|
||||||
/// This code wires the `Content` and `Render` traits together,
|
|
||||||
/// since the only way to have the cake and eat it too is by
|
|
||||||
/// implementing both traits for a given renderable.
|
|
||||||
#[macro_export] macro_rules! render {
|
|
||||||
|
|
||||||
// Implement from [Content] for all [Engine]s
|
///// Something that can be represented by a renderable component.
|
||||||
(|$self:ident:$Struct:ident$(<$($L:lifetime),*E$(,$T:ident$(:$U:path)?)*$(,)?>)?|$cb:expr) => {
|
//pub trait Content<E: Engine>: Send + Sync {
|
||||||
impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Content<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
//fn content (&self) -> Option<impl Render<E>>;
|
||||||
fn content (&$self) -> Option<impl Render<$E>> { Some($cb) }
|
//}
|
||||||
}
|
//impl<E: Engine, C: Content<E>> Content<E> for &C {
|
||||||
impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Render<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
//fn content (&self) -> Option<impl Render<E>> {
|
||||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
//(*self).content()
|
||||||
self.content().unwrap().min_size(to)
|
//}
|
||||||
}
|
//}
|
||||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
||||||
self.content().unwrap().render(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Implement from [min_size] and [render] callbacks for all engines
|
///// Something that writes to an [Output].
|
||||||
($Struct:ident$(<$($L:lifetime),*E$(,$T:ident$(:$U:path)?)*$(,)?>)?
|
//pub trait Render<E: Engine>: Send + Sync {
|
||||||
|$self1:ident, $to1:ident|$min_size:expr,
|
///// Minimum size to use
|
||||||
|$self2:ident, $to2:ident|$render:expr) =>
|
//fn min_size (&self, _: E::Size) -> Perhaps<E::Size> {
|
||||||
{
|
//Ok(None)
|
||||||
impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Content<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
//}
|
||||||
fn content (&self) -> Option<impl Render<E>> { Some(self) }
|
///// Draw to output render target
|
||||||
}
|
//fn render (&self, _: &mut E::Output) -> Usually<()> {
|
||||||
impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Render<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
//Ok(())
|
||||||
fn min_size (&$self1, $to1: E::Size) -> Perhaps<E::Size> { $min_size }
|
//}
|
||||||
fn render (&$self2, $to2: &mut E::Output) -> Usually<()> { $render }
|
//}
|
||||||
}
|
//impl<E: Engine> Render<E> for &dyn Render<E> {
|
||||||
};
|
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> { (*self).min_size(to) }
|
||||||
|
//fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) }
|
||||||
|
//}
|
||||||
|
//impl<E: Engine, R: Render<E>> Render<E> for &R {
|
||||||
|
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> { (*self).min_size(to) }
|
||||||
|
//fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) }
|
||||||
|
//}
|
||||||
|
//impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
|
||||||
|
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
//if let Some(content) = self {
|
||||||
|
//content.min_size(to)
|
||||||
|
//} else {
|
||||||
|
//Ok(None)
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
//if let Some(content) = self {
|
||||||
|
//content.render(to)?;
|
||||||
|
//}
|
||||||
|
//Ok(())
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
// Implement from [Content] for a particular [Engine]
|
///// Define custom content for a struct.
|
||||||
(<$E:ty>|$self:ident:$Struct:ident$(<
|
/////
|
||||||
$($($L:lifetime),+)?
|
///// This code wires the `Content` and `Render` traits together,
|
||||||
$($($T:ident$(:$U:path)?),+)?
|
///// since the only way to have the cake and eat it too is by
|
||||||
>)?|$cb:expr) => {
|
///// implementing both traits for a given renderable.
|
||||||
impl $(<
|
//#[macro_export] macro_rules! render {
|
||||||
$($($L),+)?
|
|
||||||
$($($T$(:$U)?),+)?
|
|
||||||
>)? Content<$E> for $Struct $(<
|
|
||||||
$($($L),+)?
|
|
||||||
$($($T),+)?
|
|
||||||
>)? {
|
|
||||||
fn content (&$self) -> Option<impl Render<$E>> {
|
|
||||||
Some($cb)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl $(<
|
|
||||||
$($($L),+)?
|
|
||||||
$($($T$(:$U)?),+)?
|
|
||||||
>)? Render<$E> for $Struct $(<
|
|
||||||
$($($L),+)?
|
|
||||||
$($($T),+)?
|
|
||||||
>)? {
|
|
||||||
fn min_size (&self, to: <$E as Engine>::Size) -> Perhaps<<$E as Engine>::Size> {
|
|
||||||
self.content().map(|content|content.min_size(to)).unwrap_or(Ok(None))
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut <$E as Engine>::Output) -> Usually<()> {
|
|
||||||
self.content().map(|content|content.render(to)).unwrap_or(Ok(()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Implement from [min_size] and [render] callbacks for a particular [Engine]
|
//// Implement from [Content] for all [Engine]s
|
||||||
(<$E:ty>($self:ident:$Struct:ident$(<$($L:lifetime),*$(,$T:ident$(:$U:path)?)*$(,)?>)?)
|
//(|$self:ident:$Struct:ident$(<$($L:lifetime),*E$(,$T:ident$(:$U:path)?)*$(,)?>)?|$cb:expr) => {
|
||||||
|$to1:ident|$min_size:expr, |$to2:ident|$render:expr) =>
|
//impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Content<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
||||||
{
|
//fn content (&$self) -> Option<impl Render<$E>> { Some($cb) }
|
||||||
impl $(<
|
//}
|
||||||
$($L),* $($($T$(:$U)?),+)?
|
//impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Render<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
||||||
>)? Content<$E> for $Struct $(<
|
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
$($L),* $($($T),+)?
|
//self.content().unwrap().min_size(to)
|
||||||
>)? {
|
//}
|
||||||
fn content (&self) -> Option<impl Render<$E>> { Some(self) }
|
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
}
|
//self.content().unwrap().render(to)
|
||||||
impl $(<
|
//}
|
||||||
$($L),* $($($T$(:$U)?),+)?
|
//}
|
||||||
>)? Render<$E> for $Struct $(<
|
//};
|
||||||
$($L),* $($($T),+)?
|
|
||||||
>)? {
|
|
||||||
fn min_size (&$self, $to1: <$E as Engine>::Size) -> Perhaps<<$E as Engine>::Size> {
|
|
||||||
$min_size
|
|
||||||
}
|
|
||||||
fn render (&$self, $to2: &mut <$E as Engine>::Output) -> Usually<()> {
|
|
||||||
$render
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
//// Implement from [min_size] and [render] callbacks for all engines
|
||||||
|
//($Struct:ident$(<$($L:lifetime),*E$(,$T:ident$(:$U:path)?)*$(,)?>)?
|
||||||
|
//|$self1:ident, $to1:ident|$min_size:expr,
|
||||||
|
//|$self2:ident, $to2:ident|$render:expr) =>
|
||||||
|
//{
|
||||||
|
//impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Content<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
||||||
|
//fn content (&self) -> Option<impl Render<E>> { Some(self) }
|
||||||
|
//}
|
||||||
|
//impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Render<E> for $Struct $(<$($L,)* E, $($T),*>)? {
|
||||||
|
//fn min_size (&$self1, $to1: E::Size) -> Perhaps<E::Size> { $min_size }
|
||||||
|
//fn render (&$self2, $to2: &mut E::Output) -> Usually<()> { $render }
|
||||||
|
//}
|
||||||
|
//};
|
||||||
|
|
||||||
//impl<E: Engine, C: Content<E>> Content<E> for &mut C {}
|
//// Implement from [Content] for a particular [Engine]
|
||||||
//impl<E: Engine, C: Content<E>> Content<E> for Option<C> {}
|
//(<$E:ty>|$self:ident:$Struct:ident$(<
|
||||||
//impl<E: Engine, C: Content<E>> Content<E> for Arc<C> {}
|
//$($($L:lifetime),+)?
|
||||||
//impl<E: Engine, C: Content<E>> Content<E> for Mutex<C> {}
|
//$($($T:ident$(:$U:path)?),+)?
|
||||||
//impl<E: Engine, C: Content<E>> Content<E> for RwLock<C> {}
|
//>)?|$cb:expr) => {
|
||||||
|
//impl $(<
|
||||||
|
//$($($L),+)?
|
||||||
|
//$($($T$(:$U)?),+)?
|
||||||
|
//>)? Content<$E> for $Struct $(<
|
||||||
|
//$($($L),+)?
|
||||||
|
//$($($T),+)?
|
||||||
|
//>)? {
|
||||||
|
//fn content (&$self) -> Option<impl Render<$E>> {
|
||||||
|
//Some($cb)
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//impl $(<
|
||||||
|
//$($($L),+)?
|
||||||
|
//$($($T$(:$U)?),+)?
|
||||||
|
//>)? Render<$E> for $Struct $(<
|
||||||
|
//$($($L),+)?
|
||||||
|
//$($($T),+)?
|
||||||
|
//>)? {
|
||||||
|
//fn min_size (&self, to: <$E as Engine>::Size) -> Perhaps<<$E as Engine>::Size> {
|
||||||
|
//self.content().map(|content|content.min_size(to)).unwrap_or(Ok(None))
|
||||||
|
//}
|
||||||
|
//fn render (&self, to: &mut <$E as Engine>::Output) -> Usually<()> {
|
||||||
|
//self.content().map(|content|content.render(to)).unwrap_or(Ok(()))
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//};
|
||||||
|
|
||||||
//impl<E: Engine, C: Content<E>> Render<E> for C {}
|
//// Implement from [min_size] and [render] callbacks for a particular [Engine]
|
||||||
|
//(<$E:ty>($self:ident:$Struct:ident$(<$($L:lifetime),*$(,$T:ident$(:$U:path)?)*$(,)?>)?)
|
||||||
|
//|$to1:ident|$min_size:expr, |$to2:ident|$render:expr) =>
|
||||||
|
//{
|
||||||
|
//impl $(<
|
||||||
|
//$($L),* $($($T$(:$U)?),+)?
|
||||||
|
//>)? Content<$E> for $Struct $(<
|
||||||
|
//$($L),* $($($T),+)?
|
||||||
|
//>)? {
|
||||||
|
//fn content (&self) -> Option<impl Render<$E>> { Some(self) }
|
||||||
|
//}
|
||||||
|
//impl $(<
|
||||||
|
//$($L),* $($($T$(:$U)?),+)?
|
||||||
|
//>)? Render<$E> for $Struct $(<
|
||||||
|
//$($L),* $($($T),+)?
|
||||||
|
//>)? {
|
||||||
|
//fn min_size (&$self, $to1: <$E as Engine>::Size) -> Perhaps<<$E as Engine>::Size> {
|
||||||
|
//$min_size
|
||||||
|
//}
|
||||||
|
//fn render (&$self, $to2: &mut <$E as Engine>::Output) -> Usually<()> {
|
||||||
|
//$render
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
////impl<E: Engine, C: Content<E>> Content<E> for &mut C {}
|
||||||
|
////impl<E: Engine, C: Content<E>> Content<E> for Option<C> {}
|
||||||
|
////impl<E: Engine, C: Content<E>> Content<E> for Arc<C> {}
|
||||||
|
////impl<E: Engine, C: Content<E>> Content<E> for Mutex<C> {}
|
||||||
|
////impl<E: Engine, C: Content<E>> Content<E> for RwLock<C> {}
|
||||||
|
|
||||||
|
////impl<E: Engine, C: Content<E>> Render<E> for C {}
|
||||||
|
|
||||||
|
////impl<E: Engine, C: Content<E>> Render<E> for C {
|
||||||
|
/////// Minimum size to use
|
||||||
|
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
////self.content().map(|content|content.min_size(to))
|
||||||
|
////.unwrap_or(Ok(None))
|
||||||
|
////}
|
||||||
|
/////// Draw to output render target
|
||||||
|
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
////self.content().map(|content|content.render(to))
|
||||||
|
////.unwrap_or(Ok(()))
|
||||||
|
////}
|
||||||
|
////}
|
||||||
|
|
||||||
|
//[>***
|
||||||
|
|
||||||
|
|
||||||
|
//impl<E: Engine, R: Render<E> + Send + Sync> Content<E> for R {}
|
||||||
|
|
||||||
|
////impl<E: Engine, R: Render<E>> Content<E> for R {
|
||||||
|
////fn content (&self) -> Option<impl Render<E>> {
|
||||||
|
////Some(self)
|
||||||
|
////}
|
||||||
|
////}
|
||||||
|
|
||||||
|
///// All implementors of [Content] can be [Render]ed.
|
||||||
//impl<E: Engine, C: Content<E>> Render<E> for C {
|
//impl<E: Engine, C: Content<E>> Render<E> for C {
|
||||||
///// Minimum size to use
|
///// Minimum size to use
|
||||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
|
@ -172,65 +226,20 @@ impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
|
|
||||||
/****
|
////impl<E: Engine, C: Content<E>> Content<E> for &C {
|
||||||
|
////fn content (&self) -> Option<impl Render<E>> {
|
||||||
|
////Some(self)
|
||||||
|
////}
|
||||||
|
////}
|
||||||
|
|
||||||
|
////impl<E: Engine, C: Content<E>> Content<E> for Option<C> {
|
||||||
|
////fn content (&self) -> Option<impl Render<E>> {
|
||||||
|
////Some(self)
|
||||||
|
////}
|
||||||
|
////}
|
||||||
|
|
||||||
|
|
||||||
impl<E: Engine, R: Render<E> + Send + Sync> Content<E> for R {}
|
//impl<E: Engine, R: Render<E>> Render<E> for &R {
|
||||||
|
|
||||||
//impl<E: Engine, R: Render<E>> Content<E> for R {
|
|
||||||
//fn content (&self) -> Option<impl Render<E>> {
|
|
||||||
//Some(self)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// All implementors of [Content] can be [Render]ed.
|
|
||||||
impl<E: Engine, C: Content<E>> Render<E> for C {
|
|
||||||
/// Minimum size to use
|
|
||||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
|
||||||
self.content().map(|content|content.min_size(to))
|
|
||||||
.unwrap_or(Ok(None))
|
|
||||||
}
|
|
||||||
/// Draw to output render target
|
|
||||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
||||||
self.content().map(|content|content.render(to))
|
|
||||||
.unwrap_or(Ok(()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//impl<E: Engine, C: Content<E>> Content<E> for &C {
|
|
||||||
//fn content (&self) -> Option<impl Render<E>> {
|
|
||||||
//Some(self)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
//impl<E: Engine, C: Content<E>> Content<E> for Option<C> {
|
|
||||||
//fn content (&self) -> Option<impl Render<E>> {
|
|
||||||
//Some(self)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
impl<E: Engine, R: Render<E>> Render<E> for &R {
|
|
||||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
|
||||||
(*self).min_size(to)
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
||||||
(*self).render(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
|
|
||||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
|
||||||
self.map(|content|content.min_size(to))
|
|
||||||
.unwrap_or(Ok(None))
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
||||||
self.map(|content|content.render(to))
|
|
||||||
.unwrap_or(Ok(()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//impl<E: Engine> Render<E> for &dyn Render<E> {
|
|
||||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
//(*self).min_size(to)
|
//(*self).min_size(to)
|
||||||
//}
|
//}
|
||||||
|
|
@ -239,124 +248,144 @@ impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//impl<E: Engine> Render<E> for &mut dyn Render<E> {
|
//impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
|
||||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
//(*self).min_size(to)
|
//self.map(|content|content.min_size(to))
|
||||||
|
//.unwrap_or(Ok(None))
|
||||||
//}
|
//}
|
||||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
//(*self).render(to)
|
//self.map(|content|content.render(to))
|
||||||
|
//.unwrap_or(Ok(()))
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//impl<E: Engine> Render<E> for Box<dyn Render<E> + '_> {
|
////impl<E: Engine> Render<E> for &dyn Render<E> {
|
||||||
|
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
////(*self).min_size(to)
|
||||||
|
////}
|
||||||
|
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
////(*self).render(to)
|
||||||
|
////}
|
||||||
|
////}
|
||||||
|
|
||||||
|
////impl<E: Engine> Render<E> for &mut dyn Render<E> {
|
||||||
|
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
////(*self).min_size(to)
|
||||||
|
////}
|
||||||
|
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
////(*self).render(to)
|
||||||
|
////}
|
||||||
|
////}
|
||||||
|
|
||||||
|
////impl<E: Engine> Render<E> for Box<dyn Render<E> + '_> {
|
||||||
|
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
////(**self).min_size(to)
|
||||||
|
////}
|
||||||
|
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
////(**self).render(to)
|
||||||
|
////}
|
||||||
|
////}
|
||||||
|
|
||||||
|
////impl<E: Engine, W: Render<E>> Render<E> for Arc<W> {
|
||||||
|
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
////self.as_ref().min_size(to)
|
||||||
|
////}
|
||||||
|
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
////self.as_ref().render(to)
|
||||||
|
////}
|
||||||
|
////}
|
||||||
|
|
||||||
|
////impl<E: Engine, W: Render<E>> Render<E> for Mutex<W> {
|
||||||
|
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
////self.lock().unwrap().min_size(to)
|
||||||
|
////}
|
||||||
|
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
////self.lock().unwrap().render(to)
|
||||||
|
////}
|
||||||
|
////}
|
||||||
|
|
||||||
|
////impl<E: Engine, W: Render<E>> Render<E> for RwLock<W> {
|
||||||
|
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
////self.read().unwrap().min_size(to)
|
||||||
|
////}
|
||||||
|
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
////self.read().unwrap().render(to)
|
||||||
|
////}
|
||||||
|
////}
|
||||||
|
|
||||||
|
////impl<E: Engine, W: Render<E>> Render<E> for Option<W> {
|
||||||
|
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
|
////Ok(self.as_ref().map(|widget|widget.min_size(to)).transpose()?.flatten())
|
||||||
|
////}
|
||||||
|
////fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
|
////self.as_ref().map(|widget|widget.render(to)).unwrap_or(Ok(()))
|
||||||
|
////}
|
||||||
|
////}
|
||||||
|
|
||||||
|
///// Cast to dynamic pointer
|
||||||
|
//pub fn widget <E, T> (w: &T) -> &dyn Render<E>
|
||||||
|
//where E: Engine, T: Render<E>
|
||||||
|
//{
|
||||||
|
//w as &dyn Render<E>
|
||||||
|
//}
|
||||||
|
|
||||||
|
///// Ad-hoc widget with custom rendering.
|
||||||
|
//pub fn render <E, F> (render: F) -> impl Render<E>
|
||||||
|
//where E: Engine, F: Fn(&mut E::Output)->Usually<()>+Send+Sync
|
||||||
|
//{
|
||||||
|
//Widget::new(|_|Ok(Some([0.into(),0.into()].into())), render)
|
||||||
|
//}
|
||||||
|
|
||||||
|
///// A custom [Render] defined by passing layout and render closures in place.
|
||||||
|
//pub struct Widget<
|
||||||
|
//E: Engine,
|
||||||
|
//L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
|
||||||
|
//R: Send + Sync + Fn(&mut E::Output)->Usually<()>
|
||||||
|
//>(L, R, PhantomData<E>);
|
||||||
|
|
||||||
|
//impl<
|
||||||
|
//E: Engine,
|
||||||
|
//L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
|
||||||
|
//R: Send + Sync + Fn(&mut E::Output)->Usually<()>
|
||||||
|
//> Widget<E, L, R> {
|
||||||
|
//pub fn new (layout: L, render: R) -> Self {
|
||||||
|
//Self(layout, render, Default::default())
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
//impl<
|
||||||
|
//E: Engine,
|
||||||
|
//L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
|
||||||
|
//R: Send + Sync + Fn(&mut E::Output)->Usually<()>
|
||||||
|
//> Render<E> for Widget<E, L, R> {
|
||||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||||
//(**self).min_size(to)
|
//self.0(to)
|
||||||
//}
|
//}
|
||||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||||
//(**self).render(to)
|
//self.1(to)
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//impl<E: Engine, W: Render<E>> Render<E> for Arc<W> {
|
///// Has static methods for conditional rendering,
|
||||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
///// in unary and binary forms.
|
||||||
//self.as_ref().min_size(to)
|
//pub struct Cond;
|
||||||
|
|
||||||
|
//impl Cond {
|
||||||
|
///// Render `item` when `cond` is true.
|
||||||
|
//pub fn when <E: Engine, A: Render<E>> (cond: bool, item: A) -> When<E, A> {
|
||||||
|
//When(cond, item, Default::default())
|
||||||
//}
|
//}
|
||||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
///// Render `item` if `cond` is true, otherwise render `other`.
|
||||||
//self.as_ref().render(to)
|
//pub fn either <E: Engine, A: Render<E>, B: Render<E>> (cond: bool, item: A, other: B) -> Either<E, A, B> {
|
||||||
|
//Either(cond, item, other, Default::default())
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//impl<E: Engine, W: Render<E>> Render<E> for Mutex<W> {
|
///// Renders `self.1` when `self.0` is true.
|
||||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
//pub struct When<E: Engine, A: Render<E>>(bool, A, PhantomData<E>);
|
||||||
//self.lock().unwrap().min_size(to)
|
|
||||||
//}
|
|
||||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
||||||
//self.lock().unwrap().render(to)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
//impl<E: Engine, W: Render<E>> Render<E> for RwLock<W> {
|
///// Renders `self.1` when `self.0` is true, otherwise renders `self.2`
|
||||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
//pub struct Either<E: Engine, A: Render<E>, B: Render<E>>(bool, A, B, PhantomData<E>);
|
||||||
//self.read().unwrap().min_size(to)
|
|
||||||
//}
|
|
||||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
||||||
//self.read().unwrap().render(to)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
//impl<E: Engine, W: Render<E>> Render<E> for Option<W> {
|
|
||||||
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
|
||||||
//Ok(self.as_ref().map(|widget|widget.min_size(to)).transpose()?.flatten())
|
|
||||||
//}
|
|
||||||
//fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
||||||
//self.as_ref().map(|widget|widget.render(to)).unwrap_or(Ok(()))
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// Cast to dynamic pointer
|
|
||||||
pub fn widget <E, T> (w: &T) -> &dyn Render<E>
|
|
||||||
where E: Engine, T: Render<E>
|
|
||||||
{
|
|
||||||
w as &dyn Render<E>
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ad-hoc widget with custom rendering.
|
|
||||||
pub fn render <E, F> (render: F) -> impl Render<E>
|
|
||||||
where E: Engine, F: Fn(&mut E::Output)->Usually<()>+Send+Sync
|
|
||||||
{
|
|
||||||
Widget::new(|_|Ok(Some([0.into(),0.into()].into())), render)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A custom [Render] defined by passing layout and render closures in place.
|
|
||||||
pub struct Widget<
|
|
||||||
E: Engine,
|
|
||||||
L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
|
|
||||||
R: Send + Sync + Fn(&mut E::Output)->Usually<()>
|
|
||||||
>(L, R, PhantomData<E>);
|
|
||||||
|
|
||||||
impl<
|
|
||||||
E: Engine,
|
|
||||||
L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
|
|
||||||
R: Send + Sync + Fn(&mut E::Output)->Usually<()>
|
|
||||||
> Widget<E, L, R> {
|
|
||||||
pub fn new (layout: L, render: R) -> Self {
|
|
||||||
Self(layout, render, Default::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<
|
|
||||||
E: Engine,
|
|
||||||
L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
|
|
||||||
R: Send + Sync + Fn(&mut E::Output)->Usually<()>
|
|
||||||
> Render<E> for Widget<E, L, R> {
|
|
||||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
|
||||||
self.0(to)
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
||||||
self.1(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Has static methods for conditional rendering,
|
|
||||||
/// in unary and binary forms.
|
|
||||||
pub struct Cond;
|
|
||||||
|
|
||||||
impl Cond {
|
|
||||||
/// Render `item` when `cond` is true.
|
|
||||||
pub fn when <E: Engine, A: Render<E>> (cond: bool, item: A) -> When<E, A> {
|
|
||||||
When(cond, item, Default::default())
|
|
||||||
}
|
|
||||||
/// Render `item` if `cond` is true, otherwise render `other`.
|
|
||||||
pub fn either <E: Engine, A: Render<E>, B: Render<E>> (cond: bool, item: A, other: B) -> Either<E, A, B> {
|
|
||||||
Either(cond, item, other, Default::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Renders `self.1` when `self.0` is true.
|
|
||||||
pub struct When<E: Engine, A: Render<E>>(bool, A, PhantomData<E>);
|
|
||||||
|
|
||||||
/// Renders `self.1` when `self.0` is true, otherwise renders `self.2`
|
|
||||||
pub struct Either<E: Engine, A: Render<E>, B: Render<E>>(bool, A, B, PhantomData<E>);
|
|
||||||
|
|
||||||
|
|
||||||
**/
|
//**/
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ impl Tui {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TuiRun<R: Render<Tui> + Handle<Tui> + Sized + 'static> {
|
pub trait TuiRun<R: Layout<Tui> + Handle<Tui> + Sized + 'static> {
|
||||||
/// Run an app in the main loop.
|
/// Run an app in the main loop.
|
||||||
fn run (&self, state: &Arc<RwLock<R>>) -> Usually<()>;
|
fn run (&self, state: &Arc<RwLock<R>>) -> Usually<()>;
|
||||||
/// Spawn the input thread.
|
/// Spawn the input thread.
|
||||||
|
|
@ -98,7 +98,7 @@ pub trait TuiRun<R: Render<Tui> + Handle<Tui> + Sized + 'static> {
|
||||||
fn run_output (&self, state: &Arc<RwLock<R>>, sleep: Duration) -> JoinHandle<()>;
|
fn run_output (&self, state: &Arc<RwLock<R>>, sleep: Duration) -> JoinHandle<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Render<Tui> + Handle<Tui> + Sized + 'static> TuiRun<T> for Arc<RwLock<Tui>> {
|
impl<T: Layout<Tui> + Handle<Tui> + Sized + 'static> TuiRun<T> for Arc<RwLock<Tui>> {
|
||||||
fn run (&self, state: &Arc<RwLock<T>>) -> Usually<()> {
|
fn run (&self, state: &Arc<RwLock<T>>) -> Usually<()> {
|
||||||
let _input_thread = self.run_input(state, Duration::from_millis(100));
|
let _input_thread = self.run_input(state, Duration::from_millis(100));
|
||||||
self.write().unwrap().setup()?;
|
self.write().unwrap().setup()?;
|
||||||
|
|
@ -151,7 +151,7 @@ impl<T: Render<Tui> + Handle<Tui> + Sized + 'static> TuiRun<T> for Arc<RwLock<Tu
|
||||||
buffer.reset();
|
buffer.reset();
|
||||||
}
|
}
|
||||||
let mut output = TuiOutput { buffer, area: [0, 0, width, height] };
|
let mut output = TuiOutput { buffer, area: [0, 0, width, height] };
|
||||||
state.render(&mut output).expect("render failed");
|
state.render(&mut output);
|
||||||
buffer = engine.write().unwrap().flip(output.buffer, size);
|
buffer = engine.write().unwrap().flip(output.buffer, size);
|
||||||
}
|
}
|
||||||
std::thread::sleep(sleep);
|
std::thread::sleep(sleep);
|
||||||
|
|
@ -257,7 +257,7 @@ impl Output<Tui> for TuiOutput {
|
||||||
#[inline] fn render_in (&mut self, area: [u16;4], widget: &impl Render<Tui>) -> Usually<()> {
|
#[inline] fn render_in (&mut self, area: [u16;4], widget: &impl Render<Tui>) -> Usually<()> {
|
||||||
let last = self.area();
|
let last = self.area();
|
||||||
*self.area_mut() = area;
|
*self.area_mut() = area;
|
||||||
widget.render(self)?;
|
widget.render(self);
|
||||||
*self.area_mut() = last;
|
*self.area_mut() = last;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -331,26 +331,14 @@ pub fn half_block (lower: bool, upper: bool) -> Option<char> {
|
||||||
//impl<T: Content<Tui>> Render<Tui> for T {}
|
//impl<T: Content<Tui>> Render<Tui> for T {}
|
||||||
|
|
||||||
impl Render<Tui> for &str {
|
impl Render<Tui> for &str {
|
||||||
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
|
fn render (&self, to: &mut TuiOutput) {
|
||||||
// TODO: line breaks
|
to.blit(self, to.area.x(), to.area.y(), None)
|
||||||
Ok(Some([self.chars().count() as u16, 1]))
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
|
|
||||||
let [x, y, ..] = to.area();
|
|
||||||
//let [w, h] = self.min_size(to.area().wh())?.unwrap();
|
|
||||||
Ok(to.blit(&self, x, y, None))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render<Tui> for String {
|
impl Render<Tui> for String {
|
||||||
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
|
fn render (&self, to: &mut TuiOutput) {
|
||||||
// TODO: line breaks
|
to.blit(self, to.area.x(), to.area.y(), None)
|
||||||
Ok(Some([self.chars().count() as u16, 1]))
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
|
|
||||||
let [x, y, ..] = to.area();
|
|
||||||
//let [w, h] = self.min_size(to.area().wh())?.unwrap();
|
|
||||||
Ok(to.blit(&self, x, y, None))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
254
layout/Cargo.lock
generated
254
layout/Cargo.lock
generated
|
|
@ -41,7 +41,7 @@ dependencies = [
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
"object",
|
"object",
|
||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -83,13 +83,14 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "compact_str"
|
name = "compact_str"
|
||||||
version = "0.7.1"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f"
|
checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"castaway",
|
"castaway",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"itoa",
|
"itoa",
|
||||||
|
"rustversion",
|
||||||
"ryu",
|
"ryu",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
@ -108,15 +109,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossterm"
|
name = "crossterm"
|
||||||
version = "0.27.0"
|
version = "0.28.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
|
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"crossterm_winapi",
|
"crossterm_winapi",
|
||||||
"libc",
|
|
||||||
"mio",
|
"mio",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"rustix",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"signal-hook-mio",
|
"signal-hook-mio",
|
||||||
"winapi",
|
"winapi",
|
||||||
|
|
@ -131,6 +132,47 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"darling_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"ident_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strsim",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diff"
|
||||||
|
version = "0.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.13.0"
|
version = "1.13.0"
|
||||||
|
|
@ -149,6 +191,22 @@ version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnv"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foldhash"
|
name = "foldhash"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
|
@ -179,12 +237,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "ident_case"
|
||||||
version = "0.12.1"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indoc"
|
||||||
|
version = "2.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instability"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "898e106451f7335950c9cc64f8ec67b5f65698679ac67ed00619aeef14e1cf75"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"darling",
|
||||||
|
"indoc",
|
||||||
|
"pretty_assertions",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -208,6 +283,12 @@ version = "0.2.169"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.12"
|
version = "0.4.12"
|
||||||
|
|
@ -250,14 +331,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.8.11"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"wasi",
|
"wasi",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -295,7 +376,7 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -304,6 +385,16 @@ version = "1.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pretty_assertions"
|
||||||
|
version = "1.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
|
||||||
|
dependencies = [
|
||||||
|
"diff",
|
||||||
|
"yansi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.92"
|
version = "1.0.92"
|
||||||
|
|
@ -324,22 +415,23 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ratatui"
|
name = "ratatui"
|
||||||
version = "0.26.3"
|
version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f44c9e68fd46eda15c646fbb85e1040b657a58cdc8c98db1d97a55930d991eef"
|
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cassowary",
|
"cassowary",
|
||||||
"compact_str",
|
"compact_str",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"itertools 0.12.1",
|
"indoc",
|
||||||
|
"instability",
|
||||||
|
"itertools",
|
||||||
"lru",
|
"lru",
|
||||||
"paste",
|
"paste",
|
||||||
"stability",
|
|
||||||
"strum",
|
"strum",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"unicode-truncate",
|
"unicode-truncate",
|
||||||
"unicode-width",
|
"unicode-width 0.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -357,6 +449,19 @@ version = "0.1.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.38.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.19"
|
version = "1.0.19"
|
||||||
|
|
@ -411,22 +516,18 @@ version = "1.13.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stability"
|
|
||||||
version = "0.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac"
|
|
||||||
dependencies = [
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strum"
|
name = "strum"
|
||||||
version = "0.26.3"
|
version = "0.26.3"
|
||||||
|
|
@ -494,9 +595,9 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf"
|
checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools 0.13.0",
|
"itertools",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"unicode-width",
|
"unicode-width 0.1.14",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -505,6 +606,12 @@ version = "0.1.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
|
@ -535,11 +642,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.48.0"
|
version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.48.5",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -548,22 +655,7 @@ version = "0.59.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.6",
|
"windows-targets",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-targets"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
|
||||||
dependencies = [
|
|
||||||
"windows_aarch64_gnullvm 0.48.5",
|
|
||||||
"windows_aarch64_msvc 0.48.5",
|
|
||||||
"windows_i686_gnu 0.48.5",
|
|
||||||
"windows_i686_msvc 0.48.5",
|
|
||||||
"windows_x86_64_gnu 0.48.5",
|
|
||||||
"windows_x86_64_gnullvm 0.48.5",
|
|
||||||
"windows_x86_64_msvc 0.48.5",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -572,46 +664,28 @@ version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm 0.52.6",
|
"windows_aarch64_gnullvm",
|
||||||
"windows_aarch64_msvc 0.52.6",
|
"windows_aarch64_msvc",
|
||||||
"windows_i686_gnu 0.52.6",
|
"windows_i686_gnu",
|
||||||
"windows_i686_gnullvm",
|
"windows_i686_gnullvm",
|
||||||
"windows_i686_msvc 0.52.6",
|
"windows_i686_msvc",
|
||||||
"windows_x86_64_gnu 0.52.6",
|
"windows_x86_64_gnu",
|
||||||
"windows_x86_64_gnullvm 0.52.6",
|
"windows_x86_64_gnullvm",
|
||||||
"windows_x86_64_msvc 0.52.6",
|
"windows_x86_64_msvc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_gnullvm"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnu"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
|
|
@ -624,50 +698,32 @@ version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnu"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnullvm"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yansi"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
||||||
|
|
|
||||||
|
|
@ -4,40 +4,26 @@ use crate::*;
|
||||||
pub struct Cond;
|
pub struct Cond;
|
||||||
|
|
||||||
impl Cond {
|
impl Cond {
|
||||||
/// Render `item` when `cond` is true.
|
/// Show an item conditionally.
|
||||||
pub fn when <E: Engine, A: Render<E>> (cond: bool, item: A) -> When<E, A> {
|
pub fn when <E: Engine> (cond: bool, item: Box<dyn Layout<E>>) -> When<E> {
|
||||||
When(cond, item, Default::default())
|
When(cond, item)
|
||||||
}
|
}
|
||||||
/// Render `item` if `cond` is true, otherwise render `other`.
|
/// Show either of two items.
|
||||||
pub fn either <E: Engine, A: Render<E>, B: Render<E>> (cond: bool, item: A, other: B) -> Either<E, A, B> {
|
pub fn either <E: Engine> (cond: bool, a: Box<dyn Layout<E>>, b: Box<dyn Layout<E>>) -> Either<E> {
|
||||||
Either(cond, item, other, Default::default())
|
Either(cond, a, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders `self.1` when `self.0` is true.
|
pub struct When<E>(bool, Box<dyn Layout<E>>);
|
||||||
pub struct When<E: Engine, A: Render<E>>(bool, A, PhantomData<E>);
|
impl<E: Engine> Layout<E> for When<E> {
|
||||||
|
fn layout (self, _: &mut E::Output) -> Option<Box<dyn Layout<E>>> {
|
||||||
impl<E: Engine, A: Render<E>> Render<E> for When<E, A> {
|
if self.0 { Some(self.1) } else { None }
|
||||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
|
||||||
let Self(cond, item, ..) = self;
|
|
||||||
if *cond { item.min_size(to) } else { Ok(Some([0.into(), 0.into()].into())) }
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
||||||
let Self(cond, item, ..) = self;
|
|
||||||
if *cond { item.render(to) } else { Ok(()) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders `self.1` when `self.0` is true, otherwise renders `self.2`
|
pub struct Either<E: Engine>(bool, Box<dyn Layout<E>>, Box<dyn Layout<E>>);
|
||||||
pub struct Either<E: Engine, A: Render<E>, B: Render<E>>(bool, A, B, PhantomData<E>);
|
impl<E: Engine> Layout<E> for Either<E> {
|
||||||
|
fn layout (self, _: &mut E::Output) -> Option<Box<dyn Layout<E>>> {
|
||||||
impl<E: Engine, A: Render<E>, B: Render<E>> Render<E> for Either<E, A, B> {
|
Some(if self.0 { self.1 } else { self.2 })
|
||||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
|
||||||
let Self(cond, item, other, ..) = self;
|
|
||||||
if *cond { item.min_size(to) } else { other.min_size(to) }
|
|
||||||
}
|
|
||||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
||||||
let Self(cond, item, other, ..) = self;
|
|
||||||
if *cond { item.render(to) } else { other.render(to) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use std::sync::{Arc, atomic::{AtomicUsize, Ordering::Relaxed}};
|
use std::sync::{Arc, atomic::{AtomicUsize, Ordering::Relaxed}};
|
||||||
|
|
||||||
|
// TODO: 🡘 🡙 ←🡙→ indicator to expand window when too small
|
||||||
|
|
||||||
impl Direction {
|
impl Direction {
|
||||||
pub fn is_north (&self) -> bool { matches!(self, Self::North) }
|
pub fn is_north (&self) -> bool { matches!(self, Self::North) }
|
||||||
pub fn is_south (&self) -> bool { matches!(self, Self::South) }
|
pub fn is_south (&self) -> bool { matches!(self, Self::South) }
|
||||||
|
|
@ -46,13 +48,12 @@ pub struct Measure<E: Engine> {
|
||||||
pub y: Arc<AtomicUsize>,
|
pub y: Arc<AtomicUsize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
render!(Measure<E>
|
impl<E: Engine> Render<E> for Measure<E> {
|
||||||
|self, layout|Ok(Some(layout)),
|
fn render (&self, to: &mut E::Output) {
|
||||||
|self, render|{
|
self.x.store(to.area().w().into(), Relaxed);
|
||||||
self.x.store(render.area().w().into(), Relaxed);
|
self.y.store(to.area().h().into(), Relaxed);
|
||||||
self.y.store(render.area().h().into(), Relaxed);
|
}
|
||||||
Ok(())
|
}
|
||||||
});
|
|
||||||
|
|
||||||
impl<E: Engine> Clone for Measure<E> {
|
impl<E: Engine> Clone for Measure<E> {
|
||||||
fn clone (&self) -> Self {
|
fn clone (&self) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ macro_rules! content_enum {
|
||||||
pub enum $Enum<E: Engine, T: Render<E>> {
|
pub enum $Enum<E: Engine, T: Render<E>> {
|
||||||
_Unused(PhantomData<E>), $($Variant(T)),+
|
_Unused(PhantomData<E>), $($Variant(T)),+
|
||||||
}
|
}
|
||||||
impl<E: Engine, T: Render<E>> Content<E> for $Enum<E, T> {
|
impl<E: Engine, T: Render<E>> $Enum<E, T> {
|
||||||
fn content (&self) -> Option<impl Render<E>> {
|
fn content (&self) -> Option<impl Render<E>> {
|
||||||
match self {
|
match self {
|
||||||
Self::_Unused(_) => None,
|
Self::_Unused(_) => None,
|
||||||
|
|
@ -25,36 +25,25 @@ macro_rules! content_enum {
|
||||||
/// Defines an enum that transforms its content
|
/// Defines an enum that transforms its content
|
||||||
/// along either the X axis, the Y axis, or both.
|
/// along either the X axis, the Y axis, or both.
|
||||||
macro_rules! transform_xy {
|
macro_rules! transform_xy {
|
||||||
($Enum:ident $(
|
(|$self:ident : $Enum:ident, $to:ident|$render:expr) => {
|
||||||
|$self1:ident, $to1:ident|$min_size:expr,
|
|
||||||
|$self2:ident, $to2:ident|$render:expr
|
|
||||||
)?) => {
|
|
||||||
content_enum!($Enum: X, Y, XY);
|
content_enum!($Enum: X, Y, XY);
|
||||||
impl<E: Engine, T: Render<E>> $Enum<E, T> {
|
impl<E: Engine, T: Render<E>> $Enum<E, T> {
|
||||||
pub fn x (item: T) -> Self { Self::X(item) }
|
pub fn x (item: T) -> Self { Self::X(item) }
|
||||||
pub fn y (item: T) -> Self { Self::Y(item) }
|
pub fn y (item: T) -> Self { Self::Y(item) }
|
||||||
pub fn xy (item: T) -> Self { Self::XY(item) }
|
pub fn xy (item: T) -> Self { Self::XY(item) }
|
||||||
}
|
}
|
||||||
$(
|
impl<E: Engine, T: Render<E>> Render<E> for $Enum<E, T> {
|
||||||
impl<E: Engine, T: Render<E>> Render<E> for $Enum<E, T> {
|
fn render (&$self, $to: &mut <E as Engine>::Output) {
|
||||||
fn min_size (&$self1, $to1: E::Size) -> Perhaps<E::Size> {
|
$render
|
||||||
$min_size
|
|
||||||
}
|
|
||||||
fn render (&$self2, $to2: &mut E::Output) -> Usually<()> {
|
|
||||||
$render
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)?
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines an enum that transforms its content parametrically
|
/// Defines an enum that transforms its content parametrically
|
||||||
/// along either the X axis, the Y axis, or both
|
/// along either the X axis, the Y axis, or both
|
||||||
macro_rules! transform_xy_unit {
|
macro_rules! transform_xy_unit {
|
||||||
($Enum:ident $(
|
(|$self:ident : $Enum:ident, $to:ident|$render:expr) => {
|
||||||
|$self1:ident, $to1:ident|$min_size:expr,
|
|
||||||
|$self2:ident, $to2:ident|$render:expr
|
|
||||||
)?) => {
|
|
||||||
pub enum $Enum<E: Engine, T: Render<E>> {
|
pub enum $Enum<E: Engine, T: Render<E>> {
|
||||||
X(E::Unit, T), Y(E::Unit, T), XY(E::Unit, E::Unit, T),
|
X(E::Unit, T), Y(E::Unit, T), XY(E::Unit, E::Unit, T),
|
||||||
}
|
}
|
||||||
|
|
@ -77,151 +66,83 @@ macro_rules! transform_xy_unit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<E: Engine, T: Render<E>> Content<E> for $Enum<E, T> {
|
impl<E: Engine, T: Render<E>> $Enum<E, T> {
|
||||||
fn content (&self) -> Option<impl Render<E>> {
|
fn content (&self) -> Option<impl Render<E>> {
|
||||||
Some(match self {
|
Some(match self {
|
||||||
Self::X(_, content) => content,
|
Self::X(_, content) => content,
|
||||||
Self::Y(_, content) => content,
|
Self::Y(_, content) => content,
|
||||||
Self::XY(_, _, content) => content,
|
Self::XY(_, _, content) => content,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$(
|
impl<E: Engine, T: Render<E>> Render<E> for $Enum<E, T> {
|
||||||
impl<E: Engine, T: Render<E>> Render<E> for $Enum<E, T> {
|
fn render (&$self, $to: &mut E::Output) -> Usually<()> {
|
||||||
fn min_size (&$self1, $to1: E::Size) -> Perhaps<E::Size> {
|
$render
|
||||||
$min_size
|
|
||||||
}
|
|
||||||
fn render (&$self2, $to2: &mut E::Output) -> Usually<()> {
|
|
||||||
$render
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)?
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
transform_xy!(Fill
|
transform_xy!(|self: Fill, to|todo!());
|
||||||
|self, to|{
|
|
||||||
let area = self.content().min_size(to.into())?;
|
|
||||||
if let Some(area) = area {
|
|
||||||
Ok(Some(match self {
|
|
||||||
Self::X(_) => [to.w().into(), area.h()],
|
|
||||||
Self::Y(_) => [area.w(), to.h().into()],
|
|
||||||
Self::XY(_) => [to.w().into(), to.h().into()],
|
|
||||||
_ => unreachable!(),
|
|
||||||
}.into()))
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|self, to|self.content().render(to));
|
|
||||||
|
|
||||||
transform_xy_unit!(Fixed
|
transform_xy_unit!(|self: Fixed, to|{
|
||||||
|self, to|{
|
let [x, y, w, h] = to.area().xywh();
|
||||||
Ok(match self {
|
to.render_in(match self {
|
||||||
Self::X(w, _) =>
|
Self::X(fw, _) => [x, y, fw, h],
|
||||||
if to.w() >= *w { Some([*w, to.h()].into()) } else { None },
|
Self::Y(fh, _) => [x, y, w, fh],
|
||||||
Self::Y(h, _) =>
|
Self::XY(fw, fh, _) => [x, y, fw, fh],
|
||||||
if to.h() >= *h { Some([to.w(), *h].into()) } else { None },
|
}, self.content())
|
||||||
Self::XY(w, h, _)
|
});
|
||||||
=> if to.w() >= *w && to.h() >= *h { Some([*w, *h].into()) } else { None },
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|self, to|{
|
|
||||||
// 🡘 🡙 ←🡙→
|
|
||||||
if let Some(size) = self.min_size(to.area().wh().into())? {
|
|
||||||
to.render_in(to.area().clip(size).into(), &self.content())
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
transform_xy_unit!(Shrink
|
transform_xy_unit!(|self: Shrink, to|to.render_in(
|
||||||
|self, to|Ok(self.content().min_size(to)?
|
[to.x(), to.y(), to.w().minus(self.dx()), to.h().minus(self.dy())],
|
||||||
.map(|wh|wh.wh())
|
self.content()));
|
||||||
.map(|[w, h]|[
|
|
||||||
w.minus(self.dx()).into(),
|
|
||||||
h.minus(self.dy()).into()
|
|
||||||
].into())),
|
|
||||||
|self, to|Ok(self.min_size(to.area().wh().into())?
|
|
||||||
.map(|size|to.render_in(to.area().clip(size).into(), &self.content()))
|
|
||||||
.transpose()?.unwrap_or(())));
|
|
||||||
|
|
||||||
transform_xy_unit!(Expand
|
transform_xy_unit!(|self: Expand, to|to.render_in(
|
||||||
|self, to|Ok(self.content().min_size(to)?.map(|to|match *self {
|
[to.x(), to.y(), to.w() + self.dx(), to.h() + self.dy()],
|
||||||
Self::X(w, _) => [to.w() + w, to.h()],
|
self.content()));
|
||||||
Self::Y(h, _) => [to.w(), to.h() + h],
|
|
||||||
Self::XY(w, h, _) => [to.w() + w, to.h() + h],
|
|
||||||
}.into())),
|
|
||||||
|self, to|Ok(self.min_size(to.area().wh().into())?
|
|
||||||
.map(|size|to.render_in(to.area().clip(size).into(), &self.content()))
|
|
||||||
.transpose()?.unwrap_or(())));
|
|
||||||
|
|
||||||
// TODO: 🡘 🡙 ←🡙→ indicator to expand window when too small
|
transform_xy_unit!(|self: Min, to|to.render_in(match self {
|
||||||
|
Self::X(mw, _) => [to.x(), to.y(), to.w().max(mw), to.h()],
|
||||||
|
Self::Y(mh, _) => [to.x(), to.y(), to.w(), to.h().max(mh)],
|
||||||
|
Self::XY(mw, mh, _) => [to.x(), to.y(), to.w().max(mw), to.h().max(mh)]
|
||||||
|
}, self.content()));
|
||||||
|
|
||||||
transform_xy_unit!(Min
|
transform_xy_unit!(|self: Max, to|to.render_in(match self {
|
||||||
|self, to|Ok(self.content().min_size(to)?.map(|to|match *self {
|
Self::X(mw, _) => [to.x(), to.y(), to.w().min(mw), to.h()],
|
||||||
Self::X(w, _) => [to.w().max(w), to.h()],
|
Self::Y(mh, _) => [to.x(), to.y(), to.w(), to.h().min(mh)],
|
||||||
Self::Y(h, _) => [to.w(), to.h().max(h)],
|
Self::XY(mw, mh, _) => [to.x(), to.y(), to.w().min(mw), to.h().min(mh)],
|
||||||
Self::XY(w, h, _) => [to.w().max(w), to.h().max(h)],
|
}, self.content()));
|
||||||
}.into())),
|
|
||||||
|self, to|Ok(self.min_size(to.area().wh().into())?
|
|
||||||
.map(|size|to.render_in(to.area().clip(size).into(), &self.content()))
|
|
||||||
.transpose()?.unwrap_or(())));
|
|
||||||
|
|
||||||
transform_xy_unit!(Max
|
transform_xy_unit!(|self: Push, to|to.render_in(
|
||||||
|self, to|Ok(self.content().min_size(to)?.map(|to|match *self {
|
[to.x() + self.dx(), to.y() + self.dy(), to.w(), to.h()],
|
||||||
Self::X(w, _) => [to.w().min(w), to.h()],
|
self.content()));
|
||||||
Self::Y(h, _) => [to.w(), to.h().min(h)],
|
|
||||||
Self::XY(w, h, _) => [to.w().min(w), to.h().min(h)],
|
|
||||||
}.into())),
|
|
||||||
|self, to|Ok(self.min_size(to.area().wh().into())?
|
|
||||||
.map(|size|to.render_in(to.area().clip(size).into(), &self.content()))
|
|
||||||
.transpose()?.unwrap_or(())));
|
|
||||||
|
|
||||||
transform_xy_unit!(Push
|
transform_xy_unit!(|self: Pull, to|to.render_in(
|
||||||
|self, to|self.content().min_size(to),
|
[to.x().minus(self.dx()), to.y().minus(self.dy()), to.w(), to.h()],
|
||||||
|self, to|Ok(if let Some(size) = self.min_size(to.area().wh().into())? {
|
self.content()));
|
||||||
to.render_in([
|
|
||||||
to.area().x() + self.dx(),
|
|
||||||
to.area().y() + self.dy(),
|
|
||||||
size.w(),
|
|
||||||
size.h(),
|
|
||||||
].into(), &self.content())?;
|
|
||||||
}));
|
|
||||||
|
|
||||||
transform_xy_unit!(Pull
|
transform_xy_unit!(|self: Margin, to|{
|
||||||
|self, to|self.content().min_size(to),
|
let dx = self.dx();
|
||||||
|self, to|Ok(if let Some(size) = self.min_size(to.area().wh().into())? {
|
let dy = self.dy();
|
||||||
to.render_in([
|
to.render_in([
|
||||||
to.area().x().minus(self.dx()),
|
to.x().minus(dx),
|
||||||
to.area().y().minus(self.dy()),
|
to.y().minus(dy),
|
||||||
size.w(),
|
to.w() + dy + dy,
|
||||||
size.h(),
|
to.h() + dy + dy,
|
||||||
].into(), &self.content())?;
|
])
|
||||||
}));
|
});
|
||||||
|
|
||||||
transform_xy_unit!(Margin
|
transform_xy_unit!(|self: Padding, to|{
|
||||||
|self, to|match *self {
|
let dx = self.dx();
|
||||||
Self::X(x, ref content) => Expand::x(x + x, content),
|
let dy = self.dy();
|
||||||
Self::Y(y, ref content) => Expand::y(y + y, content),
|
to.render_in([
|
||||||
Self::XY(x, y, ref content) => Expand::xy(x + x, y + y, content),
|
to.x() + dx,
|
||||||
}.min_size(to),
|
to.y() + dy,
|
||||||
|self, to|match *self {
|
to.w().minus(dy + dy),
|
||||||
Self::X(x, ref content) => Push::x(x, content),
|
to.h().minus(dy + dy),
|
||||||
Self::Y(y, ref content) => Push::y(y, content),
|
])
|
||||||
Self::XY(x, y, ref content) => Push::xy(x, y, content),
|
});
|
||||||
}.render(to));
|
|
||||||
|
|
||||||
transform_xy_unit!(Padding);
|
|
||||||
impl<E: Engine, T: Render<E>> Render<E> for Padding<E, T> {
|
|
||||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
|
||||||
match self {
|
|
||||||
Self::X(x, content) => Push::x(*x, Shrink::x(*x, content)),
|
|
||||||
Self::Y(y, content) => Push::y(*y, Shrink::y(*y, content)),
|
|
||||||
Self::XY(x, y, content) => Push::xy(*x, *y, Shrink::xy(*x, *y, content)),
|
|
||||||
}.render(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
content_enum!(Align: Center, X, Y, NW, N, NE, E, SE, S, SW, W);
|
content_enum!(Align: Center, X, Y, NW, N, NE, E, SE, S, SW, W);
|
||||||
impl<E: Engine, T: Render<E>> Align<E, T> {
|
impl<E: Engine, T: Render<E>> Align<E, T> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue