From 8c54f8e426e947e89ca88b7e9b1b553ead29c656 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sun, 12 Jan 2025 16:12:26 +0100 Subject: [PATCH] wip: providing content chunks with ednprovider --- {input => edn}/src/edn_provide.rs | 8 + edn/src/lib.rs | 9 +- input/src/lib.rs | 1 - .../examples/midi-import.rs | 0 .../examples/demo.rs.old | 0 output/src/edn_view.rs | 137 ++++++++++++++++-- tek/src/lib.rs | 4 + tek/src/view.rs | 39 ++--- 8 files changed, 157 insertions(+), 41 deletions(-) rename {input => edn}/src/edn_provide.rs (76%) rename tek/examples/midi_import.rs.fixme => midi/examples/midi-import.rs (100%) rename tek/examples/demo.rs.fixme => output/examples/demo.rs.old (100%) diff --git a/input/src/edn_provide.rs b/edn/src/edn_provide.rs similarity index 76% rename from input/src/edn_provide.rs rename to edn/src/edn_provide.rs index cf4b6963..83ee1791 100644 --- a/input/src/edn_provide.rs +++ b/edn/src/edn_provide.rs @@ -3,6 +3,14 @@ use crate::*; /// Implement `EdnProvide` for a type and context #[macro_export] macro_rules! edn_provide { ($type:ty:|$self:ident:$State:ty|{ $($pat:pat => $expr:expr),* $(,)? }) => { + //impl EdnProvide<$type> for $State { + //fn get > (&$self, edn: &EdnItem) -> Option<$type> { + //Some(match edn.to_ref() { + //$(EdnItem::Sym($pat) => $expr),*, + //_ => return None + //}) + //} + //} impl EdnProvide<$type> for $State { fn get > (&$self, edn: &EdnItem) -> Option<$type> { Some(match edn.to_ref() { diff --git a/edn/src/lib.rs b/edn/src/lib.rs index 3b815d7d..1e9f10c0 100644 --- a/edn/src/lib.rs +++ b/edn/src/lib.rs @@ -3,10 +3,11 @@ pub(crate) use std::{fmt::{Debug, Formatter, Error as FormatError}}; -mod edn_error; pub use self::edn_error::*; -mod edn_item; pub use self::edn_item::*; -mod edn_iter; pub use self::edn_iter::*; -mod edn_token; pub use self::edn_token::*; +mod edn_error; pub use self::edn_error::*; +mod edn_item; pub use self::edn_item::*; +mod edn_iter; pub use self::edn_iter::*; +mod edn_token; pub use self::edn_token::*; +mod edn_provide; pub use self::edn_provide::*; #[cfg(test)] #[test] fn test_edn () -> Result<(), ParseError> { use EdnItem::*; diff --git a/input/src/lib.rs b/input/src/lib.rs index c9eabac0..c3749ebc 100644 --- a/input/src/lib.rs +++ b/input/src/lib.rs @@ -9,7 +9,6 @@ mod event_map; pub use self::event_map::*; mod edn_command; pub use self::edn_command::*; mod edn_input; pub use self::edn_input::*; mod edn_keymap; pub use self::edn_keymap::*; -mod edn_provide; pub use self::edn_provide::*; pub(crate) use ::tek_edn::EdnItem; /// Standard error trait. diff --git a/tek/examples/midi_import.rs.fixme b/midi/examples/midi-import.rs similarity index 100% rename from tek/examples/midi_import.rs.fixme rename to midi/examples/midi-import.rs diff --git a/tek/examples/demo.rs.fixme b/output/examples/demo.rs.old similarity index 100% rename from tek/examples/demo.rs.fixme rename to output/examples/demo.rs.old diff --git a/output/src/edn_view.rs b/output/src/edn_view.rs index cabc65eb..7f7e9fb1 100644 --- a/output/src/edn_view.rs +++ b/output/src/edn_view.rs @@ -1,28 +1,141 @@ use crate::*; use std::marker::PhantomData; use EdnItem::*; - pub type EdnCallback<'a, O, State> = dyn Fn(&'a State)-> RenderBox<'a, O> + Send + Sync + 'a; - pub type EdnRenderCallback<'a, O, State> = Box>; - /// Provides values to the template -pub trait EdnViewData { - fn get_bool (&self, _sym: EdnItem<&str>) -> bool { - panic!("no content") +pub trait EdnViewData: + EdnProvide + + EdnProvide + + EdnProvide + + EdnProvide>> +{ + fn get_bool (&self, item: EdnItem<&str>) -> bool { + match &item { + Num(0) => false, + Num(_) => true, + Sym(":true") | Sym(":t") => true, + Sym(":false") | Sym(":f") => false, + _ => EdnProvide::get_or_fail(self, &item) + } } - fn get_usize (&self, _sym: EdnItem<&str>) -> usize { - panic!("no content") + fn get_usize (&self, item: EdnItem<&str>) -> usize { + match &item { + Num(n) => *n, + _ => EdnProvide::get_or_fail(self, &item) + } } - fn get_content <'a> (&'a self, _sym: EdnItem<&'a str>) -> RenderBox<'a, E> { - panic!("no content") + fn get_unit (&self, item: EdnItem<&str>) -> E::Unit { + match &item { + Num(n) => (*n as u16).into(), + _ => EdnProvide::get_or_fail(self, &item) + } } - fn get_unit (&self, num: EdnItem<&str>) -> E::Unit { - if let EdnItem::Num(n) = num { (n as u16).into() } else { panic!("not a number") } + fn get_content <'a> (&'a self, item: EdnItem<&str>) -> Box + 'a> where E: 'a { + match item.to_ref() { + Nil => Box::new(()), + Exp(e) => if let [head, tail @ ..] = e.as_slice() { + match (head, tail) { + (Key("when"), [c, a]) => When( + self.get_bool(c.to_ref()), + self.get_content(a.to_ref())).boxed(), + (Key("either"),[c, a, b]) => Either( + self.get_bool(c.to_ref()), + self.get_content(a.to_ref()), + self.get_content(b.to_ref())).boxed(), + + (Key("align/c"), [a]) => Align::c( + self.get_content(a.to_ref())).boxed(), + (Key("align/x"), [a]) => Align::x( + self.get_content(a.to_ref())).boxed(), + (Key("align/y"), [a]) => Align::y( + self.get_content(a.to_ref())).boxed(), + (Key("align/n"), [a]) => Align::n( + self.get_content(a.to_ref())).boxed(), + (Key("align/s"), [a]) => Align::s( + self.get_content(a.to_ref())).boxed(), + (Key("align/e"), [a]) => Align::e( + self.get_content(a.to_ref())).boxed(), + (Key("align/w"), [a]) => Align::w( + self.get_content(a.to_ref())).boxed(), + (Key("align/nw"), [a]) => Align::nw( + self.get_content(a.to_ref())).boxed(), + (Key("align/ne"), [a]) => Align::ne( + self.get_content(a.to_ref())).boxed(), + (Key("align/sw"), [a]) => Align::sw( + self.get_content(a.to_ref())).boxed(), + (Key("align/se"), [a]) => Align::se( + self.get_content(a.to_ref())).boxed(), + + (Key("bsp/a"), [a, b]) => Bsp::a( + self.get_content(a.to_ref()), self.get_content(b.to_ref()),).boxed(), + (Key("bsp/b"), [a, b]) => Bsp::b( + self.get_content(a.to_ref()), self.get_content(b.to_ref()),).boxed(), + (Key("bsp/e"), [a, b]) => Bsp::e( + self.get_content(a.to_ref()), self.get_content(b.to_ref()),).boxed(), + (Key("bsp/n"), [a, b]) => Bsp::n( + self.get_content(a.to_ref()), self.get_content(b.to_ref()),).boxed(), + (Key("bsp/s"), [a, b]) => Bsp::s( + self.get_content(a.to_ref()), self.get_content(b.to_ref()),).boxed(), + (Key("bsp/w"), [a, b]) => Bsp::w( + self.get_content(a.to_ref()), self.get_content(b.to_ref()),).boxed(), + + (Key("fill/x"), [a]) => Fill::x( + self.get_content(a.to_ref())).boxed(), + (Key("fill/y"), [a]) => Fill::y( + self.get_content(a.to_ref())).boxed(), + (Key("fill/xy"), [a]) => Fill::xy( + self.get_content(a.to_ref())).boxed(), + + (Key("fixed/x"), [x, a]) => Fixed::x( + self.get_unit(x.to_ref()), self.get_content(a.to_ref())).boxed(), + (Key("fixed/y"), [y, a]) => Fixed::y( + self.get_unit(y.to_ref()), self.get_content(a.to_ref())).boxed(), + (Key("fixed/xy"), [x, y, a]) => Fixed::xy( + self.get_unit(x.to_ref()), self.get_unit(y.to_ref()), self.get_content(a.to_ref())).boxed(), + + (Key("max/x"), [x, a]) => Max::x( + self.get_unit(x.to_ref()), self.get_content(a.to_ref())).boxed(), + (Key("max/y"), [y, a]) => Max::y( + self.get_unit(y.to_ref()), self.get_content(a.to_ref())).boxed(), + + (Key("push/x"), [x, a]) => Push::x( + self.get_unit(x.to_ref()), self.get_content(a.to_ref())).boxed(), + (Key("push/y"), [y, a]) => Push::y( + self.get_unit(y.to_ref()), self.get_content(a.to_ref())).boxed(), + + (Key("pad/x"), [x, a]) => Padding::x( + self.get_unit(x.to_ref()), self.get_content(a.to_ref())).boxed(), + (Key("pad/y"), [y, a]) => Padding::y( + self.get_unit(y.to_ref()), self.get_content(a.to_ref())).boxed(), + (Key("pad/xy"), [x, y, a]) => Padding::xy( + self.get_unit(x.to_ref()), self.get_unit(y.to_ref()), self.get_content(a.to_ref())).boxed(), + + (Key("grow/x"), [x, a]) => Margin::x( + self.get_unit(x.to_ref()), self.get_content(a.to_ref())).boxed(), + (Key("grow/y"), [y, a]) => Margin::y( + self.get_unit(y.to_ref()), self.get_content(a.to_ref())).boxed(), + (Key("grow/xy"), [x, y, a]) => Margin::xy( + self.get_unit(x.to_ref()), self.get_unit(y.to_ref()), self.get_content(a.to_ref())).boxed(), + + _ => todo!("{:?} {:?}", &head, &tail) + } + } else { + panic!("invalid expression: {e:?}") + }, + _ => EdnProvide::get_or_fail(self, &item) + } + //panic!("no content") } } +impl EdnViewData for T where T: + EdnProvide + + EdnProvide + + EdnProvide + + EdnProvide>> +{} /// Renders from EDN source and context. #[derive(Default)] diff --git a/tek/src/lib.rs b/tek/src/lib.rs index c655817b..458dae2a 100644 --- a/tek/src/lib.rs +++ b/tek/src/lib.rs @@ -57,6 +57,10 @@ pub(crate) use std::time::Duration; pub(crate) use std::path::PathBuf; pub(crate) use std::ffi::OsString; +#[cfg(test)] fn test_tek () { + // TODO +} + //#[cfg(test)] mod test_focus { //use super::focus::*; //#[test] fn test_focus () { diff --git a/tek/src/view.rs b/tek/src/view.rs index c54837ec..9708f01e 100644 --- a/tek/src/view.rs +++ b/tek/src/view.rs @@ -1,31 +1,22 @@ use crate::*; render!(TuiOut: (self: App) => self.size.of(EdnView::from_source(self, self.edn.as_ref()))); -impl EdnViewData for &App { - fn get_content <'a> (&'a self, item: EdnItem<&'a str>) -> RenderBox<'a, TuiOut> { - use EdnItem::*; - let w = self.tracks_with_sizes().last().map(|x|x.3 as u16).unwrap_or(0); - match item { - Nil => Box::new(()), - Exp(items) => Box::new(EdnView::from_items(*self, items.as_slice())), - Sym(":editor") => (&self.editor).boxed(), - Sym(":inputs") => self.input_row(w, 3).boxed(), - Sym(":outputs") => self.output_row(w, 3).boxed(), - Sym(":pool") => self.pool().boxed(), - Sym(":sample") => self.sample().boxed(), - Sym(":sampler") => self.sampler().boxed(), - Sym(":scenes") => self.scene_row(w, self.size.h().saturating_sub(9) as u16).boxed(), - Sym(":status") => self.status(0).boxed(), - Sym(":toolbar") => self.toolbar().boxed(), - Sym(":tracks") => self.track_row(w, 3).boxed(), - _ => panic!("no content for {item:?}") - } - } - fn get_unit (&self, item: EdnItem<&str>) -> u16 { - EdnProvide::::get_or_fail(self, &item) - } -} +edn_provide!(Box>: |self: App|{ + ":editor" => (&self.editor).boxed(), + ":inputs" => self.input_row(self.w(), 3).boxed(), + ":outputs" => self.output_row(self.w(), 3).boxed(), + ":pool" => self.pool().boxed(), + ":sample" => self.sample().boxed(), + ":sampler" => self.sampler().boxed(), + ":scenes" => self.scene_row(self.w(), self.size.h().saturating_sub(9) as u16).boxed(), + ":status" => self.status(0).boxed(), + ":toolbar" => self.toolbar().boxed(), + ":tracks" => self.track_row(self.w(), 3).boxed(), +}); impl App { pub fn compact (&self) -> bool { false } + fn w (&self) -> u16 { + self.tracks_with_sizes().last().map(|x|x.3 as u16).unwrap_or(0) + } fn toolbar (&self) -> impl Content + use<'_> { Fill::x(Fixed::y(2, Align::x(ClockView::new(true, &self.clock)))) }