diff --git a/cli/tek.rs b/cli/tek.rs index 4d47d68d..0f5ce513 100644 --- a/cli/tek.rs +++ b/cli/tek.rs @@ -1,5 +1,5 @@ -use tek::*; -use clap::{self, Parser, Subcommand}; +pub use tek::*; +pub(crate) use clap::{self, Parser, Subcommand}; /// Application entrypoint. pub fn main () -> Usually<()> { TekCli::parse().run() diff --git a/edn/src/iter.rs b/edn/src/iter.rs index 90792174..f5916667 100644 --- a/edn/src/iter.rs +++ b/edn/src/iter.rs @@ -1,4 +1,18 @@ +//! The token iterator [TokenIter] allows you to get the +//! general-purpose syntactic [Token]s represented by the source text. +//! +//! Both iterators are `peek`able: +//! +//! ``` +//! let src = include_str!("../../tek/src/view_arranger.edn") +//! let mut view = TokenIter(src); +//! assert_eq!(view.0.0, src); +//! assert_eq!(src.peek(), src.0.peek())) +//! ``` use crate::*; +/// Provides a native [Iterator] API over the [ConstIntoIter] [SourceIter] +/// [TokenIter::next] returns just the [Token] and mutates `self`, +/// instead of returning an updated version of the struct as [SourceIter::next] does. #[derive(Copy, Clone, Debug, Default, PartialEq)] pub struct TokenIter<'a>(pub SourceIter<'a>); impl<'a> TokenIter<'a> { pub const fn new (source: &'a str) -> Self { Self(SourceIter::new(source)) } @@ -10,6 +24,11 @@ impl<'a> Iterator for TokenIter<'a> { self.0.next().map(|(item, rest)|{self.0 = rest; item}) } } +/// Owns a reference to the source text. +/// [SourceIter::next] emits subsequent pairs of: +/// * a [Token] and +/// * the source text remaining +/// * [ ] TODO: maybe [SourceIter::next] should wrap the remaining source in `Self` ? #[derive(Copy, Clone, Debug, Default, PartialEq)] pub struct SourceIter<'a>(pub &'a str); const_iter!(<'a>|self: SourceIter<'a>| => Token<'a> => self.next_mut().map(|(result, _)|result)); impl<'a> From<&'a str> for SourceIter<'a> {fn from (source: &'a str) -> Self{Self::new(source)}} diff --git a/edn/src/lib.rs b/edn/src/lib.rs index 4469bf53..cb660327 100644 --- a/edn/src/lib.rs +++ b/edn/src/lib.rs @@ -5,15 +5,8 @@ mod error; pub use self::error::*; mod token; pub use self::token::*; mod iter; pub use self::iter::*; mod context; pub use self::context::*; -//mod atom; pub use self::atom::*; -//mod atom_ref; pub use self::atom_ref::*; -//mod atom_arc; pub use self::atom_arc::*; pub(crate) use self::Value::*; pub(crate) use self::ParseError::*; -//pub(crate) use self::TokenKind::*; -pub(crate) use std::sync::Arc; -//pub(crate) use std::marker::ConstParamTy; -pub(crate) use itertools::join; pub(crate) use konst::iter::{ConstIntoIter, IsIteratorKind}; pub(crate) use konst::string::{split_at, str_range, char_indices}; pub(crate) use std::error::Error; @@ -81,27 +74,27 @@ pub(crate) use std::fmt::{Debug, Display, Formatter, Result as FormatResult, Err Ok(()) } -#[cfg(test)] #[test] fn test_examples () -> Result<(), ParseError> { - let src = include_str!("../../tek/src/view_arranger.edn"); - let mut view = SourceIter(src); - assert_eq!(view.0, src); - let mut expr = view.peek(); - assert_eq!(view.0, src); - assert_eq!(expr, Some(Token { - source: src, - start: 0, - length: src.len(), - value: Exp(0, SourceIter(&src[1..])) - })); - //panic!("{view:?}"); - //panic!("{:#?}", expr); - //for example in [ - //include_str!("../../tui/examples/edn01.edn"), - //include_str!("../../tui/examples/edn02.edn"), - //] { - ////let items = Atom::read_all(example)?; - ////panic!("{layout:?}"); - ////let content = >::from(&layout); - //} - Ok(()) -} +//#[cfg(test)] #[test] fn test_examples () -> Result<(), ParseError> { + //// Let's pretend to render some view. + //let source = include_str!("../../tek/src/view_arranger.edn"); + //// The token iterator allows you to get the tokens represented by the source text. + //let mut view = TokenIter(source); + //// The token iterator wraps a const token+source iterator. + //assert_eq!(view.0.0, source); + //let mut expr = view.peek(); + //assert_eq!(view.0.0, source); + //assert_eq!(expr, Some(Token { + //source, start: 0, length: source.len() - 1, value: Exp(0, SourceIter(&source[1..])) + //})); + ////panic!("{view:?}"); + ////panic!("{:#?}", expr); + ////for example in [ + ////include_str!("../../tui/examples/edn01.edn"), + ////include_str!("../../tui/examples/edn02.edn"), + ////] { + //////let items = Atom::read_all(example)?; + //////panic!("{layout:?}"); + //////let content = >::from(&layout); + ////} + //Ok(()) +//} diff --git a/edn/src/token.rs b/edn/src/token.rs index 0b041ea7..352ba2c9 100644 --- a/edn/src/token.rs +++ b/edn/src/token.rs @@ -1,3 +1,24 @@ +//! [Token]s are parsed substrings with an associated [Value]. +//! +//! * [ ] FIXME: Value may be [Err] which may shadow [Result::Err] +//! * [Value::Exp] wraps an expression depth and a [SourceIter] +//! with the remaining part of the expression. +//! * expression depth other that 0 mean unclosed parenthesis. +//! * closing and unopened parenthesis panics during reading. +//! * [ ] TODO: signed depth might be interesting +//! * [Value::Sym] and [Value::Key] are stringish literals +//! with slightly different parsing rules. +//! * [Value::Num] is an unsigned integer literal. +//!``` +//! let src = include_str!("../../tek/src/view_arranger.edn") +//! let mut view = TokenIter(src); +//! assert_eq!(source.peek(), Some(Token { +//! source, +//! start: 0, +//! length: source.len() - 1, +//! value: Exp(0, SourceIter(&source[1..])) +//! }))) +//!``` use crate::*; use self::Value::*; #[derive(Debug, Copy, Clone, Default, PartialEq)] pub struct Token<'a> { diff --git a/input/src/keymap.rs b/input/src/keymap.rs index 28024894..fca114b9 100644 --- a/input/src/keymap.rs +++ b/input/src/keymap.rs @@ -1,5 +1,5 @@ use crate::*; -/// [Input] state that can be matched against an [Atom]. +/// [Input] state that can be matched against a [Value]. pub trait AtomInput: Input { fn matches_atom (&self, token: &str) -> bool; } @@ -222,6 +222,6 @@ impl<'a, C, T: TryFromAtom<'a, C> + Command> AtomCommand<'a, C> for T {} //} //} #[cfg(test)] #[test] fn test_atom_keymap () -> Usually<()> { - let keymap = KeyMap::new("")?; + let keymap = SourceIter::new(""); Ok(()) } diff --git a/midi/src/lib.rs b/midi/src/lib.rs index 2f87ea90..98908d98 100644 --- a/midi/src/lib.rs +++ b/midi/src/lib.rs @@ -1,17 +1,15 @@ mod midi_clip; pub use midi_clip::*; -mod midi_launch; pub use midi_launch::*; -mod midi_player; pub use midi_player::*; +mod midi_edit; pub use midi_edit::*; mod midi_in; pub use midi_in::*; +mod midi_launch; pub use midi_launch::*; mod midi_out; pub use midi_out::*; - mod midi_pitch; pub use midi_pitch::*; -mod midi_range; pub use midi_range::*; +mod midi_player; pub use midi_player::*; mod midi_point; pub use midi_point::*; +mod midi_pool; pub use midi_pool::*; +mod midi_range; pub use midi_range::*; mod midi_view; pub use midi_view::*; - -mod midi_pool; pub use midi_pool::*; -mod midi_edit; pub use midi_edit::*; -mod piano_h; pub use self::piano_h::*; +mod piano_h; pub use self::piano_h::*; pub(crate) use ::tek_time::*; pub(crate) use ::tek_jack::{*, jack::*}; @@ -20,7 +18,6 @@ pub(crate) use ::tek_tui::{ tek_input::*, tek_output::*, tek_edn::*, - crossterm::event::*, ratatui::style::{Style, Stylize, Color} }; diff --git a/midi/src/midi_edit.rs b/midi/src/midi_edit.rs index e829bdd2..7dfc27c2 100644 --- a/midi/src/midi_edit.rs +++ b/midi/src/midi_edit.rs @@ -1,5 +1,4 @@ use crate::*; -use Value::*; pub trait HasEditor { fn editor (&self) -> &Option; fn editor_mut (&mut self) -> &Option; diff --git a/midi/src/piano_h.rs b/midi/src/piano_h.rs index f132c4b8..dd07cbaa 100644 --- a/midi/src/piano_h.rs +++ b/midi/src/piano_h.rs @@ -121,7 +121,7 @@ impl PianoHorizontal { let note_lo = self.note_lo().get(); let note_hi = self.note_hi(); let buffer = self.buffer.clone(); - RenderThunk::new(move|to: &mut TuiOut|{ + ThunkRender::new(move|to: &mut TuiOut|{ let source = buffer.read().unwrap(); let [x0, y0, w, _h] = to.area().xywh(); //if h as usize != note_axis { @@ -156,7 +156,7 @@ impl PianoHorizontal { let time_pos = self.time_pos(); let time_start = self.time_start().get(); let time_zoom = self.time_zoom().get(); - RenderThunk::new(move|to: &mut TuiOut|{ + ThunkRender::new(move|to: &mut TuiOut|{ let [x0, y0, w, _] = to.area().xywh(); for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) { if note == note_pos { @@ -187,7 +187,7 @@ impl PianoHorizontal { let key_style = Some(Style::default().fg(Color::Rgb(192, 192, 192)).bg(Color::Rgb(0, 0, 0))); let off_style = Some(Style::default().fg(TuiTheme::g(160))); let on_style = Some(Style::default().fg(TuiTheme::g(255)).bg(color.base.rgb).bold()); - Fill::y(Fixed::x(self.keys_width, RenderThunk::new(move|to: &mut TuiOut|{ + Fill::y(Fixed::x(self.keys_width, ThunkRender::new(move|to: &mut TuiOut|{ let [x, y0, _w, _h] = to.area().xywh(); for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) { to.blit(&to_key(note), x, screen_y, key_style); @@ -203,7 +203,7 @@ impl PianoHorizontal { }))) } fn timeline (&self) -> impl Content + '_ { - Fill::x(Fixed::y(1, RenderThunk::new(move|to: &mut TuiOut|{ + Fill::x(Fixed::y(1, ThunkRender::new(move|to: &mut TuiOut|{ let [x, y, w, _h] = to.area(); let style = Some(Style::default().dim()); let length = self.clip.as_ref().map(|p|p.read().unwrap().length).unwrap_or(1); diff --git a/output/src/lib.rs b/output/src/lib.rs index bb62c35d..a9565583 100644 --- a/output/src/lib.rs +++ b/output/src/lib.rs @@ -49,37 +49,5 @@ pub type Perhaps = Result, Box>; assert_eq!(Area::center(&[10u16, 10, 20, 20]), [20, 20]); } #[cfg(test)] #[test] fn test_layout () -> Usually<()> { - use ::tek_tui::{*, tek_output::*}; - let area: [u16;4] = [10, 10, 20, 20]; - let unit = (); - fn test (area: [u16;4], item: &impl Content, expected: [u16;4]) { - assert_eq!(Content::layout(item, area), expected); - assert_eq!(Render::layout(item, area), expected); - }; - test(area, &(), [20, 20, 0, 0]); - test(area, &Fill::xy(()), area); - test(area, &Fill::x(()), [10, 20, 20, 0]); - test(area, &Fill::y(()), [20, 10, 0, 20]); - test(area, &Fixed::x(4, unit), [18, 20, 4, 0]); - test(area, &Fixed::y(4, unit), [20, 18, 0, 4]); - test(area, &Fixed::xy(4, 4, unit), [18, 18, 4, 4]); - let four = ||Fixed::::xy(4, 4, unit); - test(area, &Align::nw(four()), [10, 10, 4, 4]); - test(area, &Align::n(four()), [18, 10, 4, 4]); - test(area, &Align::ne(four()), [26, 10, 4, 4]); - test(area, &Align::e(four()), [26, 18, 4, 4]); - test(area, &Align::se(four()), [26, 26, 4, 4]); - test(area, &Align::s(four()), [18, 26, 4, 4]); - test(area, &Align::sw(four()), [10, 26, 4, 4]); - test(area, &Align::w(four()), [10, 18, 4, 4]); - let two_by_four = ||Fixed::::xy(4, 2, unit); - test(area, &Align::nw(two_by_four()), [10, 10, 4, 2]); - test(area, &Align::n(two_by_four()), [18, 10, 4, 2]); - test(area, &Align::ne(two_by_four()), [26, 10, 4, 2]); - test(area, &Align::e(two_by_four()), [26, 19, 4, 2]); - test(area, &Align::se(two_by_four()), [26, 28, 4, 2]); - test(area, &Align::s(two_by_four()), [18, 28, 4, 2]); - test(area, &Align::sw(two_by_four()), [10, 28, 4, 2]); - test(area, &Align::w(two_by_four()), [10, 19, 4, 2]); Ok(()) } diff --git a/output/src/op_align.rs b/output/src/op_align.rs index 6d5c1acb..d083a735 100644 --- a/output/src/op_align.rs +++ b/output/src/op_align.rs @@ -1,3 +1,24 @@ +//! Aligns things to the container. Comes with caveats. +//! ``` +//! let four = ||Fixed::::xy(4, 4, unit); +//! test(area, &Align::nw(four()), [10, 10, 4, 4]); +//! test(area, &Align::n(four()), [18, 10, 4, 4]); +//! test(area, &Align::ne(four()), [26, 10, 4, 4]); +//! test(area, &Align::e(four()), [26, 18, 4, 4]); +//! test(area, &Align::se(four()), [26, 26, 4, 4]); +//! test(area, &Align::s(four()), [18, 26, 4, 4]); +//! test(area, &Align::sw(four()), [10, 26, 4, 4]); +//! test(area, &Align::w(four()), [10, 18, 4, 4]); +//! let two_by_four = ||Fixed::::xy(4, 2, unit); +//! test(area, &Align::nw(two_by_four()), [10, 10, 4, 2]); +//! test(area, &Align::n(two_by_four()), [18, 10, 4, 2]); +//! test(area, &Align::ne(two_by_four()), [26, 10, 4, 2]); +//! test(area, &Align::e(two_by_four()), [26, 19, 4, 2]); +//! test(area, &Align::se(two_by_four()), [26, 28, 4, 2]); +//! test(area, &Align::s(two_by_four()), [18, 28, 4, 2]); +//! 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 } pub struct Align(Alignment, A); diff --git a/output/src/op_transform.rs b/output/src/op_transform.rs index 8c534164..ab423010 100644 --- a/output/src/op_transform.rs +++ b/output/src/op_transform.rs @@ -1,3 +1,23 @@ +//! [Content] items that modify the inherent +//! dimensions of their inner [Render]ables. +//! +//! Transform may also react to the [Area] provided. +//! ``` +//! use ::tek_tui::{*, tek_output::*}; +//! let area: [u16;4] = [10, 10, 20, 20]; +//! let unit = (); +//! fn test (area: [u16;4], item: &impl Content, expected: [u16;4]) { +//! assert_eq!(Content::layout(item, area), expected); +//! assert_eq!(Render::layout(item, area), expected); +//! }; +//! test(area, &(), [20, 20, 0, 0]); +//! test(area, &Fill::xy(()), area); +//! test(area, &Fill::x(()), [10, 20, 20, 0]); +//! test(area, &Fill::y(()), [20, 10, 0, 20]); +//! test(area, &Fixed::x(4, unit), [18, 20, 4, 0]); +//! test(area, &Fixed::y(4, unit), [20, 18, 0, 4]); +//! 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. @@ -5,8 +25,8 @@ macro_rules! transform_xy { ($x:literal $y:literal $xy:literal |$self:ident : $Enum:ident, $to:ident|$area:expr) => { pub enum $Enum { X(T), Y(T), XY(T) } impl $Enum { - pub fn x (item: T) -> Self { Self::X(item) } - pub fn y (item: T) -> Self { Self::Y(item) } + pub fn x (item: T) -> Self { Self::X(item) } + pub fn y (item: T) -> Self { Self::Y(item) } pub fn xy (item: T) -> Self { Self::XY(item) } } impl<'a, E: Output + 'a, T: ViewContext<'a, E>> TryFromAtom<'a, T> diff --git a/output/src/thunk.rs b/output/src/thunk.rs index b24e3d15..ce1c6084 100644 --- a/output/src/thunk.rs +++ b/output/src/thunk.rs @@ -12,39 +12,39 @@ impl, F: Fn()->T + Send + Sync> Content for Thunk impl Render { (self.1)() } } -pub struct BoxThunk<'a, E: Output>(PhantomData, BoxBox + 'a> + Send + Sync + 'a>); -impl<'a, E: Output> BoxThunk<'a, E> { +pub struct ThunkBox<'a, E: Output>(PhantomData, BoxBox + 'a> + Send + Sync + 'a>); +impl<'a, E: Output> ThunkBox<'a, E> { pub fn new (thunk: BoxBox + 'a> + Send + Sync + 'a>) -> Self { Self(Default::default(), thunk) } } -impl<'a, E: Output> Content for BoxThunk<'a, E> { +impl<'a, E: Output> Content for ThunkBox<'a, E> { fn content (&self) -> impl Render { (self.1)() } } -impl<'a, E: Output, F: Fn()->T + Send + Sync + 'a, T: Render + Send + Sync + 'a> From for BoxThunk<'a, E> { +impl<'a, E: Output, F: Fn()->T + Send + Sync + 'a, T: Render + Send + Sync + 'a> From for ThunkBox<'a, E> { fn from (f: F) -> Self { Self(Default::default(), Box::new(move||f().boxed())) } } -//impl<'a, E: Output, F: Fn()->Box + 'a> + Send + Sync + 'a> From for BoxThunk<'a, E> { +//impl<'a, E: Output, F: Fn()->Box + 'a> + Send + Sync + 'a> From for ThunkBox<'a, E> { //fn from (f: F) -> Self { //Self(Default::default(), Box::new(f)) //} //} -pub struct RenderThunk(PhantomData, F); -impl RenderThunk { +pub struct ThunkRender(PhantomData, F); +impl ThunkRender { pub fn new (render: F) -> Self { Self(Default::default(), render) } } -impl Content for RenderThunk { +impl Content for ThunkRender { fn render (&self, to: &mut E) { (self.1)(to) } } -pub struct LayoutThunkE::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync>(PhantomData, F1, F2); -implE::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync> LayoutThunk { +pub struct ThunkLayoutE::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync>(PhantomData, F1, F2); +implE::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync> ThunkLayout { pub fn new (layout: F1, render: F2) -> Self { Self(Default::default(), layout, render) } } -implE::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync> Content for LayoutThunk { +implE::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync> Content for ThunkLayout { fn layout (&self, to: E::Area) -> E::Area { (self.1)(to) } fn render (&self, to: &mut E) { (self.2)(to) } } diff --git a/sampler/src/sampler.rs b/sampler/src/sampler.rs index 26578852..7d4e796c 100644 --- a/sampler/src/sampler.rs +++ b/sampler/src/sampler.rs @@ -884,7 +884,7 @@ impl Sampler { None }; let min_db = -40.0; - RenderThunk::new(move|to: &mut TuiOut|{ + ThunkRender::new(move|to: &mut TuiOut|{ let [x, y, width, height] = to.area(); let area = Rect { x, y, width, height }; let (x_bounds, y_bounds, lines): ([f64;2], [f64;2], Vec) = diff --git a/tek/src/lib.rs b/tek/src/lib.rs index 53fb06d1..de5840ac 100644 --- a/tek/src/lib.rs +++ b/tek/src/lib.rs @@ -487,7 +487,7 @@ impl Tek { scene.clips.remove(index); } } - fn clip_columns <'a> (&'a self) -> BoxThunk<'a, TuiOut> { + fn clip_columns <'a> (&'a self) -> ThunkBox<'a, TuiOut> { let editing = self.is_editing(); let tracks = move||self.tracks_sizes(editing, self.editor_w()); let scenes = move||self.scenes_sizes(editing, 2, 15); @@ -555,7 +555,7 @@ impl Tek { } Ok(()) } - fn input_header <'a> (&'a self) -> BoxThunk<'a, TuiOut> { + fn input_header <'a> (&'a self) -> ThunkBox<'a, TuiOut> { let fg = TuiTheme::g(224); let bg = TuiTheme::g(64); (move||Bsp::s(Fill::x(Align::w(self.button(" I ".to_string(), format!(" midi ins ({})", self.midi_ins().len())))), self.midi_ins().get(0).map(|inp|Bsp::s( @@ -564,7 +564,7 @@ impl Tek { Tui::fg_bg(fg, bg, connect.info()))))), ))).boxed()).into() } - fn output_header <'a> (&'a self) -> BoxThunk<'a, TuiOut> { + fn output_header <'a> (&'a self) -> ThunkBox<'a, TuiOut> { let fg = TuiTheme::g(224); let bg = TuiTheme::g(64); (move||Bsp::s(Fill::x(Align::w(self.button(" O ".to_string(), format!(" midi outs ({}) ", self.midi_outs().len())))), self.midi_outs().get(0).map(|out|Bsp::s( @@ -573,7 +573,7 @@ impl Tek { Tui::fg_bg(fg, bg, connect.info()))))), ))).boxed()).into() } - fn track_header <'a> (&'a self) -> BoxThunk<'a, TuiOut> { + fn track_header <'a> (&'a self) -> ThunkBox<'a, TuiOut> { let add_scene = ||self.button(" C-a ".to_string(), format!(" add scene ({}/{})", self.selected.scene().unwrap_or(0), self.scenes().len())); @@ -930,7 +930,7 @@ trait HasTracks: HasSelection + HasClock + HasJack + HasEditor + Send + Sync { fn track_mut (&mut self) -> Option<&mut Track> { self.selected().track().and_then(|s|self.tracks_mut().get_mut(s)) } - fn track_cells <'a> (&'a self) -> BoxThunk<'a, TuiOut> { + fn track_cells <'a> (&'a self) -> ThunkBox<'a, TuiOut> { let iter = ||self.tracks_sizes(self.is_editing(), self.editor_w()); (move||Align::x(Map::new(iter, move|(_, track, x1, x2), i| { let name = Push::x(1, &track.name); @@ -946,7 +946,7 @@ trait HasTracks: HasSelection + HasClock + HasJack + HasEditor + Send + Sync { )) })).boxed()).into() } - fn input_cells <'a> (&'a self) -> BoxThunk<'a, TuiOut> { + fn input_cells <'a> (&'a self) -> ThunkBox<'a, TuiOut> { (move||Align::x(Map::new(||self.tracks_sizes(self.is_editing(), self.editor_w()), move|(_, track, x1, x2), i| { let w = (x2 - x1) as u16; let color: ItemPalette = track.color.dark.into(); @@ -965,7 +965,7 @@ trait HasTracks: HasSelection + HasClock + HasJack + HasEditor + Send + Sync { Tui::fg_bg(if mon { Color::White } else { bg }, bg, "▌"), ) } - fn output_cells <'a> (&'a self) -> BoxThunk<'a, TuiOut> { + fn output_cells <'a> (&'a self) -> ThunkBox<'a, TuiOut> { (move||Align::x(Map::new(||self.tracks_sizes(self.is_editing(), self.editor_w()), move|(_, track, x1, x2), i| { let w = (x2 - x1) as u16; let color: ItemPalette = track.color.dark.into(); @@ -1103,7 +1103,7 @@ trait HasScenes: HasSelection + HasEditor + Send + Sync { fn scene_del (&mut self, index: usize) { self.selected().scene().and_then(|s|Some(self.scenes_mut().remove(index))); } - fn scene_header <'a> (&'a self) -> BoxThunk<'a, TuiOut> { + fn scene_header <'a> (&'a self) -> ThunkBox<'a, TuiOut> { (move||{ let last_color = Arc::new(RwLock::new(ItemPalette::from(Color::Rgb(0, 0, 0)))); let selected = self.selected().scene(); diff --git a/tui/examples/tui.rs b/tui/examples/tui.rs index 548f80d6..411647e0 100644 --- a/tui/examples/tui.rs +++ b/tui/examples/tui.rs @@ -11,8 +11,8 @@ fn main () -> Usually<()> { #[derive(Debug)] pub struct Example(usize, Measure); const KEYMAP: &str = "(:left prev) (:right next)"; handle!(TuiIn: |self: Example, input|{ - let keymap = KeyMap::new(KEYMAP)?; - let command = keymap.command::<_, ExampleCommand>(self, input); + let keymap = SourceIter::new(KEYMAP); + let command = keymap.command::<_, ExampleCommand, _>(self, input); if let Some(command) = command { command.execute(self)?; return Ok(Some(true)) @@ -46,22 +46,21 @@ const EXAMPLES: &'static [&'static str] = &[ include_str!("edn13.edn"), ]; view!(TuiOut: |self: Example|{ - let title = Tui::bg(Color::Rgb(60,10,10), - Push::y(1, Align::n(format!("Example {}/{} in {:?}", self.0 + 1, EXAMPLES.len(), &self.1.wh())))); - let code = Tui::bg(Color::Rgb(10,60,10), - Push::y(2, Align::n(format!("{}", EXAMPLES[self.0])))); - let content = Tui::bg(Color::Rgb(10,10,60), - AtomView::from_source(self, EXAMPLES[self.0])); + let index = self.0 + 1; + let wh = self.1.wh(); + let src = EXAMPLES[self.0]; + let heading = format!("Example {}/{} in {:?}", index, EXAMPLES.len(), &wh); + let title = Tui::bg(Color::Rgb(60, 10, 10), Push::y(1, Align::n(heading))); + let code = Tui::bg(Color::Rgb(10, 60, 10), Push::y(2, Align::n(format!("{}", src)))); + let content = Tui::bg(Color::Rgb(10, 10, 60), View(self, SourceIter::new(src))); self.1.of(Bsp::s(title, Bsp::n(""/*code*/, content))) }; { - bool {}; - u16 {}; - usize {}; - Box + 'a> { - ":title" => Tui::bg(Color::Rgb(60,10,10), Push::y(1, Align::n(format!("Example {}/{}:", self.0 + 1, EXAMPLES.len())))).boxed(), - ":code" => Tui::bg(Color::Rgb(10,60,10), Push::y(2, Align::n(format!("{}", EXAMPLES[self.0])))).boxed(), - ":hello" => Tui::bg(Color::Rgb(10, 100, 10), "Hello").boxed(), - ":world" => Tui::bg(Color::Rgb(100, 10, 10), "world").boxed(), - ":hello-world" => "Hello world!".boxed() - } + ":title" => Tui::bg(Color::Rgb(60, 10, 10), Push::y(1, Align::n(format!("Example {}/{}:", self.0 + 1, EXAMPLES.len())))).boxed(), + ":code" => Tui::bg(Color::Rgb(10, 60, 10), Push::y(2, Align::n(format!("{}", EXAMPLES[self.0])))).boxed(), + ":hello" => Tui::bg(Color::Rgb(10, 100, 10), "Hello").boxed(), + ":world" => Tui::bg(Color::Rgb(100, 10, 10), "world").boxed(), + ":hello-world" => "Hello world!".boxed() }); +provide_bool!(bool: |self: Example| {}); +provide_num!(u16: |self: Example| {}); +provide_num!(usize: |self: Example| {}); diff --git a/tui/src/lib.rs b/tui/src/lib.rs index 7e00ae59..43787759 100644 --- a/tui/src/lib.rs +++ b/tui/src/lib.rs @@ -1,11 +1,11 @@ -mod tui_buffer; pub use self::tui_buffer::*; -mod tui_color; pub use self::tui_color::*; +mod tui_buffer; pub use self::tui_buffer::*; +mod tui_color; pub use self::tui_color::*; mod tui_content; pub use self::tui_content::*; mod tui_engine; pub use self::tui_engine::*; -mod tui_file; pub use self::tui_file::*; +mod tui_file; pub use self::tui_file::*; mod tui_input; pub use self::tui_input::*; mod tui_output; pub use self::tui_output::*; -pub use ::tek_edn; pub(crate) use ::tek_edn::*; +pub use ::tek_edn;// pub(crate) use ::tek_edn::*; pub use ::tek_time; pub(crate) use ::tek_time::*; pub use ::tek_input; pub(crate) use tek_input::*; pub use ::tek_output; pub(crate) use tek_output::*;