diff --git a/output/src/lib.rs b/output/src/lib.rs index 064d8da..41f824a 100644 --- a/output/src/lib.rs +++ b/output/src/lib.rs @@ -19,8 +19,6 @@ pub type Usually = Result>; /// Standard optional result type. pub type Perhaps = Result, Box>; -#[cfg(test)] use proptest_derive::Arbitrary; - #[cfg(test)] #[test] fn test_stub_output () -> Usually<()> { use crate::*; struct TestOutput([u16;4]); @@ -45,152 +43,3 @@ pub type Perhaps = Result, Box>; } Ok(()) } - -#[cfg(test)] #[test] fn test_space () { - use crate::*; - assert_eq!(Area::center(&[10u16, 10, 20, 20]), [20, 20]); -} - -#[cfg(test)] #[test] fn test_iter_map () { - struct Foo; - impl Content for Foo {} - fn make_map + Send + Sync> (data: &Vec) -> impl Content { - Map::new(||data.iter(), |foo, index|{}) - } - let data = vec![Foo, Foo, Foo]; - //let map = make_map(&data); -} - -#[cfg(test)] mod test { - use crate::*; - use proptest::{prelude::*, option::of}; - use proptest::option::of; - - proptest! { - #[test] fn proptest_direction ( - d in prop_oneof![ - Just(North), Just(South), - Just(East), Just(West), - Just(Above), Just(Below) - ], - x in u16::MIN..u16::MAX, - y in u16::MIN..u16::MAX, - w in u16::MIN..u16::MAX, - h in u16::MIN..u16::MAX, - a in u16::MIN..u16::MAX, - ) { - let _ = d.split_fixed([x, y, w, h], a); - } - } - - proptest! { - #[test] fn proptest_size ( - x in u16::MIN..u16::MAX, - y in u16::MIN..u16::MAX, - a in u16::MIN..u16::MAX, - b in u16::MIN..u16::MAX, - ) { - let size = [x, y]; - let _ = size.w(); - let _ = size.h(); - let _ = size.wh(); - let _ = size.clip_w(a); - let _ = size.clip_h(b); - let _ = size.expect_min(a, b); - let _ = size.to_area_pos(); - let _ = size.to_area_size(); - } - } - - proptest! { - #[test] fn proptest_area ( - x in u16::MIN..u16::MAX, - y in u16::MIN..u16::MAX, - w in u16::MIN..u16::MAX, - h in u16::MIN..u16::MAX, - a in u16::MIN..u16::MAX, - b in u16::MIN..u16::MAX, - ) { - let _: [u16;4] = <[u16;4] as Area>::zero(); - let _: [u16;4] = <[u16;4] as Area>::from_position([a, b]); - let _: [u16;4] = <[u16;4] as Area>::from_size([a, b]); - let area: [u16;4] = [x, y, w, h]; - let _ = area.expect_min(a, b); - let _ = area.xy(); - let _ = area.wh(); - let _ = area.xywh(); - let _ = area.clip_h(a); - let _ = area.clip_w(b); - let _ = area.clip([a, b]); - let _ = area.set_w(a); - let _ = area.set_h(b); - let _ = area.x2(); - let _ = area.y2(); - let _ = area.lrtb(); - let _ = area.center(); - let _ = area.center_x(a); - let _ = area.center_y(b); - let _ = area.center_xy([a, b]); - let _ = area.centered(); - } - } - - macro_rules! test_op_transform { - ($fn:ident, $Op:ident) => { - proptest! { - #[test] fn $fn ( - op_x in of(u16::MIN..u16::MAX), - op_y in of(u16::MIN..u16::MAX), - content in "\\PC*", - x in u16::MIN..u16::MAX, - y in u16::MIN..u16::MAX, - w in u16::MIN..u16::MAX, - h in u16::MIN..u16::MAX, - ) { - if let Some(op) = match (op_x, op_y) { - (Some(x), Some(y)) => Some($Op::xy(x, y, content)), - (Some(x), None) => Some($Op::x(x, content)), - (Some(y), None) => Some($Op::y(y, content)), - _ => None - } { - assert_eq!(Content::layout(&op, [x, y, w, h]), - Render::layout(&op, [x, y, w, h])); - } - } - } - } - } - - test_op_transform!(proptest_op_fixed, Fixed); - test_op_transform!(proptest_op_min, Min); - test_op_transform!(proptest_op_max, Max); - test_op_transform!(proptest_op_push, Push); - test_op_transform!(proptest_op_pull, Pull); - test_op_transform!(proptest_op_shrink, Shrink); - test_op_transform!(proptest_op_expand, Expand); - test_op_transform!(proptest_op_margin, Margin); - test_op_transform!(proptest_op_padding, Padding); - - proptest! { - #[test] fn proptest_op_bsp ( - d in prop_oneof![ - Just(North), Just(South), - Just(East), Just(West), - Just(Above), Just(Below) - ], - a in "\\PC*", - b in "\\PC*", - x in u16::MIN..u16::MAX, - y in u16::MIN..u16::MAX, - w in u16::MIN..u16::MAX, - h in u16::MIN..u16::MAX, - ) { - let bsp = Bsp(d, a, b); - assert_eq!( - Content::layout(&bsp, [x, y, w, h]), - Render::layout(&bsp, [x, y, w, h]), - ); - } - } - -} diff --git a/output/src/ops.rs b/output/src/ops.rs index 2cd1784..a46f3f3 100644 --- a/output/src/ops.rs +++ b/output/src/ops.rs @@ -5,3 +5,8 @@ mod map; pub use self::map::*; //mod reduce; pub use self::reduce::*; mod thunk; pub use self::thunk::*; mod transform; pub use self::transform::*; + +#[cfg(test)] use crate::*; +#[cfg(test)] #[test] fn test_ops () -> Usually<()> { + Ok(()) +} diff --git a/output/src/ops/align.rs b/output/src/ops/align.rs index 35a2b68..e9ff5a7 100644 --- a/output/src/ops/align.rs +++ b/output/src/ops/align.rs @@ -27,12 +27,9 @@ //! test(area, &Align::sw(two_by_four()), [10, 28, 4, 2]); //! test(area, &Align::w(two_by_four()), [10, 19, 4, 2]); //! ``` - use crate::*; -#[derive(Debug, Copy, Clone, Default)] -pub enum Alignment { #[default] Center, X, Y, NW, N, NE, E, SE, S, SW, W } - +#[derive(Debug, Copy, Clone, Default)] pub enum Alignment { #[default] Center, X, Y, NW, N, NE, E, SE, S, SW, W } pub struct Align(Alignment, A); #[cfg(feature = "dsl")] @@ -82,7 +79,6 @@ impl Align { #[inline] pub const fn ne (a: A) -> Self { Self(Alignment::NE, a) } #[inline] pub const fn se (a: A) -> Self { Self(Alignment::SE, a) } } - impl> Content for Align { fn content (&self) -> impl Render { &self.1 diff --git a/output/src/ops/bsp.rs b/output/src/ops/bsp.rs index 5ede569..52e697d 100644 --- a/output/src/ops/bsp.rs +++ b/output/src/ops/bsp.rs @@ -117,3 +117,28 @@ impl, B: Content> BspAreas for Bsp { #[macro_export] macro_rules! row { ($($expr:expr),* $(,)?) => {{ let bsp = (); $(let bsp = Bsp::e(bsp, $expr);)*; bsp }}; } +#[cfg(test)] mod test { + use super::*; + use proptest::prelude::*; + proptest! { + #[test] fn proptest_op_bsp ( + d in prop_oneof![ + Just(North), Just(South), + Just(East), Just(West), + Just(Above), Just(Below) + ], + a in "\\PC*", + b in "\\PC*", + x in u16::MIN..u16::MAX, + y in u16::MIN..u16::MAX, + w in u16::MIN..u16::MAX, + h in u16::MIN..u16::MAX, + ) { + let bsp = Bsp(d, a, b); + assert_eq!( + Content::layout(&bsp, [x, y, w, h]), + Render::layout(&bsp, [x, y, w, h]), + ); + } + } +} diff --git a/output/src/ops/map.rs b/output/src/ops/map.rs index d124569..285bd20 100644 --- a/output/src/ops/map.rs +++ b/output/src/ops/map.rs @@ -1,4 +1,27 @@ use crate::*; +#[inline] pub fn map_south( + item_offset: O::Unit, + item_height: O::Unit, + item: impl Content +) -> impl Content { + Push::y(item_offset, Fixed::y(item_height, Fill::x(item))) +} + +#[inline] pub fn map_south_west( + item_offset: O::Unit, + item_height: O::Unit, + item: impl Content +) -> impl Content { + Push::y(item_offset, Align::nw(Fixed::y(item_height, Fill::x(item)))) +} + +#[inline] pub fn map_east( + item_offset: O::Unit, + item_width: O::Unit, + item: impl Content +) -> impl Content { + Push::x(item_offset, Align::w(Fixed::x(item_width, Fill::y(item)))) +} /// Renders items from an iterator. pub struct Map @@ -125,26 +148,12 @@ impl<'a, E, A, B, I, F, G> Content for Map where } } -#[inline] pub fn map_south( - item_offset: O::Unit, - item_height: O::Unit, - item: impl Content -) -> impl Content { - Push::y(item_offset, Fixed::y(item_height, Fill::x(item))) -} - -#[inline] pub fn map_south_west( - item_offset: O::Unit, - item_height: O::Unit, - item: impl Content -) -> impl Content { - Push::y(item_offset, Align::nw(Fixed::y(item_height, Fill::x(item)))) -} - -#[inline] pub fn map_east( - item_offset: O::Unit, - item_width: O::Unit, - item: impl Content -) -> impl Content { - Push::x(item_offset, Align::w(Fixed::x(item_width, Fill::y(item)))) +#[cfg(test)] #[test] fn test_iter_map () { + struct Foo; + impl Content for Foo {} + fn make_map + Send + Sync> (data: &Vec) -> impl Content { + Map::new(||data.iter(), |foo, index|{}) + } + let data = vec![Foo, Foo, Foo]; + //let map = make_map(&data); } diff --git a/output/src/ops/transform.rs b/output/src/ops/transform.rs index 6012a96..0ed9c80 100644 --- a/output/src/ops/transform.rs +++ b/output/src/ops/transform.rs @@ -19,9 +19,7 @@ //! //FIXME:test(area, &Fixed::y(4, ()), [20, 18, 0, 4]); //! //FIXME:test(area, &Fixed::xy(4, 4, unit), [18, 18, 4, 4]); //! ``` - use crate::*; - /// Defines an enum that transforms its content /// along either the X axis, the Y axis, or both. macro_rules! transform_xy { @@ -133,7 +131,6 @@ macro_rules! transform_xy_unit { } } } - transform_xy!("fill/x" "fill/y" "fill/xy" |self: Fill, to|{ let [x0, y0, wmax, hmax] = to.xywh(); let [x, y, w, h] = self.content().layout(to).xywh(); @@ -141,9 +138,7 @@ transform_xy!("fill/x" "fill/y" "fill/xy" |self: Fill, to|{ X(_) => [x0, y, wmax, h], Y(_) => [x, y0, w, hmax], XY(_) => [x0, y0, wmax, hmax], - }.into() -}); - + }.into() }); transform_xy_unit!("fixed/x" "fixed/y" "fixed/xy"|self: Fixed, area|{ let [x, y, w, h] = area.xywh(); let fixed_area = match self { @@ -157,55 +152,80 @@ transform_xy_unit!("fixed/x" "fixed/y" "fixed/xy"|self: Fixed, area|{ Self::Y(fh, _) => [x, y, w, *fh], Self::XY(fw, fh, _) => [x, y, *fw, *fh], }; - fixed_area -}); - + fixed_area }); transform_xy_unit!("min/x" "min/y" "min/xy"|self: Min, area|{ let area = Render::layout(&self.content(), area); match self { Self::X(mw, _) => [area.x(), area.y(), area.w().max(*mw), area.h()], Self::Y(mh, _) => [area.x(), area.y(), area.w(), area.h().max(*mh)], Self::XY(mw, mh, _) => [area.x(), area.y(), area.w().max(*mw), area.h().max(*mh)], - } -}); - + }}); transform_xy_unit!("max/x" "max/y" "max/xy"|self: Max, area|{ let [x, y, w, h] = area.xywh(); Render::layout(&self.content(), match self { Self::X(fw, _) => [x, y, *fw, h], Self::Y(fh, _) => [x, y, w, *fh], Self::XY(fw, fh, _) => [x, y, *fw, *fh], - }.into()) -}); - + }.into())}); transform_xy_unit!("shrink/x" "shrink/y" "shrink/xy"|self: Shrink, area|Render::layout( &self.content(), [area.x(), area.y(), area.w().minus(self.dx()), area.h().minus(self.dy())].into())); - transform_xy_unit!("expand/x" "expand/y" "expand/xy"|self: Expand, area|Render::layout( &self.content(), [area.x(), area.y(), area.w().plus(self.dx()), area.h().plus(self.dy())].into())); - transform_xy_unit!("push/x" "push/y" "push/xy"|self: Push, area|{ let area = Render::layout(&self.content(), area); - [area.x().plus(self.dx()), area.y().plus(self.dy()), area.w(), area.h()] -}); - + [area.x().plus(self.dx()), area.y().plus(self.dy()), area.w(), area.h()] }); transform_xy_unit!("pull/x" "pull/y" "pull/xy"|self: Pull, area|{ let area = Render::layout(&self.content(), area); - [area.x().minus(self.dx()), area.y().minus(self.dy()), area.w(), area.h()] -}); - + [area.x().minus(self.dx()), area.y().minus(self.dy()), area.w(), area.h()] }); transform_xy_unit!("margin/x" "margin/y" "margin/xy"|self: Margin, area|{ let area = Render::layout(&self.content(), area); let dx = self.dx(); let dy = self.dy(); - [area.x().minus(dx), area.y().minus(dy), area.w().plus(dy.plus(dy)), area.h().plus(dy.plus(dy))] -}); - + [area.x().minus(dx), area.y().minus(dy), area.w().plus(dy.plus(dy)), area.h().plus(dy.plus(dy))] }); transform_xy_unit!("padding/x" "padding/y" "padding/xy"|self: Padding, area|{ let area = Render::layout(&self.content(), area); let dx = self.dx(); let dy = self.dy(); - [area.x().plus(dx), area.y().plus(dy), area.w().minus(dy.plus(dy)), area.h().minus(dy.plus(dy))] -}); + [area.x().plus(dx), area.y().plus(dy), area.w().minus(dy.plus(dy)), area.h().minus(dy.plus(dy)), ] }); + +#[cfg(test)] mod test_op_transform { + use super::*; + use proptest::prelude::*; + use proptest::option::of; + macro_rules! test_op_transform { + ($fn:ident, $Op:ident) => { + proptest! { + #[test] fn $fn ( + op_x in of(u16::MIN..u16::MAX), + op_y in of(u16::MIN..u16::MAX), + content in "\\PC*", + x in u16::MIN..u16::MAX, + y in u16::MIN..u16::MAX, + w in u16::MIN..u16::MAX, + h in u16::MIN..u16::MAX, + ) { + if let Some(op) = match (op_x, op_y) { + (Some(x), Some(y)) => Some($Op::xy(x, y, content)), + (Some(x), None) => Some($Op::x(x, content)), + (Some(y), None) => Some($Op::y(y, content)), + _ => None + } { + assert_eq!(Content::layout(&op, [x, y, w, h]), + Render::layout(&op, [x, y, w, h])); + } + } + } + } + } + test_op_transform!(test_op_fixed, Fixed); + test_op_transform!(test_op_min, Min); + test_op_transform!(test_op_max, Max); + test_op_transform!(test_op_push, Push); + test_op_transform!(test_op_pull, Pull); + test_op_transform!(test_op_shrink, Shrink); + test_op_transform!(test_op_expand, Expand); + test_op_transform!(test_op_margin, Margin); + test_op_transform!(test_op_padding, Padding); +} diff --git a/output/src/space.rs b/output/src/space.rs index 056e12f..8edcb63 100644 --- a/output/src/space.rs +++ b/output/src/space.rs @@ -3,3 +3,8 @@ mod coordinate; pub use self::coordinate::*; mod direction; pub use self::direction::*; mod measure; pub use self::measure::*; mod size; pub use self::size::*; + +#[cfg(test)] #[test] fn test_space () { + use crate::*; + assert_eq!(Area::center(&[10u16, 10, 20, 20]), [20, 20]); +} diff --git a/output/src/space/area.rs b/output/src/space/area.rs index 4393790..aefcfe8 100644 --- a/output/src/space/area.rs +++ b/output/src/space/area.rs @@ -96,3 +96,40 @@ impl Area for [N;4] { fn w (&self) -> N { self[2] } fn h (&self) -> N { self[3] } } + +#[cfg(test)] mod test_area { + use super::*; + use proptest::prelude::*; + proptest! { + #[test] fn test_area_prop ( + x in u16::MIN..u16::MAX, + y in u16::MIN..u16::MAX, + w in u16::MIN..u16::MAX, + h in u16::MIN..u16::MAX, + a in u16::MIN..u16::MAX, + b in u16::MIN..u16::MAX, + ) { + let _: [u16;4] = <[u16;4] as Area>::zero(); + let _: [u16;4] = <[u16;4] as Area>::from_position([a, b]); + let _: [u16;4] = <[u16;4] as Area>::from_size([a, b]); + let area: [u16;4] = [x, y, w, h]; + let _ = area.expect_min(a, b); + let _ = area.xy(); + let _ = area.wh(); + let _ = area.xywh(); + let _ = area.clip_h(a); + let _ = area.clip_w(b); + let _ = area.clip([a, b]); + let _ = area.set_w(a); + let _ = area.set_h(b); + let _ = area.x2(); + let _ = area.y2(); + let _ = area.lrtb(); + let _ = area.center(); + let _ = area.center_x(a); + let _ = area.center_y(b); + let _ = area.center_xy([a, b]); + let _ = area.centered(); + } + } +} diff --git a/output/src/space/direction.rs b/output/src/space/direction.rs index 90dc95e..afa2139 100644 --- a/output/src/space/direction.rs +++ b/output/src/space/direction.rs @@ -1,12 +1,9 @@ use crate::*; - +#[cfg(test)] use proptest_derive::Arbitrary; /// A cardinal direction. #[derive(Copy, Clone, PartialEq, Debug)] #[cfg_attr(test, derive(Arbitrary))] -pub enum Direction { - North, South, East, West, Above, Below -} - +pub enum Direction { North, South, East, West, Above, Below } impl Direction { pub fn split_fixed (self, area: impl Area, a: N) -> ([N;4],[N;4]) { let [x, y, w, h] = area.xywh(); @@ -19,3 +16,23 @@ impl Direction { } } } +#[cfg(test)] mod test { + use super::*; + use proptest::prelude::*; + proptest! { + #[test] fn proptest_direction ( + d in prop_oneof![ + Just(North), Just(South), + Just(East), Just(West), + Just(Above), Just(Below) + ], + x in u16::MIN..u16::MAX, + y in u16::MIN..u16::MAX, + w in u16::MIN..u16::MAX, + h in u16::MIN..u16::MAX, + a in u16::MIN..u16::MAX, + ) { + let _ = d.split_fixed([x, y, w, h], a); + } + } +} diff --git a/output/src/space/size.rs b/output/src/space/size.rs index f9e2d19..cfeeeed 100644 --- a/output/src/space/size.rs +++ b/output/src/space/size.rs @@ -38,3 +38,26 @@ impl Size for [N;2] { fn x (&self) -> N { self[0] } fn y (&self) -> N { self[1] } } + +#[cfg(test)] mod test_size { + use super::*; + use proptest::prelude::*; + proptest! { + #[test] fn test_size ( + x in u16::MIN..u16::MAX, + y in u16::MIN..u16::MAX, + a in u16::MIN..u16::MAX, + b in u16::MIN..u16::MAX, + ) { + let size = [x, y]; + let _ = size.w(); + let _ = size.h(); + let _ = size.wh(); + let _ = size.clip_w(a); + let _ = size.clip_h(b); + let _ = size.expect_min(a, b); + let _ = size.to_area_pos(); + let _ = size.to_area_size(); + } + } +} diff --git a/tui/src/tui_engine/tui_input.rs b/tui/src/tui_engine/tui_input.rs index 75c5be2..2dd06f4 100644 --- a/tui/src/tui_engine/tui_input.rs +++ b/tui/src/tui_engine/tui_input.rs @@ -3,14 +3,7 @@ use std::time::Duration; use std::thread::{spawn, JoinHandle}; use crossterm::event::{poll, read}; -#[derive(Debug, Clone)] -pub struct TuiIn( - /// Exit flag - pub Arc, - /// Input event - pub Event, -); - +#[derive(Debug, Clone)] pub struct TuiIn(pub Arc, pub Event); impl Input for TuiIn { type Event = Event; type Handled = bool; @@ -56,7 +49,6 @@ impl TuiIn { } } -#[cfg(feature = "dsl")] impl DslInput for TuiIn { fn matches_dsl (&self, token: &str) -> bool { if let Some(event) = KeyMatcher::new(token).build() {