document stuff; Thunk suffix -> prefix

This commit is contained in:
🪞👃🪞 2025-01-19 21:31:16 +01:00
parent f9f9051eb7
commit 9d250daa04
16 changed files with 162 additions and 125 deletions

View file

@ -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()

View file

@ -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)}}

View file

@ -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 = <dyn ViewContext<::tek_engine::tui::Tui>>::from(&layout);
//#[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 = <dyn ViewContext<::tek_engine::tui::Tui>>::from(&layout);
////}
//Ok(())
//}
Ok(())
}

View file

@ -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> {

View file

@ -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<C>> AtomCommand<'a, C> for T {}
//}
//}
#[cfg(test)] #[test] fn test_atom_keymap () -> Usually<()> {
let keymap = KeyMap::new("")?;
let keymap = SourceIter::new("");
Ok(())
}

View file

@ -1,16 +1,14 @@
mod midi_clip; pub use midi_clip::*;
mod midi_launch; pub use midi_launch::*;
mod midi_player; pub use midi_player::*;
mod midi_in; pub use midi_in::*;
mod midi_out; pub use midi_out::*;
mod midi_pitch; pub use midi_pitch::*;
mod midi_range; pub use midi_range::*;
mod midi_point; pub use midi_point::*;
mod midi_view; pub use midi_view::*;
mod midi_pool; pub use midi_pool::*;
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_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 piano_h; pub use self::piano_h::*;
pub(crate) use ::tek_time::*;
@ -20,7 +18,6 @@ pub(crate) use ::tek_tui::{
tek_input::*,
tek_output::*,
tek_edn::*,
crossterm::event::*,
ratatui::style::{Style, Stylize, Color}
};

View file

@ -1,5 +1,4 @@
use crate::*;
use Value::*;
pub trait HasEditor {
fn editor (&self) -> &Option<MidiEditor>;
fn editor_mut (&mut self) -> &Option<MidiEditor>;

View file

@ -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<TuiOut> + '_ {
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);

View file

@ -49,37 +49,5 @@ pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
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<TuiOut>, 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::<TuiOut, _, _>::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::<TuiOut, _, _>::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(())
}

View file

@ -1,3 +1,24 @@
//! Aligns things to the container. Comes with caveats.
//! ```
//! let four = ||Fixed::<TuiOut, _, _>::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::<TuiOut, _, _>::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<A>(Alignment, A);

View file

@ -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<TuiOut>, 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.

View file

@ -12,39 +12,39 @@ impl<E: Output, T: Render<E>, F: Fn()->T + Send + Sync> Content<E> for Thunk<E,
fn content (&self) -> impl Render<E> { (self.1)() }
}
pub struct BoxThunk<'a, E: Output>(PhantomData<E>, Box<dyn Fn()->Box<dyn Render<E> + 'a> + Send + Sync + 'a>);
impl<'a, E: Output> BoxThunk<'a, E> {
pub struct ThunkBox<'a, E: Output>(PhantomData<E>, Box<dyn Fn()->Box<dyn Render<E> + 'a> + Send + Sync + 'a>);
impl<'a, E: Output> ThunkBox<'a, E> {
pub fn new (thunk: Box<dyn Fn()->Box<dyn Render<E> + 'a> + Send + Sync + 'a>) -> Self {
Self(Default::default(), thunk)
}
}
impl<'a, E: Output> Content<E> for BoxThunk<'a, E> {
impl<'a, E: Output> Content<E> for ThunkBox<'a, E> {
fn content (&self) -> impl Render<E> { (self.1)() }
}
impl<'a, E: Output, F: Fn()->T + Send + Sync + 'a, T: Render<E> + Send + Sync + 'a> From<F> for BoxThunk<'a, E> {
impl<'a, E: Output, F: Fn()->T + Send + Sync + 'a, T: Render<E> + Send + Sync + 'a> From<F> for ThunkBox<'a, E> {
fn from (f: F) -> Self {
Self(Default::default(), Box::new(move||f().boxed()))
}
}
//impl<'a, E: Output, F: Fn()->Box<dyn Render<E> + 'a> + Send + Sync + 'a> From<F> for BoxThunk<'a, E> {
//impl<'a, E: Output, F: Fn()->Box<dyn Render<E> + 'a> + Send + Sync + 'a> From<F> for ThunkBox<'a, E> {
//fn from (f: F) -> Self {
//Self(Default::default(), Box::new(f))
//}
//}
pub struct RenderThunk<E: Output, F: Fn(&mut E) + Send + Sync>(PhantomData<E>, F);
impl<E: Output, F: Fn(&mut E) + Send + Sync> RenderThunk<E, F> {
pub struct ThunkRender<E: Output, F: Fn(&mut E) + Send + Sync>(PhantomData<E>, F);
impl<E: Output, F: Fn(&mut E) + Send + Sync> ThunkRender<E, F> {
pub fn new (render: F) -> Self { Self(Default::default(), render) }
}
impl<E: Output, F: Fn(&mut E) + Send + Sync> Content<E> for RenderThunk<E, F> {
impl<E: Output, F: Fn(&mut E) + Send + Sync> Content<E> for ThunkRender<E, F> {
fn render (&self, to: &mut E) { (self.1)(to) }
}
pub struct LayoutThunk<E: Output, F1: Fn(E::Area)->E::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync>(PhantomData<E>, F1, F2);
impl<E: Output, F1: Fn(E::Area)->E::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync> LayoutThunk<E, F1, F2> {
pub struct ThunkLayout<E: Output, F1: Fn(E::Area)->E::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync>(PhantomData<E>, F1, F2);
impl<E: Output, F1: Fn(E::Area)->E::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync> ThunkLayout<E, F1, F2> {
pub fn new (layout: F1, render: F2) -> Self { Self(Default::default(), layout, render) }
}
impl<E: Output, F1: Fn(E::Area)->E::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync> Content<E> for LayoutThunk<E, F1, F2> {
impl<E: Output, F1: Fn(E::Area)->E::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync> Content<E> for ThunkLayout<E, F1, F2> {
fn layout (&self, to: E::Area) -> E::Area { (self.1)(to) }
fn render (&self, to: &mut E) { (self.2)(to) }
}

View file

@ -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<Line>) =

View file

@ -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();

View file

@ -11,8 +11,8 @@ fn main () -> Usually<()> {
#[derive(Debug)] pub struct Example(usize, Measure<TuiOut>);
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<dyn Render<TuiOut> + '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()
}
});
provide_bool!(bool: |self: Example| {});
provide_num!(u16: |self: Example| {});
provide_num!(usize: |self: Example| {});

View file

@ -5,7 +5,7 @@ mod tui_engine; pub use self::tui_engine::*;
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::*;