diff --git a/Justfile b/Justfile index 83c5796..b233be1 100644 --- a/Justfile +++ b/Justfile @@ -29,9 +29,11 @@ doc: CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' RUSTDOCFLAGS='-Cinstrument-coverage' \ cargo doc -mode-00: - cargo run --example mode_00 -mode-01: - cargo run --example mode_01 -mode-02: - cargo run --example mode_02 +example-tui-00: + cargo run --example mode_0 + +example-tui-01: + cargo run --example mode_1 + +example-tui-02: + cargo run --example mode_2 diff --git a/dizzle b/dizzle index 0f06571..4424ef7 160000 --- a/dizzle +++ b/dizzle @@ -1 +1 @@ -Subproject commit 0f06571f7fc7e5f87aadb82d531726d24bf769e8 +Subproject commit 4424ef7fc3fd8bfbea1fb55b4922f7a8cfd2a8ef diff --git a/examples/mode_00.rs b/examples/mode_00.rs index 31b148d..9ab858c 100644 --- a/examples/mode_00.rs +++ b/examples/mode_00.rs @@ -1,37 +1,3 @@ -//! Mode 00: Direct draw, direct control - -use ::std::sync::{Arc, RwLock}; -use ::crossterm::event::{Event::*, KeyEvent, KeyCode::*}; -use ::ratatui::style::Color; -use ::tengri::{*, lang::*}; - -tui_app!(State { - /** User-controllable value. */ - cursor: usize, -}); - -tui_view!(self: State { - thunk(|to: &mut Tui|{ - let cursor = format!("Cursor: {}", self.cursor); - let _ = "DEMO [MODE 00]".align_sw().draw(to); - let _ = ShowSize.align_se().draw(to); - let _ = format!("Cursor: {}", self.cursor).align_c().draw(to); - Ok(Some(to.area())) - }) -}); - -tui_keys!(self: State, input { - Ok(if let Key(KeyEvent { code, .. }) = input.0 { - match code { - Up | Right => { - self.cursor = (self.cursor + 1) % 10; - () - }, - Down | Left => { - self.cursor = if self.cursor > 0 { self.cursor - 1 } else { 10 - 1 }; - () - }, - _ => {} - } - }) -}); +//! Mode 0: Direct draw +use ::{std::sync::{Arc, RwLock}, ratatui::style::Color, tengri::*}; +fn main () {} diff --git a/examples/mode_01.rs b/examples/mode_01.rs index d7ee626..18a9dae 100644 --- a/examples/mode_01.rs +++ b/examples/mode_01.rs @@ -1,63 +1,153 @@ -//! Mode 01: Direct view, actions with history - +//! Mode 01 use ::std::sync::{Arc, RwLock}; use ::crossterm::event::{Event::*, KeyEvent, KeyCode::*}; use ::ratatui::style::Color; use ::tengri::{*, lang::*}; -use itertools::Itertools; - tui_app!(State { /** Command history (undo/redo). */ history: Vec, /** User-controllable value. */ cursor: usize, + /** Rendered window size. */ + size: Sizer, }); - tui_keys!(self: State, input { Ok(if let Key(KeyEvent { code, .. }) = input.0 { match code { - Down | Right => Action::Next, - Up | Left => Action::Prev, - _ => { return Ok(()) } + Up | Right => { self.next()?.map(|x|self.history.push(x)); }, + Down | Left => { self.prev()?.map(|x|self.history.push(x)); }, + _ => {} } - .apply(self)? - .map(|x|self.history.push(x)); }) }); - tui_view!(self: State { - let title = "Demo Mode 00"; - let items = self.history.iter().take(10).map(|x|format!("{x:?}")).join("\n"); - let history = format!("History: {}\n{items}", self.history.len()); - let cursor = format!("Cursor: {}", self.cursor); - north( - east(title.align_sw(), ShowSize.align_se()), - east(history.align_c(), cursor.align_c()), - ) + let index = self.cursor + 1; + let wh = (self.size.w(), self.size.h()); + let src = VIEWS.get(self.cursor).unwrap_or(&""); + let heading = format!("State {}/{} in {:?}", index, VIEWS.len(), &wh); + let title = bg(Color::Rgb(60, 10, 10), heading.align_n().push_y(1)); + let code = bg(Color::Rgb(10, 60, 10), format!("{}", src).align_n().push_y(2)); + let widget = thunk(move|to: &mut Tui|self.interpret(to, &src)); + self.size.of(south(title, north(code, widget))) }); - -#[derive(Debug)] enum Action { - /** Increment cursor */ Next, - /** Decrement cursor */ Prev, -} - -impl Action { - fn apply (&self, state: &mut State) -> Perhaps { - use Action::*; - match self { - Next => state.next(), - Prev => state.prev(), +impl Interpret for State { + fn interpret_expr (&self, to: &mut Tui, expr: &impl Language) -> Usually { + let expr = expr.expr()?; + match expr.head()? { + Some("g") if let Some(tail) = expr.tail()? => { + Color::new_g(tail.head()?, try_to_u8) + }, + Some("rgb") if let Some(tail) = expr.tail()? => { + Color::new_rgb(tail.head()?) + }, + _ => Err(format!("not a color").into()) } } } - +impl Interpret>> for State { + fn interpret_word (&self, to: &mut Tui, sym: &impl Language) -> Perhaps> { + match sym.src()? { + Some(":foo") => "foo".draw(to), + Some(":bar") => "bar".draw(to), + Some(":foobar") => "FOOBAR".draw(to), + _ => todo!() + } + } + fn interpret_expr (&self, to: &mut Tui, src: &impl Expression) -> Perhaps> { + Ok(Some(if let Some(area) = eval_view(self, to, src)? { + area + } else if let Some(area) = eval_view_tui(self, to, src)? { + area + } else { + return Err(format!("App::interpret_expr: unexpected: {src:?}").into()) + })) + } +} impl State { fn next (&mut self) -> Perhaps { - self.cursor = (self.cursor + 1) % 10; + self.cursor = (self.cursor + 1) % VIEWS.len(); Ok(Some(Action::Prev)) } fn prev (&mut self) -> Perhaps { - self.cursor = if self.cursor > 0 { self.cursor - 1 } else { 10 - 1 }; + self.cursor = if self.cursor > 0 { self.cursor - 1 } else { VIEWS.len() - 1 }; Ok(Some(Action::Next)) } } +#[derive(Debug)] +enum Action { + /** Increment cursor */ Next, + /** Decrement cursor */ Prev, +} +impl Action { + fn eval (&self, state: &mut State) -> Perhaps { + use Action::*; + match self { Next => state.next(), Prev => state.prev(), } + } +} +const VIEWS: &'static [&'static str] = &[ + stringify! { :foobar }, + stringify! { (bg (g 8) :foobar) }, + stringify! { (fill/xy :foobar) }, + stringify! { (bsp/s :foo :bar) }, + stringify! { (fixed/xy 20 10 :foobar) }, + stringify! { (bsp/s (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) }, + stringify! { (bsp/e (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) }, + stringify! { (bsp/n (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) }, + stringify! { (bsp/w (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) }, + stringify! { (bsp/a (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) }, + stringify! { (bsp/b (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) }, + stringify! { + (bsp/s + (bsp/e (align/nw (fixed/xy 5 3 :foo)) + (bsp/e (align/n (fixed/xy 5 3 :foo)) + (align/ne (fixed/xy 5 3 :foo)))) + (bsp/s + (bsp/e (align/w (fixed/xy 5 3 :foo)) + (bsp/e (align/c (fixed/xy 5 3 :foo)) + (align/e (fixed/xy 5 3 :foo)))) + (bsp/e (align/sw (fixed/xy 5 3 :foo)) + (bsp/e (align/s (fixed/xy 5 3 :foo)) + (align/se (fixed/xy 5 3 :foo)))))) + }, + stringify! { + (bsp/s + (bsp/e (fixed/xy 8 5 (align/nw :foo)) + (bsp/e (fixed/xy 8 5 (align/n :foo)) + (fixed/xy 8 5 (align/ne :foo)))) + (bsp/s + (bsp/e (fixed/xy 8 5 (align/w :foo)) + (bsp/e (fixed/xy 8 5 (align/c :foo)) + (fixed/xy 8 5 (align/e :foo)))) + (bsp/e (fixed/xy 8 5 (align/sw :foo)) + (bsp/e (fixed/xy 8 5 (align/s :foo)) + (fixed/xy 8 5 (align/se :foo)))))) + }, + stringify! { + (bsp/s + (bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/nw :foo))) + (bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/n :foo))) + (grow/xy 1 1 (fixed/xy 8 5 (align/ne :foo))))) + (bsp/s + (bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/w :foo))) + (bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/c :foo))) + (grow/xy 1 1 (fixed/xy 8 5 (align/e :foo))))) + (bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/sw :foo))) + (bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/s :foo))) + (grow/xy 1 1 (fixed/xy 8 5 (align/se :foo))))))) + }, + stringify! { :map-e }, + stringify! { (align/c :map-e) }, + stringify! { :map-s }, + stringify! { (align/c :map-s) }, + stringify! { + (align/c (bg/behind :bg0 (margin/xy 1 1 (col + (bg/behind :bg1 (border/around :border1 (margin/xy 2 1 :label1))) + (bg/behind :bg2 (border/around :border2 (margin/xy 4 2 :label2))) + (bg/behind :bg3 (border/around :border3 (margin/xy 6 3 :label3))))))) + }, +]; +//handle!(TuiIn: |self: State, input|Action::from(input).eval(self).map(|_|None)); + //view!(State: Tui: [ evaluate_output_expression, evaluate_output_expression_tui ]); + //draw!(State: Tui: [ draw_example ]); +//impl_from!(Action: |input: &TuiIn| todo!()); +//fn draw_example (state: &State, to: &mut Tui) {} diff --git a/examples/mode_02.rs b/examples/mode_02.rs index 70cec30..40fba02 100644 --- a/examples/mode_02.rs +++ b/examples/mode_02.rs @@ -1,162 +1,107 @@ -//! Mode 02: Inline Dizzle config +//! Mode 02 +use ::{std::sync::{Arc, RwLock}, ratatui::style::Color, tengri::*}; +fn main () {} -use ::std::sync::{Arc, RwLock}; -use ::crossterm::event::{Event::*, KeyEvent, KeyCode::*}; -use ::ratatui::style::Color; -use ::tengri::{*, lang::*}; -tui_app!(State { - /** Command history (undo/redo). */ - history: Vec, - /** User-controllable value. */ - cursor: usize, - /** Rendered window size. */ - size: Sizer, -}); -tui_keys!(self: State, input { - Ok(if let Key(KeyEvent { code, .. }) = input.0 { - match code { - Up | Right => { self.next()?.map(|x|self.history.push(x)); }, - Down | Left => { self.prev()?.map(|x|self.history.push(x)); }, - _ => {} - } - }) -}); -tui_view!(self: State { - let index = self.cursor + 1; - let wh = (self.size.w(), self.size.h()); - let src = VIEWS.get(self.cursor).unwrap_or(&""); - let heading = format!("State {}/{} in {:?}", index, VIEWS.len(), &wh); - let title = bg(Color::Rgb(60, 10, 10), heading.align_n().push_y(1)); - let code = bg(Color::Rgb(10, 60, 10), format!("{}", src).align_n().push_y(2)); - let widget = thunk(move|to: &mut Tui|self.interpret(to, &src)); - self.size.of(south(title, north(code, widget))) -}); -impl Interpret for State { - fn interpret_expr (&self, to: &mut Tui, expr: &impl Language) -> Usually { - let expr = expr.expr()?; - match expr.head()? { - Some("g") if let Some(tail) = expr.tail()? => { - Color::new_g(tail.head()?, try_to_u8) - }, - Some("rgb") if let Some(tail) = expr.tail()? => { - Color::new_rgb(tail.head()?, try_to_u8) - }, - _ => Err(format!("not a color").into()) - } - } -} -fn try_to_u8 (src: Perhaps<&str>) -> Perhaps { - use std::str::FromStr; - if let Some(src) = src? { - Ok(Some(u8::from_str(src)?)) - } else { - Ok(None) - } -} -impl Interpret>> for State { - fn interpret_word (&self, to: &mut Tui, sym: &impl Language) -> Perhaps> { - match sym.src()? { - Some(":foo") => "foo".draw(to), - Some(":bar") => "bar".draw(to), - Some(":foobar") => "FOOBAR".draw(to), - _ => todo!() - } - } - fn interpret_expr (&self, to: &mut Tui, src: &impl Expression) -> Perhaps> { - Ok(Some(if let Some(area) = eval_view(self, to, src)? { - area - } else if let Some(area) = eval_view_tui(self, to, src)? { - area - } else { - return Err(format!("App::interpret_expr: unexpected: {src:?}").into()) - })) - } -} -impl State { - fn next (&mut self) -> Perhaps { - self.cursor = (self.cursor + 1) % VIEWS.len(); - Ok(Some(Action::Prev)) - } - fn prev (&mut self) -> Perhaps { - self.cursor = if self.cursor > 0 { self.cursor - 1 } else { VIEWS.len() - 1 }; - Ok(Some(Action::Next)) - } -} -#[derive(Debug)] -enum Action { - /** Increment cursor */ Next, - /** Decrement cursor */ Prev, -} -impl Action { - fn eval (&self, state: &mut State) -> Perhaps { - use Action::*; - match self { Next => state.next(), Prev => state.prev(), } - } -} -const VIEWS: &'static [&'static str] = &[ - stringify! { :foobar }, - stringify! { (bg (g 8) :foobar) }, - stringify! { (fill/xy :foobar) }, - stringify! { (bsp/s :foo :bar) }, - stringify! { (fixed/xy 20 10 :foobar) }, - stringify! { (bsp/s (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) }, - stringify! { (bsp/e (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) }, - stringify! { (bsp/n (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) }, - stringify! { (bsp/w (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) }, - stringify! { (bsp/a (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) }, - stringify! { (bsp/b (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) }, - stringify! { - (bsp/s - (bsp/e (align/nw (fixed/xy 5 3 :foo)) - (bsp/e (align/n (fixed/xy 5 3 :foo)) - (align/ne (fixed/xy 5 3 :foo)))) - (bsp/s - (bsp/e (align/w (fixed/xy 5 3 :foo)) - (bsp/e (align/c (fixed/xy 5 3 :foo)) - (align/e (fixed/xy 5 3 :foo)))) - (bsp/e (align/sw (fixed/xy 5 3 :foo)) - (bsp/e (align/s (fixed/xy 5 3 :foo)) - (align/se (fixed/xy 5 3 :foo)))))) - }, - stringify! { - (bsp/s - (bsp/e (fixed/xy 8 5 (align/nw :foo)) - (bsp/e (fixed/xy 8 5 (align/n :foo)) - (fixed/xy 8 5 (align/ne :foo)))) - (bsp/s - (bsp/e (fixed/xy 8 5 (align/w :foo)) - (bsp/e (fixed/xy 8 5 (align/c :foo)) - (fixed/xy 8 5 (align/e :foo)))) - (bsp/e (fixed/xy 8 5 (align/sw :foo)) - (bsp/e (fixed/xy 8 5 (align/s :foo)) - (fixed/xy 8 5 (align/se :foo)))))) - }, - stringify! { - (bsp/s - (bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/nw :foo))) - (bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/n :foo))) - (grow/xy 1 1 (fixed/xy 8 5 (align/ne :foo))))) - (bsp/s - (bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/w :foo))) - (bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/c :foo))) - (grow/xy 1 1 (fixed/xy 8 5 (align/e :foo))))) - (bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/sw :foo))) - (bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/s :foo))) - (grow/xy 1 1 (fixed/xy 8 5 (align/se :foo))))))) - }, - stringify! { :map-e }, - stringify! { (align/c :map-e) }, - stringify! { :map-s }, - stringify! { (align/c :map-s) }, - stringify! { - (align/c (bg/behind :bg0 (margin/xy 1 1 (col - (bg/behind :bg1 (border/around :border1 (margin/xy 2 1 :label1))) - (bg/behind :bg2 (border/around :border2 (margin/xy 4 2 :label2))) - (bg/behind :bg3 (border/around :border3 (margin/xy 6 3 :label3))))))) - }, -]; -//handle!(TuiIn: |self: State, input|Action::from(input).eval(self).map(|_|None)); - //view!(State: Tui: [ evaluate_output_expression, evaluate_output_expression_tui ]); - //draw!(State: Tui: [ draw_example ]); -//impl_from!(Action: |input: &TuiIn| todo!()); -//fn draw_example (state: &State, to: &mut Tui) {} +//#[tengri_proc::expose] +//impl Example { + //fn _todo_u16_stub (&self) -> u16 { todo!() } + //fn _todo_bool_stub (&self) -> bool { todo!() } + //fn _todo_usize_stub (&self) -> usize { todo!() } + ////[bool] => {} + ////[u16] => {} + ////[usize] => {} +//} + +//#[tengri_proc::view(TuiOut)] +//impl Example { + //pub fn title (&self) -> impl Content + use<'_> { + //Tui::bg(Color::Rgb(60, 10, 10), Push::y(1, Align::n(format!("Example {}/{}:", self.0 + 1, VIEWS.len())))).boxed() + //} + //pub fn code (&self) -> impl Content + use<'_> { + //Tui::bg(Color::Rgb(10, 60, 10), Push::y(2, Align::n(format!("{}", VIEWS[self.0])))).boxed() + //} + //pub fn hello (&self) -> impl Content + use<'_> { + //Tui::bg(Color::Rgb(10, 100, 10), "Hello").boxed() + //} + //pub fn world (&self) -> impl Content + use<'_> { + //Tui::bg(Color::Rgb(100, 10, 10), "world").boxed() + //} + //pub fn hello_world (&self) -> impl Content + use<'_> { + //"Hello world!".boxed() + //} + //pub fn map_e (&self) -> impl Content + use<'_> { + //Map::east(5u16, ||0..5u16, |n, _i|format!("{n}")).boxed() + //} + //pub fn map_s (&self) -> impl Content + use<'_> { + //Map::south(5u16, ||0..5u16, |n, _i|format!("{n}")).boxed() + //} +//} + + //fn content (&self) -> dyn Draw { + //let border_style = Style::default().fg(Color::Rgb(0,0,0)); + //Align::Center(Layers::new(move|add|{ + + //add(&Background(Color::Rgb(0,128,128)))?; + + //add(&Margin::XY(1, 1, Stack::down(|add|{ + + //add(&Layers::new(|add|{ + //add(&Background(Color::Rgb(128,96,0)))?; + //add(&Border(Square(border_style)))?; + //add(&Margin::XY(2, 1, "..."))?; + //Ok(()) + //}).debug())?; + + //add(&Layers::new(|add|{ + //add(&Background(Color::Rgb(128,64,0)))?; + //add(&Border(Lozenge(border_style)))?; + //add(&Margin::XY(4, 2, "---"))?; + //Ok(()) + //}).debug())?; + + //add(&Layers::new(|add|{ + //add(&Background(Color::Rgb(96,64,0)))?; + //add(&Border(SquareBold(border_style)))?; + //add(&Margin::XY(6, 3, "~~~"))?; + //Ok(()) + //}).debug())?; + + //Ok(()) + //})).debug())?; + + //Ok(()) + + //})) + ////Align::Center(Margin::X(1, Layers::new(|add|{ + ////add(&Background(Color::Rgb(128,0,0)))?; + ////add(&Stack::down(|add|{ + ////add(&Margin::Y(1, Layers::new(|add|{ + ////add(&Background(Color::Rgb(0,128,0)))?; + ////add(&Align::Center("12345"))?; + ////add(&Align::Center("FOO")) + ////})))?; + ////add(&Margin::XY(1, 1, Layers::new(|add|{ + ////add(&Align::Center("1234567"))?; + ////add(&Align::Center("BAR"))?; + ////add(&Background(Color::Rgb(0,0,128))) + ////}))) + ////})) + ////}))) + + ////Align::Y(Layers::new(|add|{ + ////add(&Background(Color::Rgb(128,0,0)))?; + ////add(&Margin::X(1, Align::Center(Stack::down(|add|{ + ////add(&Align::X(Margin::Y(1, Layers::new(|add|{ + ////add(&Background(Color::Rgb(0,128,0)))?; + ////add(&Align::Center("12345"))?; + ////add(&Align::Center("FOO")) + ////})))?; + ////add(&Margin::XY(1, 1, Layers::new(|add|{ + ////add(&Align::Center("1234567"))?; + ////add(&Align::Center("BAR"))?; + ////add(&Background(Color::Rgb(0,0,128))) + ////})))?; + ////Ok(()) + ////}))))) + ////})) + //} diff --git a/examples/mode_03.rs b/examples/mode_03.rs deleted file mode 100644 index 30eec8c..0000000 --- a/examples/mode_03.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Mode 03: Hot reloaded Dizzle config - -use ::{std::sync::{Arc, RwLock}, ratatui::style::Color, tengri::*}; -fn main () {} - -//#[tengri_proc::expose] -//impl Example { - //fn _todo_u16_stub (&self) -> u16 { todo!() } - //fn _todo_bool_stub (&self) -> bool { todo!() } - //fn _todo_usize_stub (&self) -> usize { todo!() } - ////[bool] => {} - ////[u16] => {} - ////[usize] => {} -//} - -//#[tengri_proc::view(TuiOut)] -//impl Example { - //pub fn title (&self) -> impl Content + use<'_> { - //Tui::bg(Color::Rgb(60, 10, 10), Push::y(1, Align::n(format!("Example {}/{}:", self.0 + 1, VIEWS.len())))).boxed() - //} - //pub fn code (&self) -> impl Content + use<'_> { - //Tui::bg(Color::Rgb(10, 60, 10), Push::y(2, Align::n(format!("{}", VIEWS[self.0])))).boxed() - //} - //pub fn hello (&self) -> impl Content + use<'_> { - //Tui::bg(Color::Rgb(10, 100, 10), "Hello").boxed() - //} - //pub fn world (&self) -> impl Content + use<'_> { - //Tui::bg(Color::Rgb(100, 10, 10), "world").boxed() - //} - //pub fn hello_world (&self) -> impl Content + use<'_> { - //"Hello world!".boxed() - //} - //pub fn map_e (&self) -> impl Content + use<'_> { - //Map::east(5u16, ||0..5u16, |n, _i|format!("{n}")).boxed() - //} - //pub fn map_s (&self) -> impl Content + use<'_> { - //Map::south(5u16, ||0..5u16, |n, _i|format!("{n}")).boxed() - //} -//} - - //fn content (&self) -> dyn Draw { - //let border_style = Style::default().fg(Color::Rgb(0,0,0)); - //Align::Center(Layers::new(move|add|{ - - //add(&Background(Color::Rgb(0,128,128)))?; - - //add(&Margin::XY(1, 1, Stack::down(|add|{ - - //add(&Layers::new(|add|{ - //add(&Background(Color::Rgb(128,96,0)))?; - //add(&Border(Square(border_style)))?; - //add(&Margin::XY(2, 1, "..."))?; - //Ok(()) - //}).debug())?; - - //add(&Layers::new(|add|{ - //add(&Background(Color::Rgb(128,64,0)))?; - //add(&Border(Lozenge(border_style)))?; - //add(&Margin::XY(4, 2, "---"))?; - //Ok(()) - //}).debug())?; - - //add(&Layers::new(|add|{ - //add(&Background(Color::Rgb(96,64,0)))?; - //add(&Border(SquareBold(border_style)))?; - //add(&Margin::XY(6, 3, "~~~"))?; - //Ok(()) - //}).debug())?; - - //Ok(()) - //})).debug())?; - - //Ok(()) - - //})) - ////Align::Center(Margin::X(1, Layers::new(|add|{ - ////add(&Background(Color::Rgb(128,0,0)))?; - ////add(&Stack::down(|add|{ - ////add(&Margin::Y(1, Layers::new(|add|{ - ////add(&Background(Color::Rgb(0,128,0)))?; - ////add(&Align::Center("12345"))?; - ////add(&Align::Center("FOO")) - ////})))?; - ////add(&Margin::XY(1, 1, Layers::new(|add|{ - ////add(&Align::Center("1234567"))?; - ////add(&Align::Center("BAR"))?; - ////add(&Background(Color::Rgb(0,0,128))) - ////}))) - ////})) - ////}))) - - ////Align::Y(Layers::new(|add|{ - ////add(&Background(Color::Rgb(128,0,0)))?; - ////add(&Margin::X(1, Align::Center(Stack::down(|add|{ - ////add(&Align::X(Margin::Y(1, Layers::new(|add|{ - ////add(&Background(Color::Rgb(0,128,0)))?; - ////add(&Align::Center("12345"))?; - ////add(&Align::Center("FOO")) - ////})))?; - ////add(&Margin::XY(1, 1, Layers::new(|add|{ - ////add(&Align::Center("1234567"))?; - ////add(&Align::Center("BAR"))?; - ////add(&Background(Color::Rgb(0,0,128))) - ////})))?; - ////Ok(()) - ////}))))) - ////})) - //} diff --git a/src/draw.rs b/src/draw.rs index 9d27ad3..6a7bc5b 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -13,20 +13,16 @@ use crate::*; /// } /// impl Screen for TestOut { /// type Unit = u16; -/// fn show (&mut self, _: impl Draw) -> Perhaps> { -/// println!("placed"); -/// Ok(None) -/// } -/// fn area (&self) -> XYWH { -/// Default::default() -/// } +/// fn show (&mut self, _: impl Draw) -> Perhaps> +/// { println!("placed"); Ok(None) } +/// fn area (&self) -> XYWH +/// { Default::default() } /// fn clip ( /// &mut self, /// area: impl Into>>, /// draw: impl FnOnce(&mut Self)->T -/// ) -> T { -/// draw(self) -/// } +/// ) -> T +/// { draw(self } /// } /// /// impl_draw!(|self: String, to: TestOut|{ @@ -154,6 +150,7 @@ features! { layout, lrtb, sizer, + space, split, thunk, xywh diff --git a/src/draw/coord.rs b/src/draw/coord.rs index 6f0b611..053258e 100644 --- a/src/draw/coord.rs +++ b/src/draw/coord.rs @@ -22,7 +22,7 @@ pub trait Coord: Send + Sync + Copy + From + Into + Into + Into - //+ std::iter::Step + + std::iter::Step { /// Zero in own type. fn zero () -> Self { 0.into() } diff --git a/src/draw/layout.rs b/src/draw/layout.rs index fba4d9b..0561f2a 100644 --- a/src/draw/layout.rs +++ b/src/draw/layout.rs @@ -1,5 +1,3 @@ -#![allow(unused)] - use crate::*; impl> Layout for T {} @@ -160,14 +158,10 @@ pub trait Layout: Draw + Sized { /// Use whole drawing area along one or both axes. /// /// ``` -/// # fn doctest_layout_full () -> Result<(), Box> { -/// use tengri::{Layout, Draw, XYWH}; -/// let area = XYWH(0u16, 0, 80, 25); -/// assert_eq!("1".layout(area)?, Some(XYWH(0u16, 0, 1, 1))); -/// assert_eq!("1".full_w().layout(area)?, Some(XYWH(0u16, 0, 80, 1))); -/// assert_eq!("1".full_h().layout(area)?, Some(XYWH(0u16, 0, 1, 25))); -/// assert_eq!("1".full_wh().layout(area)?, Some(XYWH(0u16, 0, 80, 25))); -/// # Ok(()) } +/// use tengri::Layout; +/// let _ = "".full_w(); +/// let _ = "".full_h(); +/// let _ = "".full_wh(); /// ``` pub enum Full> { __(PhantomData), @@ -175,6 +169,7 @@ pub enum Full> { H(I), WH(I), } + impl_draw!(,>|self: Full, to: T|{ let XYWH(x0, y0, w0, h0) = to.area(); match self { @@ -200,14 +195,10 @@ impl_draw!(,>|self: Full, to: T|{ /// Move content in the positive direction of one or both axes. /// /// ``` -/// # fn doctest_layout_push () -> Result<(), Box> { -/// use tengri::{Layout, Draw, XYWH}; -/// let area = XYWH(0u16, 0, 80, 25); -/// assert_eq!("1".layout(area)?, Some(XYWH(0u16, 0, 1, 1))); -/// assert_eq!("1".push_x(1).layout(area)?, Some(XYWH(1u16, 0, 1, 1))); -/// assert_eq!("1".push_y(1).layout(area)?, Some(XYWH(0u16, 1, 1, 1))); -/// assert_eq!("1".push_xy(1, 1).layout(area)?, Some(XYWH(1u16, 1, 1, 1))); -/// # Ok(()) } +/// use tengri::Layout; +/// let _ = "".push_x(1); +/// let _ = "".push_y(1); +/// let _ = "".push_xy(1, 1); /// ``` pub enum Push, X: Into>> { __(PhantomData), @@ -215,6 +206,7 @@ pub enum Push, X: Into>> { Y(I, X), XY(I, X, X), } + impl_draw!(, X: Into>,>|self: Push, to: T|{ match self { Self::__(_) => unreachable!(), @@ -240,14 +232,10 @@ impl_draw!(, X: Into>,>|self: Push Result<(), Box> { -/// use tengri::{Layout, Draw, XYWH}; -/// let area = XYWH(1u16, 1, 80, 25); -/// assert_eq!("1".layout(area)?, Some(XYWH(0u16, 0, 1, 1))); -/// assert_eq!("1".pull_x(1).layout(area)?, Some(XYWH(0u16, 1, 1, 1))); -/// assert_eq!("1".pull_y(1).layout(area)?, Some(XYWH(1u16, 0, 1, 1))); -/// assert_eq!("1".pull_xy(1, 1).layout(area)?, Some(XYWH(0u16, 0, 1, 1))); -/// # Ok(()) } +/// use tengri::Layout; +/// let _ = "".pull_x(1); +/// let _ = "".pull_y(1); +/// let _ = "".pull_xy(1, 1); /// ``` pub enum Pull, X: Into>> { __(PhantomData), @@ -255,6 +243,7 @@ pub enum Pull, X: Into>> { Y(I, X), XY(I, X, X), } + impl_draw!(, X: Into>,>|self: Pull, _to: T|{ todo!() }); @@ -262,14 +251,10 @@ impl_draw!(, X: Into>,>|self: Pull Result<(), Box> { -/// use tengri::{Layout, Draw, XYWH}; -/// let area = XYWH(1u16, 1, 80, 25); -/// assert_eq!("1".min_w(5).layout(area)?, Some(XYWH(1u16, 1, 5, 1))); -/// assert_eq!("1".min_h(5).layout(area)?, Some(XYWH(1u16, 1, 1, 5))); -/// assert_eq!("1".min_wh(5, 5).layout(area)?, Some(XYWH(1u16, 1, 5, 5))); -/// assert_eq!("123456".min_w(5).layout(area)?, Some(XYWH(1u16, 1, 6, 1))); -/// # Ok(()) } +/// use tengri::Layout; +/// let _ = "".min_w(1); +/// let _ = "".min_h(1); +/// let _ = "".min_wh(1, 1); /// ``` pub enum Min, X: Into>> { __(PhantomData), @@ -277,6 +262,7 @@ pub enum Min, X: Into>> { H(I, X), WH(I, X, X), } + impl_draw!(, X: Into>,>|self: Min, _to: T|{ todo!() }); @@ -284,13 +270,10 @@ impl_draw!(, X: Into>,>|self: Min /// Set maximum size of of drawing area. /// /// ``` -/// # fn doctest_layout_max () -> Result<(), Box> { -/// use tengri::{Layout, Draw, XYWH}; -/// let area = XYWH(1u16, 1, 80, 25); -/// assert_eq!("12345".max_w(1).layout(area)?, Some(XYWH(1u16, 1, 1, 1))); -/// assert_eq!("12345".max_h(1).layout(area)?, Some(XYWH(1u16, 1, 1, 1))); -/// assert_eq!("12345".max_wh(1, 1).layout(area)?, Some(XYWH(1u16, 1, 5, 1))); -/// # Ok(()) } +/// use tengri::Layout; +/// let _ = "".max_w(1); +/// let _ = "".max_h(1); +/// let _ = "".max_wh(1, 1); /// ``` pub enum Max, X: Into>> { __(PhantomData), @@ -298,6 +281,7 @@ pub enum Max, X: Into>> { H(I, X), WH(I, X, X), } + impl_draw!(, X: Into>,>|self: Max, to: T|{ let area: XYWH = to.area(); let (item, area) = match self { @@ -332,6 +316,7 @@ pub enum Exact, X: Into>> { H(I, X), WH(I, X, X), } + impl_draw!(, X: Into>,>|self: Exact, to: T|{ let area: XYWH = to.area(); let (item, area) = match self { @@ -360,27 +345,29 @@ pub enum Pad, X: Into>> { H(I, X), WH(I, X, X), } + impl_draw!(, X: Into>,>|self: Pad, _to: T|{ todo!() }); pub struct Align(Option, T); + impl_draw!(,>|self: Align, to: S|{ use Azimuth::*; let XYWH(x0, y0, w0, h0) = to.area(); if let Some(XYWH(x, y, w, h)) = self.1.layout(to.area())? { to.clip(match self.0 { - Some(NW) => XYWH(x0, y0, w, h), - Some(N) => XYWH(x0 + w0.minus(w) / 2.into(), y0, w, h), - Some(NE) => XYWH((x0 + w0).minus(w), y0, w, h), - Some(W) => XYWH(x0, y0 + h0.minus(h) / 2.into(), w, h), - Some(C) => XYWH(x0 + w0.minus(w) / 2.into(), y0 + h0.minus(h) / 2.into(), w, h), - Some(E) => XYWH((x0 + w0).minus(w), y0 + h0.minus(h) / 2.into(), w, h), - Some(SW) => XYWH(x0, (y0 + h0).minus(h), w, h), - Some(S) => XYWH(x0 + w0.minus(w) / 2.into(), (y0 + h0).minus(h), w, h), - Some(SE) => XYWH((x0 + w0).minus(w), (y0 + h0).minus(h), w, h), - Some(X) => XYWH(x0 + w0.minus(w) / 2.into(), y, w, h), - Some(Y) => XYWH(x, y0 + h0.minus(h) / 2.into(), w, h), + Some(NW) => XYWH(x0, y0, w, h), + Some(N) => XYWH(x0 + w0.sub(w) / 2.into(), y0, w, h), + Some(NE) => XYWH((x0 + w0).sub(w), y0, w, h), + Some(W) => XYWH(x0, y0 + h0.sub(h) / 2.into(), w, h), + Some(C) => XYWH(x0 + w0.sub(w) / 2.into(), y0 + h0.sub(h) / 2.into(), w, h), + Some(E) => XYWH((x0 + w0).sub(w), y0 + h0.sub(h) / 2.into(), w, h), + Some(SW) => XYWH(x0, (y0 + h0).sub(h), w, h), + Some(S) => XYWH(x0 + w0.sub(w) / 2.into(), (y0 + h0).sub(h), w, h), + Some(SE) => XYWH((x0 + w0).sub(w), (y0 + h0).sub(h), w, h), + Some(X) => XYWH(x0 + w0.sub(w) / 2.into(), y, w, h), + Some(Y) => XYWH(x, y0 + h0.sub(h) / 2.into(), w, h), None => to.area() }, |to|self.1.draw(to)) } else { @@ -416,11 +403,13 @@ pub struct Area>( pub Option>, pub T ); + impl_draw!(,>|self: Area, to: S|{ to.clip(self.0, |to|self.1.draw(to)) }); pub struct Origin(Option, T); + impl_draw!(,>|self: Origin, _to: S|{ todo!() }); diff --git a/src/draw/lrtb.rs b/src/draw/lrtb.rs index 586f912..7f8b182 100644 --- a/src/draw/lrtb.rs +++ b/src/draw/lrtb.rs @@ -8,7 +8,7 @@ pub trait Lrtb: Xywh { // FIXME: factor origin [self.x(), self.y(), self.x()+self.w(), self.y()+self.h()] } - fn iter_x (&self) -> std::ops::Range where Self: HasOrigin { + fn iter_x (&self) -> impl Iterator where Self: HasOrigin { self.x_west()..self.x_east() } fn x_west (&self) -> N where Self: HasOrigin { @@ -26,7 +26,7 @@ pub trait Lrtb: Xywh { fn x_center (&self) -> N where Self: HasOrigin { todo!() } - fn iter_y (&self) -> std::ops::Range where Self: HasOrigin { + fn iter_y (&self) -> impl Iterator where Self: HasOrigin { self.y_north()..self.y_south() } fn y_north (&self) -> N where Self: HasOrigin { diff --git a/src/draw/sizer.rs b/src/draw/sizer.rs index 5e20693..7ff5ed5 100644 --- a/src/draw/sizer.rs +++ b/src/draw/sizer.rs @@ -29,17 +29,3 @@ impl Sizer { }) } } - -pub struct ShowSize; - -impl Draw for ShowSize { - fn layout (&self, area: XYWH) -> Perhaps> { - let info = format!("{area:?}"); - Ok(Some(XYWH(area.0, area.1, info.len() as u16, 1))) - } - fn draw (self, to: &mut Tui) -> Drawn { - let area = to.area(); - let info = format!("{area:?}"); - to.text(&info, area.0, area.1, info.len() as u16) - } -} diff --git a/src/draw/space.rs b/src/draw/space.rs new file mode 100644 index 0000000..6576b44 --- /dev/null +++ b/src/draw/space.rs @@ -0,0 +1,2 @@ +use crate::*; + diff --git a/src/eval.rs b/src/eval.rs index e0df0f1..35ec582 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -190,11 +190,18 @@ pub fn eval_view <'a, O: Screen + 'a, S> ( /// use tengri::{*, lang::*, ratatui::prelude::Color}; /// /// #[namespace(bool)] -/// #[namespace(u8)] -/// #[namespace(u16)] -/// #[namespace(Color get_color)] +/// #[namespace(u8 try_to_u8)] +/// #[namespace(u16 try_to_u16)] +/// #[namespace(Color try_to_color)] +/// #[interpret(Tui -> Option>: try_eval_tui)] /// struct State; -/// +/// tengri::lang::primitive!(u8: try_to_u8); +/// tengri::lang::primitive!(u16: try_to_u16); +/// tengri::lang::interpret!(|self: State, context: Tui, lang|->Option>{ +/// expression = { +/// "text" (...rest) => { todo!() } +/// } +/// }); /// impl Interpret>> for State { /// fn interpret_expr <'a> (&'a self, _: &mut Tui, lang: &'a impl Expression) /// -> Usually>> @@ -203,36 +210,6 @@ pub fn eval_view <'a, O: Screen + 'a, S> ( /// } /// } /// -/// fn get_color (state: &State, src: impl Language) -> Perhaps { -/// if let Some(expr) = src.expr()? { -/// match (expr.head()?, expr.tail()?) { -/// (Some("g"), Some(tail)) => { -/// let n: u8 = state.namespace(tail.head().map_err(Into::into))?.ok_or(LanguageError::Domain("not gray"))?; -/// Ok(Some(Color::Rgb(n, n, n))) -/// }, -/// (Some("rgb"), Some(tail)) => { -/// let r: u8 = state.namespace(tail.head().map_err(Into::into))? -/// .ok_or(LanguageError::Domain("not red"))?; -/// let g: u8 = state.namespace(tail.tail().head().map_err(Into::into))? -/// .ok_or(LanguageError::Domain("not green"))?; -/// let b: u8 = state.namespace(tail.tail().tail().head().map_err(Into::into))? -/// .ok_or(LanguageError::Domain("not blue"))?; -/// Ok(Some(Color::Rgb(r, g, b))) -/// }, -/// (Some(_), _) => return Err(format!("not a color expression: {expr}").into()), -/// (None, _) => return Err(format!("not a color expression: {expr}").into()), -/// } -/// } else if let Ok(Some(sym)) = src.word() { -/// Ok(match sym { -/// ":color/bg" => Some(Color::Rgb(28, 32, 36)), -/// ":color/fg" => Some(Color::Rgb(98, 92, 96)), -/// _ => return Err(format!("not a color: {sym}").into()) -/// }) -/// } else { -/// return Err(format!("not a color: {:?}", src.src()?).into()) -/// } -/// } -/// /// # fn main () -> tengri::Usually<()> { /// let state = State; /// let mut out = Tui::new(80, 25); @@ -244,7 +221,7 @@ pub fn eval_view <'a, O: Screen + 'a, S> ( /// # Ok(()) } /// ``` pub fn eval_view_tui <'a, S> ( - state: &S, to: &mut Tui, expr: impl Expression + 'a + state: &S, output: &mut Tui, expr: impl Expression + 'a ) -> Perhaps> where S: Interpret>> + for<'b>Namespace<'b, bool> @@ -262,7 +239,7 @@ pub fn eval_view_tui <'a, S> ( match frags.next() { Some("text") => { if let Some(src) = args?.src()? { - to.show(src) + output.show(src) } else { return Ok(None) } @@ -271,10 +248,11 @@ pub fn eval_view_tui <'a, S> ( Some("fg") => { let arg0 = arg0?.expect("fg: expected arg 0 (color)"); if let Some(color) = Namespace::namespace(state, arg0)? { - fg(color, thunk(move|to: &mut Tui|{ - state.interpret(to, &arg1)?; - Ok(Some(to.area().into())) // FIXME?: don't max out the used area? - })).draw(to) + output.show(fg(color, thunk(move|output: &mut Tui|{ + state.interpret(output, &arg1)?; + // FIXME?: don't max out the used area? + Ok(Some(output.area().into())) + }))) } else { return Err(format!("fg: {arg0:?}: not a color").into()) } @@ -283,10 +261,11 @@ pub fn eval_view_tui <'a, S> ( Some("bg") => { let arg0 = arg0?.expect("bg: expected arg 0 (color)"); if let Some(color) = Namespace::namespace(state, arg0)? { - bg(color, thunk(move|to: &mut Tui|{ - state.interpret(to, &arg1)?; - Ok(Some(to.area().into())) // FIXME?: don't max out the used area? - })).draw(to) + output.show(bg(color, thunk(move|output: &mut Tui|{ + state.interpret(output, &arg1)?; + // FIXME?: don't max out the used area? + Ok(Some(output.area().into())) + }))) } else { return Err(format!("bg: {arg0:?}: not a color").into()) } diff --git a/src/lib.rs b/src/lib.rs index 4b6fcfb..155a53f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,11 @@ -//#![feature(anonymous_lifetime_in_impl_trait)] +#![feature(anonymous_lifetime_in_impl_trait)] //#![feature(associated_type_defaults)] //#![feature(const_default)] //#![feature(const_option_ops)] -//#![feature(const_precise_live_drops)] -//#![feature(const_trait_impl)] +#![feature(const_precise_live_drops)] +#![feature(const_trait_impl)] //#![feature(impl_trait_in_assoc_type)] -//#![feature(step_trait)] +#![feature(step_trait)] //#![feature(trait_alias)] //#![feature(type_alias_impl_trait)] //#![feature(type_changing_struct_update)] diff --git a/src/sing.rs b/src/sing.rs index d7d4469..c06a1e5 100644 --- a/src/sing.rs +++ b/src/sing.rs @@ -803,7 +803,7 @@ pub trait AddMidiOut { /// Port connection manager. /// /// ``` -/// let connect = tengri::Connect::default(); +/// let connect = tek::Connect::default(); /// ``` #[derive(Clone, Debug, Default)] pub struct Connect { @@ -814,6 +814,7 @@ pub struct Connect { } impl Connect { + pub fn new > ( exact: Option>, re: Option>, @@ -826,6 +827,62 @@ impl Connect { connections } + pub fn midi_ins > ( + jack: &Jack<'static>, + name: &T, + midi_from: &[T], + midi_from_re: Option<&[T]>, + ) -> Usually> { + Ok(Connect::new( + Some(midi_from.into_iter()), + Some([].into_iter()), + midi_from_re.map(|x|x.into_iter())).iter().enumerate() + .map(|(index, connect)|jack.midi_in(&format!("{}/{index}", name.as_ref()), &[connect.clone()])) + .collect::>()?) + } + + pub fn midi_outs > ( + jack: &Jack<'static>, + name: &T, + midi_to: &[T], + midi_to_re: Option<&[T]>, + ) -> Usually> { + Ok(Connect::new( + Some(midi_to.into_iter()), + Some([].into_iter()), + midi_to_re.map(|x|x.into_iter())).iter().enumerate() + .map(|(index, connect)|jack.midi_out(&format!("{index}/{}", name.as_ref()), &[connect.clone()])) + .collect::>()?) + } + + pub fn audio_ins > ( + jack: &Jack<'static>, + name: &T, + audio_from: &[T], + audio_from_re: Option<&[T]>, + ) -> Usually> { + Ok(Connect::new( + Some(audio_from.into_iter()), + Some([].into_iter()), + audio_from_re.map(|x|x.into_iter())).iter().enumerate() + .map(|(index, connect)|jack.audio_in(&format!("{}/{index}", name.as_ref()), &[connect.clone()])) + .collect::>()?) + } + + pub fn audio_outs > ( + jack: &Jack<'static>, + name: &T, + audio_to: &[T], + audio_to_re: Option<&[T]>, + ) -> Usually> { + Ok(Connect::new( + Some(audio_to.into_iter()), + Some([].into_iter()), + audio_to_re.map(|x|x.into_iter())).iter().enumerate() + .map(|(index, connect)|jack.audio_out(&format!("{index}/{}", name.as_ref()), &[connect.clone()])) + .collect::>()?) + } + /// Connect to this exact port pub fn exact (name: impl AsRef) -> Self { let info = format!("=:{}", name.as_ref()).into(); @@ -866,59 +923,3 @@ impl Connect { }).into() } } - -pub fn connect_midi_ins > ( - jack: &Jack<'static>, - name: &T, - midi_from: &[T], - midi_from_re: Option<&[T]>, -) -> Usually> { - Ok(Connect::new( - Some(midi_from.into_iter()), - Some([].into_iter()), - midi_from_re.map(|x|x.into_iter())).iter().enumerate() - .map(|(index, connect)|jack.midi_in(&format!("{}/{index}", name.as_ref()), &[connect.clone()])) - .collect::>()?) -} - -pub fn connect_midi_outs > ( - jack: &Jack<'static>, - name: &T, - midi_to: &[T], - midi_to_re: Option<&[T]>, -) -> Usually> { - Ok(Connect::new( - Some(midi_to.into_iter()), - Some([].into_iter()), - midi_to_re.map(|x|x.into_iter())).iter().enumerate() - .map(|(index, connect)|jack.midi_out(&format!("{index}/{}", name.as_ref()), &[connect.clone()])) - .collect::>()?) -} - -pub fn connect_audio_ins > ( - jack: &Jack<'static>, - name: &T, - audio_from: &[T], - audio_from_re: Option<&[T]>, -) -> Usually> { - Ok(Connect::new( - Some(audio_from.into_iter()), - Some([].into_iter()), - audio_from_re.map(|x|x.into_iter())).iter().enumerate() - .map(|(index, connect)|jack.audio_in(&format!("{}/{index}", name.as_ref()), &[connect.clone()])) - .collect::>()?) -} - -pub fn connect_audio_outs > ( - jack: &Jack<'static>, - name: &T, - audio_to: &[T], - audio_to_re: Option<&[T]>, -) -> Usually> { - Ok(Connect::new( - Some(audio_to.into_iter()), - Some([].into_iter()), - audio_to_re.map(|x|x.into_iter())).iter().enumerate() - .map(|(index, connect)|jack.audio_out(&format!("{index}/{}", name.as_ref()), &[connect.clone()])) - .collect::>()?) -} diff --git a/src/sing/jack.rs b/src/sing/jack.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/sing/jack_event.rs b/src/sing/jack_event.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/sing/jack_perf.rs b/src/sing/jack_perf.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/term/buffer.rs b/src/term/buffer.rs index f95ab52..fcd83f1 100644 --- a/src/term/buffer.rs +++ b/src/term/buffer.rs @@ -1,4 +1,5 @@ -use crate::lang::*; +use crate::*; +use crate::{*, lang::*, draw::*, task::*, exit::*}; use ::ratatui::buffer::Cell; /// TUI buffer sized by `usize` instead of `u16`. diff --git a/src/term/colors.rs b/src/term/colors.rs index 8d63fc2..f224b69 100644 --- a/src/term/colors.rs +++ b/src/term/colors.rs @@ -1,6 +1,6 @@ use crate::*; use ratatui::prelude::Color; -use dizzle::{Expression, LanguageError::*}; +use dizzle::{Ostensibly, Expression, LanguageError::*}; pub trait ColorDsl: Sized { fn new_g (expr: T, try_to_u8: impl Fn(Perhaps<&str>)->Perhaps) -> Usually; diff --git a/src/term/keys.rs b/src/term/keys.rs index f4ab04e..a0ccca8 100644 --- a/src/term/keys.rs +++ b/src/term/keys.rs @@ -1,5 +1,10 @@ -use ::dizzle::{Language, Symbol, Usually}; -use ::crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState}; +use crate::{task::Task, term::TuiEvent}; +use ::std::sync::{Arc, RwLock, atomic::{AtomicBool, Ordering::*}}; +use ::std::time::Duration; +use ::dizzle::{Language, Symbol, Usually, Apply}; +use ::crossterm::event::{ + read, Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState +}; /// TUI key spec. #[derive(Debug, Clone, Eq, PartialEq, PartialOrd)] diff --git a/src/term/phat.rs b/src/term/phat.rs index 9d3e6ed..ec24914 100644 --- a/src/term/phat.rs +++ b/src/term/phat.rs @@ -1,3 +1,5 @@ +use crate::*; + /// Stackably padded. /// /// ``` diff --git a/src/term/repeat.rs b/src/term/repeat.rs index 0ea6508..fe989e7 100644 --- a/src/term/repeat.rs +++ b/src/term/repeat.rs @@ -1,5 +1,5 @@ use crate::*; -use ratatui::{prelude::{Position}}; +use ratatui::{prelude::{Style, Position, Backend, Color}}; pub const fn x_repeat (c: &str) -> impl Draw { thunk(move|to: &mut Tui|{ diff --git a/src/term/scroll.rs b/src/term/scroll.rs index 8900360..3608237 100644 --- a/src/term/scroll.rs +++ b/src/term/scroll.rs @@ -1,5 +1,5 @@ use crate::*; -use ratatui::{prelude::{Position}}; +use ratatui::{prelude::{Style, Position, Backend, Color}}; pub const ICON_DEC_V: &[char] = &['▲']; pub const ICON_INC_V: &[char] = &['▼']; @@ -7,7 +7,7 @@ pub const ICON_DEC_H: &[char] = &[' ', '🞀', ' ']; pub const ICON_INC_H: &[char] = &[' ', '🞂', ' ']; pub fn x_scroll () -> impl Draw { - thunk(|Tui(buf, XYWH(x1, y1, w, _h)): &mut Tui|{ + thunk(|Tui(buf, XYWH(x1, y1, w, h)): &mut Tui|{ let x2 = *x1 + *w; for (i, x) in (*x1..=x2).enumerate() { if let Some(cell) = buf.cell_mut(Position::from((x, *y1))) { @@ -35,7 +35,7 @@ pub fn x_scroll () -> impl Draw { } pub fn y_scroll () -> impl Draw { - thunk(|Tui(buf, XYWH(x1, y1, _w, h)): &mut Tui|{ + thunk(|Tui(buf, XYWH(x1, y1, w, h)): &mut Tui|{ let y2 = *y1 + *h; for (i, y) in (*y1..=y2).enumerate() { if let Some(cell) = buf.cell_mut(Position::from((*x1, y))) { diff --git a/src/text.rs b/src/text.rs index 07d438c..3fd8806 100644 --- a/src/text.rs +++ b/src/text.rs @@ -1,36 +1,18 @@ -#![allow(unused)] - use crate::*; pub(crate) use ::unicode_width::*; #[cfg(feature = "term")] mod impl_term { use super::*; + use crate::*; use ratatui::prelude::Position; impl_draw!(|self: String, to: Tui|{self.as_str().draw(to)}); impl_draw!(|self: std::sync::Arc, to: Tui|{self.as_ref().draw(to)}); impl_draw!(|self: &std::sync::Arc, to: Tui|{self.as_ref().draw(to)}); - impl Draw for &str { - fn layout (&self, area: XYWH) -> Perhaps> { - let XYWH(x, y, ..) = area; - let mut max_w = 0u16; - let mut max_h = 0u16; - for line in self.split("\n") { - max_h += 1; - max_w = max_w.max(line.len() as u16); - } - Ok(Some(XYWH(x, y, max_w, max_h))) - } - fn draw (self, to: &mut Tui) -> Drawn { - let area = self.layout(to.area())?.unwrap(); - ////let info = format!("{area:?}"); - //to.text(&self, area.0, area.1, self.len() as u16) - for (index, line) in self.split("\n").enumerate() { - let _ = to.text(&line, area.0, area.1 + index as u16, width_chars_max(area.2, line) as u16)?; - } - Ok(Some(area)) - } - } + impl_draw!(|self: &str, to: Tui|{ + let XYWH(x, y, w, ..) = to.1.centered_xy([width_chars_max(to.w(), self), 1]); + to.text(&self, x, y, w) + }); impl_draw!(,>|self: TrimString, to: Tui|{self.as_ref().draw(to)}); impl_draw!(,>|self: TrimStringRef<'_, T>, to: Tui|{ @@ -98,9 +80,7 @@ pub fn trim_string (max_width: usize, input: impl AsRef) -> String { pub struct TrimString>(pub u16, pub T); impl> AsRef for TrimString { fn as_ref (&self) -> &str { self.1.as_ref() } } impl<'a, T: AsRef> TrimString { - fn to_ref (&self) -> TrimStringRef<'_, T> { - TrimStringRef(self.0, &self.1) - } + fn to_ref (&self) -> TrimStringRef<'_, T> { TrimStringRef(self.0, &self.1) } } /// Displays a borrowed [str]-like with fixed maximum width