From 1b9da07280b3270c7638079d4c7c9ac12c05e51d Mon Sep 17 00:00:00 2001 From: unspeaker Date: Fri, 17 Jan 2025 18:49:04 +0100 Subject: [PATCH] wip: make EdnItem work on Arc --- edn/src/edn_error.rs | 8 +- edn/src/edn_item.rs | 208 +++++++++----------------------- edn/src/edn_iter.rs | 19 +-- edn/src/edn_provide.rs | 32 ++--- edn/src/lib.rs | 9 +- edn/src/try_from_edn.rs | 2 +- input/src/edn_input.rs | 20 ++- midi/src/midi_pool.rs | 2 +- output/src/align.rs | 2 +- output/src/direction.rs | 2 +- output/src/edn_view.rs | 88 +++++++------- output/src/either.rs | 2 +- output/src/transform_xy.rs | 2 +- output/src/transform_xy_unit.rs | 2 +- output/src/when.rs | 2 +- plugin/src/lib.rs | 10 +- tui/src/tui_input.rs | 2 +- 17 files changed, 152 insertions(+), 260 deletions(-) diff --git a/edn/src/edn_error.rs b/edn/src/edn_error.rs index 56028378..1bd18ec0 100644 --- a/edn/src/edn_error.rs +++ b/edn/src/edn_error.rs @@ -1,11 +1,9 @@ use crate::*; - -#[derive(Debug)] -pub enum ParseError { - Unknown(u8), +#[derive(Debug)] pub enum ParseError { Empty, Incomplete, Unexpected(char), + Code(u8), } impl std::fmt::Display for ParseError { fn fmt (&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -13,7 +11,7 @@ impl std::fmt::Display for ParseError { Self::Empty => write!(f, "empty"), Self::Incomplete => write!(f, "incomplete"), Self::Unexpected(c) => write!(f, "unexpected '{c}'"), - Self::Unknown(i) => write!(f, "unknown #{i}"), + Self::Code(i) => write!(f, "error #{i}"), } } } diff --git a/edn/src/edn_item.rs b/edn/src/edn_item.rs index 68f0100d..cdab9b25 100644 --- a/edn/src/edn_item.rs +++ b/edn/src/edn_item.rs @@ -1,31 +1,51 @@ use crate::*; - -pub enum EdnItem { - Nil, +use std::sync::Arc; +#[derive(Default, Clone, PartialEq)] pub enum EdnItem { + #[default] Nil, Num(usize), - Sym(T), - Key(T), - Exp(Vec>), + Sym(Arc), + Key(Arc), + Exp(Vec), } -impl Default for EdnItem { - fn default () -> Self { - Self::Nil - } -} -impl Display for EdnItem { - fn fmt (&self, f: &mut Formatter<'_>) -> Result<(), FormatError> { - use EdnItem::*; - use itertools::join; - match self { - Nil => write!(f, ""), - Num(u) => write!(f, "{u}"), - Sym(u) => write!(f, "{u}"), - Key(u) => write!(f, "{u}"), - Exp(e) => write!(f, "({})", join(e.iter().map(|i|format!("{}", i)), " ")) +impl EdnItem { + pub fn read_all (mut source: &str) -> Result, ParseError> { + let mut items = vec![]; + loop { + if source.len() == 0 { + break + } + let (remaining, token) = Token::chomp(source)?; + match Self::read(token)? { Self::Nil => {}, item => items.push(item) }; + source = remaining } + Ok(items) + } + pub fn read_one (source: &str) -> Result<(Self, &str), ParseError> { + Ok({ + if source.len() == 0 { + return Err(ParseError::Code(5)) + } + let (remaining, token) = Token::chomp(source)?; + (Self::read(token)?, remaining) + }) + } + pub fn read <'a> (token: Token<'a>) -> Result { + use Token::*; + Ok(match token { + Nil => EdnItem::Nil, + Num(chars, index, length) => + Self::Num(Token::number(&chars[index..index+length])), + Sym(chars, index, length) => + Self::Sym((&chars[index..index+length]).into()), + Key(chars, index, length) => + Self::Key((&chars[index..index+length]).into()), + Exp(chars, index, length, 0) => + Self::Exp(Self::read_all(&chars[index+1..(index+length).saturating_sub(1)])?), + _ => panic!("unclosed delimiter") + }) } } -impl Debug for EdnItem { +impl Debug for EdnItem { fn fmt (&self, f: &mut Formatter<'_>) -> Result<(), FormatError> { use EdnItem::*; match self { @@ -38,147 +58,31 @@ impl Debug for EdnItem { } } } -impl PartialEq for EdnItem { - fn eq (&self, other: &Self) -> bool { - use EdnItem::*; - match (self, other) { - (Nil, Nil) => true, - (Num(a), Num(b)) => a == b, - (Sym(a), Sym(b)) => a == b, - (Key(a), Key(b)) => a == b, - (Exp(a), Exp(b)) => a == b, - _ => false - } - } -} -impl EdnItem<&str> { - pub fn clone (&self) -> EdnItem { +impl Display for EdnItem { + fn fmt (&self, f: &mut Formatter<'_>) -> Result<(), FormatError> { use EdnItem::*; + use itertools::join; match self { - Nil => Nil, - Num(u) => Num(*u), - Sym(u) => Sym(u.to_string()), - Key(u) => Key(u.to_string()), - Exp(e) => Exp(e.iter().map(|i|i.clone()).collect()), + Nil => write!(f, ""), + Num(u) => write!(f, "{u}"), + Sym(u) => write!(f, "{u}"), + Key(u) => write!(f, "{u}"), + Exp(e) => write!(f, "({})", join(e.iter().map(|i|format!("{}", i)), " ")) } } } -impl> EdnItem { - pub fn to_ref (&self) -> EdnItem<&str> { - match self { - Self::Nil => EdnItem::Nil, - Self::Num(x) => EdnItem::Num(*x), - Self::Key(x) => EdnItem::Key(x.as_ref()), - Self::Sym(x) => EdnItem::Sym(x.as_ref()), - Self::Exp(x) => EdnItem::Exp(x.iter().map(|x|x.to_ref()).collect::>()), - } - } - pub fn to_str (&self) -> &str { - match self { - Self::Nil => "", - Self::Num(_) => "", - Self::Key(x) => x.as_ref(), - Self::Sym(x) => x.as_ref(), - Self::Exp(_) => "", - } - } - pub fn symbols <'a> (&'a self) -> EdnIterator<'a, T> { - EdnIterator::new(&self) - } -} -impl EdnItem { - pub fn from (other: EdnItem>) -> EdnItem { - use EdnItem::*; - match other { - Nil => Nil, - Key(t) => Key(t.as_ref().to_string()), - _ => todo!() - } - } -} -impl<'a> TryFrom> for EdnItem { +impl<'a> TryFrom> for EdnItem { type Error = ParseError; fn try_from (token: Token<'a>) -> Result { use Token::*; Ok(match token { Nil => Self::Nil, - Num(chars, index, length) => - Self::Num(Token::number(&chars[index..index+length])), - Sym(chars, index, length) => - Self::Sym(String::from(&chars[index..index+length])), - Key(chars, index, length) => - Self::Key(String::from(&chars[index..index+length])), - Exp(chars, index, length, 0) => - Self::Exp(Self::read_all(&chars[index+1..(index+length).saturating_sub(1)])?), + Num(chars, index, length) => Self::Num(Token::number(&chars[index..index+length])), + Sym(chars, index, length) => Self::Sym((&chars[index..index+length]).into()), + Key(chars, index, length) => Self::Key((&chars[index..index+length]).into()), + Exp(chars, index, length, 0) => Self::Exp(Self::read_all( + &chars[index+1..(index+length).saturating_sub(1)])?), _ => panic!("unclosed delimiter") }) } } - -impl<'a> TryFrom> for EdnItem<&'a str> { - type Error = ParseError; - fn try_from (token: Token<'a>) -> Result { - use Token::*; - Ok(match token { - Nil => EdnItem::Nil, - Num(chars, index, length) => - Self::Num(Token::number(&chars[index..index+length])), - Sym(chars, index, length) => - Self::Sym(&chars[index..index+length]), - Key(chars, index, length) => - Self::Key(&chars[index..index+length]), - Exp(chars, index, length, 0) => - Self::Exp(Self::read_all(&chars[index+1..(index+length).saturating_sub(1)])?), - _ => panic!("unclosed delimiter") - }) - } -} - -impl<'a, T: std::fmt::Debug + Clone + Default + PartialEq + From<&'a str>> EdnItem { - pub fn read_all (mut source: &'a str) -> Result, ParseError> { - let mut items = vec![]; - loop { - if source.len() == 0 { - break - } - let (remaining, token) = Token::chomp(source)?; - match Self::read(token)? { Self::Nil => {}, item => items.push(item) }; - source = remaining - } - Ok(items) - } - pub fn read_one (source: &'a str) -> Result<(Self, &'a str), ParseError> { - Ok({ - if source.len() == 0 { - return Err(ParseError::Unknown(5)) - } - let (remaining, token) = Token::chomp(source)?; - (Self::read(token)?, remaining) - }) - } - pub fn read (token: Token<'a>) -> Result { - use Token::*; - Ok(match token { - Nil => EdnItem::Nil, - Num(chars, index, length) => - Self::Num(Token::number(&chars[index..index+length])), - Sym(chars, index, length) => - Self::Sym(T::from(&chars[index..index+length])), - Key(chars, index, length) => - Self::Key(T::from(&chars[index..index+length])), - Exp(chars, index, length, 0) => - Self::Exp(Self::read_all(&chars[index+1..(index+length).saturating_sub(1)])?), - _ => panic!("unclosed delimiter") - }) - } - //pub fn to_str <'a> (&'a self) -> EdnItem<&'a str> { - //use EdnItem::*; - //match self { - //Nil => Nil, - //Num(n) => Num(*n), - //Sym(t) => Sym(t.as_str()), - //Key(t) => Key(t.as_str()), - //Exp(t) => Exp(t.iter().map(|x|x.to_str()).collect()) - //} - //} -} diff --git a/edn/src/edn_iter.rs b/edn/src/edn_iter.rs index 55409cb0..6ef3c025 100644 --- a/edn/src/edn_iter.rs +++ b/edn/src/edn_iter.rs @@ -1,28 +1,29 @@ use crate::*; -pub enum EdnIterator<'a, T>{ +use std::sync::Arc; +pub enum EdnIterator { Nil, - Sym(&'a T), - Exp(Vec>) + Sym(Arc), + Exp(Vec) } -impl<'a, T: AsRef> EdnIterator<'a, T> { - pub fn new (item: &'a EdnItem) -> Self { +impl EdnIterator { + pub fn new (item: &EdnItem) -> Self { use EdnItem::*; match item { - Sym(t) => Self::Sym(t), + Sym(t) => Self::Sym(t.clone()), Exp(i) => Self::Exp(i.iter().map(EdnIterator::new).collect()), _ => Self::Nil, } } } -impl<'a, T: AsRef> Iterator for EdnIterator<'a, T> { - type Item = &'a T; +impl Iterator for EdnIterator { + type Item = EdnItem; fn next (&mut self) -> Option { use EdnIterator::*; match self { Sym(t) => { let t = *t; *self = Nil; - Some(t) + Some(Sym(t)) }, Exp(v) => match v.as_mut_slice() { [a] => if let Some(next) = a.next() { diff --git a/edn/src/edn_provide.rs b/edn/src/edn_provide.rs index 8cd14c52..03703732 100644 --- a/edn/src/edn_provide.rs +++ b/edn/src/edn_provide.rs @@ -4,26 +4,26 @@ use crate::*; // Provide a value to the EDN template ($type:ty:|$self:ident:$State:ty|{ $($pat:pat => $expr:expr),* $(,)? }) => { impl<'a> EdnProvide<'a, $type> for $State { - fn get > (&'a $self, edn: &'a EdnItem) -> Option<$type> { - Some(match edn.to_ref() { $(EdnItem::Sym($pat) => $expr,)* _ => return None }) + fn get (&'a $self, edn: &'a EdnItem) -> Option<$type> { + Some(match EdnItem::<&str>::from(edn) { $(EdnItem::Sym($pat) => $expr,)* _ => return None }) } } }; // Provide a value more generically ($lt:lifetime: $type:ty:|$self:ident:$State:ty|{ $($pat:pat => $expr:expr),* $(,)? }) => { impl<$lt> EdnProvide<$lt, $type> for $State { - fn get > (&$lt $self, edn: &$lt EdnItem) -> Option<$type> { - Some(match edn.to_ref() { $(EdnItem::Sym($pat) => $expr,)* _ => return None }) + fn get (&$lt $self, edn: &$lt EdnItem) -> Option<$type> { + Some(match EdnItem::<&str>::from(edn) { $(EdnItem::Sym($pat) => $expr,)* _ => return None }) } } }; // Provide a value that may also be a numeric literal in the EDN, to a generic implementation. (# $type:ty:|$self:ident:<$T:ident:$Trait:path>|{ $($pat:pat => $expr:expr),* $(,)? }) => { impl<'a, $T: $Trait> EdnProvide<'a, $type> for $T { - fn get > (&'a $self, edn: &'a EdnItem) -> Option<$type> { - Some(match edn.to_ref() { + fn get (&'a $self, edn: &'a EdnItem) -> Option<$type> { + Some(match edn { $(EdnItem::Sym($pat) => $expr,)* - EdnItem::Num(n) => n as $type, + EdnItem::Num(n) => *n as $type, _ => return None }) } @@ -32,10 +32,10 @@ use crate::*; // Provide a value that may also be a numeric literal in the EDN, to a concrete implementation. (# $type:ty:|$self:ident:$State:ty|{ $($pat:pat => $expr:expr),* $(,)? }) => { impl<'a> EdnProvide<'a, $type> for $State { - fn get > (&'a $self, edn: &'a EdnItem) -> Option<$type> { - Some(match edn.to_ref() { + fn get (&'a $self, edn: &'a EdnItem) -> Option<$type> { + Some(match edn { $(EdnItem::Sym($pat) => $expr,)* - EdnItem::Num(n) => n as $type, + EdnItem::Num(n) => *n as $type, _ => return None }) } @@ -44,26 +44,26 @@ use crate::*; } /// Map EDN tokens to parameters of a given type for a given context pub trait EdnProvide<'a, U>: Sized { - fn get > (&'a self, _edn: &'a EdnItem) -> Option { + fn get (&'a self, _edn: &'a EdnItem) -> Option { None } - fn get_or_fail > (&'a self, edn: &'a EdnItem) -> U { + fn get_or_fail (&'a self, edn: &'a EdnItem) -> U { self.get(edn).expect("no value") } } impl<'a, T: EdnProvide<'a, U>, U> EdnProvide<'a, U> for &T { - fn get > (&'a self, edn: &'a EdnItem) -> Option { + fn get (&'a self, edn: &'a EdnItem) -> Option { (*self).get(edn) } - fn get_or_fail > (&'a self, edn: &'a EdnItem) -> U { + fn get_or_fail (&'a self, edn: &'a EdnItem) -> U { (*self).get_or_fail(edn) } } impl<'a, T: EdnProvide<'a, U>, U> EdnProvide<'a, U> for Option { - fn get > (&'a self, edn: &'a EdnItem) -> Option { + fn get (&'a self, edn: &'a EdnItem) -> Option { self.as_ref().map(|s|s.get(edn)).flatten() } - fn get_or_fail > (&'a self, edn: &'a EdnItem) -> U { + fn get_or_fail (&'a self, edn: &'a EdnItem) -> U { self.as_ref().map(|s|s.get_or_fail(edn)).expect("no provider") } } diff --git a/edn/src/lib.rs b/edn/src/lib.rs index a53b2f5c..5070596b 100644 --- a/edn/src/lib.rs +++ b/edn/src/lib.rs @@ -1,15 +1,12 @@ #![feature(type_alias_impl_trait)] #![feature(impl_trait_in_fn_trait_return)] - -pub(crate) use std::{fmt::{Debug, Display, 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_iter; pub use self::edn_iter::*; mod edn_token; pub use self::edn_token::*; mod edn_provide; pub use self::edn_provide::*; mod try_from_edn; pub use self::try_from_edn::*; - +pub(crate) use std::{fmt::{Debug, Display, Formatter, Error as FormatError}}; #[cfg(test)] #[test] fn test_edn () -> Result<(), ParseError> { use EdnItem::*; assert_eq!(EdnItem::::read_all("")?, @@ -30,7 +27,6 @@ mod try_from_edn; pub use self::try_from_edn::*; vec![Exp(vec![Key("foo/bar".into()), Sym(":baz".into()), Num(456)])]); Ok(()) } - #[cfg(test)] #[test] fn test_edn_layout () -> Result<(), ParseError> { EdnItem::::read_all(include_str!("../../output/examples/edn01.edn"))?; EdnItem::::read_all(include_str!("../../output/examples/edn02.edn"))?; @@ -38,7 +34,6 @@ mod try_from_edn; pub use self::try_from_edn::*; //let content = >::from(&layout); Ok(()) } - #[macro_export] macro_rules! from_edn { ($($x:tt)*) => {} } diff --git a/edn/src/try_from_edn.rs b/edn/src/try_from_edn.rs index 84bae227..23c64965 100644 --- a/edn/src/try_from_edn.rs +++ b/edn/src/try_from_edn.rs @@ -1,6 +1,6 @@ use crate::*; pub trait TryFromEdn<'a, T>: Sized { - fn try_from_edn (state: &'a T, head: &EdnItem<&str>, tail: &'a [EdnItem<&str>]) -> + fn try_from_edn (state: &'a T, head: &EdnItem, tail: &'a [EdnItem]) -> Option; } diff --git a/input/src/edn_input.rs b/input/src/edn_input.rs index 1ae78e6b..d5b58930 100644 --- a/input/src/edn_input.rs +++ b/input/src/edn_input.rs @@ -2,14 +2,14 @@ use crate::*; pub trait EdnInput: Input { fn matches_edn (&self, token: &str) -> bool; - fn get_event > (_: &EdnItem) -> Option { + fn get_event > (_: &EdnItem) -> Option { None } } /// Turns an EDN item sequence into a command enum variant. pub trait EdnCommand: Command { - fn from_edn <'a> (state: &C, head: &EdnItem<&str>, tail: &'a [EdnItem<&'a str>]) + fn from_edn <'a> (state: &C, head: &EdnItem, tail: &'a [EdnItem]) -> Option; } @@ -39,8 +39,8 @@ pub trait EdnCommand: Command { impl<$T: $Trait> EdnCommand<$T> for $Command { fn from_edn <'a> ( $state: &$T, - head: &EdnItem<&str>, - tail: &'a [EdnItem<&'a str>] + head: &EdnItem, + tail: &'a [EdnItem] ) -> Option { $(if let (EdnItem::Key($key), [ // if the identifier matches // bind argument ids @@ -81,9 +81,7 @@ pub trait EdnCommand: Command { ))* }) => { impl EdnCommand<$State> for $Command { fn from_edn <'a> ( - $state: &$State, - head: &EdnItem<&str>, - tail: &'a [EdnItem<&'a str>] + $state: &$State, head: &EdnItem, tail: &'a [EdnItem] ) -> Option { $(if let (EdnItem::Key($key), [ // if the identifier matches // bind argument ids @@ -109,11 +107,11 @@ pub trait EdnCommand: Command { }; } -pub struct EdnKeyMapToCommand<'a>(Vec>); -impl<'a> EdnKeyMapToCommand<'a> { +pub struct EdnKeyMapToCommand(Vec); +impl EdnKeyMapToCommand { /// Construct keymap from source text or fail - pub fn new (keymap: &'a str) -> Usually { - Ok(Self(EdnItem::<&str>::read_all(keymap)?)) + pub fn new (keymap: &str) -> Usually { + Ok(Self(EdnItem::read_all(keymap)?)) } /// Try to find a binding matching the currently pressed key pub fn from (&self, state: &T, input: &impl EdnInput) -> Option diff --git a/midi/src/midi_pool.rs b/midi/src/midi_pool.rs index 2fb73f39..0372575e 100644 --- a/midi/src/midi_pool.rs +++ b/midi/src/midi_pool.rs @@ -192,7 +192,7 @@ content!(TuiOut: |self: ClipLength| { impl PoolCommand { pub fn from_tui_event (state: &MidiPool, input: &impl EdnInput) -> Usually> { use EdnItem::*; - let edns: Vec> = EdnItem::read_all(match state.mode() { + let edns: Vec = EdnItem::read_all(match state.mode() { Some(PoolMode::Rename(..)) => KEYS_RENAME, Some(PoolMode::Length(..)) => KEYS_LENGTH, Some(PoolMode::Import(..)) | Some(PoolMode::Export(..)) => KEYS_FILE, diff --git a/output/src/align.rs b/output/src/align.rs index ecbd02d9..c56757e6 100644 --- a/output/src/align.rs +++ b/output/src/align.rs @@ -46,7 +46,7 @@ impl> Content for Align { } } impl<'a, E: Output + 'a, T: EdnViewData<'a, E>> TryFromEdn<'a, T> for Align> { - fn try_from_edn (state: &'a T, head: &EdnItem<&str>, tail: &'a [EdnItem<&str>]) -> Option { + fn try_from_edn (state: &'a T, head: &EdnItem, tail: &'a [EdnItem]) -> Option { use EdnItem::*; Some(match (head, tail) { (Key("align/c"), [a]) => Self::c(state.get_content(a).expect("no content")), diff --git a/output/src/direction.rs b/output/src/direction.rs index 710a3f8b..0cbff8a6 100644 --- a/output/src/direction.rs +++ b/output/src/direction.rs @@ -92,7 +92,7 @@ impl, B: Content> BspAreas for Bsp fn contents (&self) -> (&A, &B) { (&self.2, &self.3) } } impl<'a, E: Output + 'a, T: EdnViewData<'a, E>> TryFromEdn<'a, T> for Bsp, RenderBox<'a, E>> { - fn try_from_edn (s: &'a T, head: &EdnItem<&str>, tail: &'a [EdnItem<&str>]) -> Option { + fn try_from_edn (s: &'a T, head: &EdnItem, tail: &'a [EdnItem]) -> Option { use EdnItem::*; Some(match (head, tail) { (Key("bsp/n"), [a, b]) => Self::n( diff --git a/output/src/edn_view.rs b/output/src/edn_view.rs index 58ab2629..97c38e12 100644 --- a/output/src/edn_view.rs +++ b/output/src/edn_view.rs @@ -11,7 +11,7 @@ use EdnItem::*; } $( impl<'a> EdnProvide<'a, $type> for $App { - fn get > (&'a $self, edn: &'a EdnItem) -> Option<$type> { + fn get > (&'a $self, edn: &'a EdnItem) -> Option<$type> { Some(match edn.to_ref() { $(EdnItem::Sym($sym) => $value,)* _ => return None }) } } @@ -23,7 +23,7 @@ use EdnItem::*; #[macro_export] macro_rules! edn_provide_content { (|$self:ident:$State:ty|{ $($pat:pat => $expr:expr),* $(,)? }) => { impl<'a, E: Output> EdnProvide<'a, Box + 'a>> for $State { - fn get > (&'a $self, edn: &'a EdnItem) -> Option + 'a>> { + fn get > (&'a $self, edn: &'a EdnItem) -> Option + 'a>> { Some(match edn.to_ref() { $(EdnItem::Sym($pat) => $expr),*, _ => return None @@ -33,7 +33,7 @@ use EdnItem::*; }; ($Output:ty: |$self:ident:$State:ty|{ $($pat:pat => $expr:expr),* $(,)? }) => { impl<'a> EdnProvide<'a, Box + 'a>> for $State { - fn get > (&'a $self, edn: &'a EdnItem) -> Option + 'a>> { + fn get > (&'a $self, edn: &'a EdnItem) -> Option + 'a>> { Some(match edn.to_ref() { $(EdnItem::Sym($pat) => $expr),*, _ => return None @@ -45,7 +45,7 @@ use EdnItem::*; /// Renders from EDN source and context. #[derive(Default)] pub enum EdnView<'a, E: Output, T: EdnViewData<'a, E> + std::fmt::Debug> { #[default] Inert, - Ok(T, EdnItem<&'a str>), + Ok(T, EdnItem), //render: BoxBox + Send + Sync + 'a> + Send + Sync + 'a> Err(String), _Unused(PhantomData<&'a E>), @@ -76,7 +76,7 @@ impl<'a, E: Output, T: EdnViewData<'a, E> + std::fmt::Debug> EdnView<'a, E, T> { Err(error) => Self::Err(format!("{error} in {source}")) } } - pub fn from_items (state: T, items: Vec>) -> Self { + pub fn from_items (state: T, items: Vec) -> Self { Self::Ok(state, EdnItem::Exp(items)) } } @@ -92,6 +92,17 @@ implEdnViewData<'a, E> + Send + Sync + std::fmt::Debug> Co } } } + +macro_rules! edn_try_delegate { + ($s:ident, $e:expr, $T:ty) => { + if let [head, tail @ ..] = $e.as_slice() { + if let Some(content) = <$T>::try_from_edn($s, head, tail) { + return Some(content.boxed()) + } + } + } +} + /// Provides values to the template pub trait EdnViewData<'a, E: Output>: EdnProvide<'a, bool> + @@ -99,55 +110,42 @@ pub trait EdnViewData<'a, E: Output>: EdnProvide<'a, E::Unit> + EdnProvide<'a, Box + 'a>> { - fn get_bool (&'a self, item: &'a EdnItem<&str>) -> Option { + fn get_bool (&'a self, item: &'a EdnItem) -> Option { Some(match &item { - Sym(":false") | Sym(":f") | Num(0) => false, - Sym(":true") | Sym(":t") | Num(_) => true, + Sym(s) => match s.as_ref() { + ":false" | ":f" => false, + ":true" | ":t" => true, + _ => return EdnProvide::get(self, item) + }, + Num(0) => false, + Num(_) => true, _ => return EdnProvide::get(self, item) }) } - fn get_usize (&'a self, item: &'a EdnItem<&str>) -> Option { + fn get_usize (&'a self, item: &'a EdnItem) -> Option { Some(match &item { Num(n) => *n, _ => return EdnProvide::get(self, item) }) } - fn get_unit (&'a self, item: &'a EdnItem<&str>) -> Option { + fn get_unit (&'a self, item: &'a EdnItem) -> Option { Some(match &item { Num(n) => (*n as u16).into(), _ => return EdnProvide::get(self, item) }) } - fn get_content (&'a self, item: &'a EdnItem<&'a str>) -> Option + 'a>> where E: 'a { + fn get_content (&'a self, item: &'a EdnItem) -> Option + 'a>> where E: 'a { Some(match item { - Nil => Box::new(()), - Exp(e) => if let [head, tail @ ..] = e.as_slice() { - if let Some(builtin) = When::<_, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else if let Some(builtin) = Either::<_, RenderBox<'a, E>, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else if let Some(builtin) = Align::<_, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else if let Some(builtin) = Bsp::<_, RenderBox<'a, E>, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else if let Some(builtin) = Fill::<_, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else if let Some(builtin) = Fixed::<_, _, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else if let Some(builtin) = Min::<_, _, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else if let Some(builtin) = Max::<_, _, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else if let Some(builtin) = Shrink::<_, _, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else if let Some(builtin) = Expand::<_, _, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else if let Some(builtin) = Push::<_, _, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else if let Some(builtin) = Pull::<_, _, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else if let Some(builtin) = Margin::<_, _, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else if let Some(builtin) = Padding::<_, _, RenderBox<'a, E>>::try_from_edn(self, head, tail) { - builtin.boxed() - } else { - EdnProvide::get_or_fail(self, &item) - } - } else { + Nil => Box::new(()), + Exp(ref e) => { + edn_try_delegate!(self, e, When::<_, RenderBox<'a, E>>); + edn_try_delegate!(self, e, Either::<_, RenderBox<'a, E>, RenderBox<'a, E>>); + edn_try_delegate!(self, e, Align::<_, RenderBox<'a, E>>); + edn_try_delegate!(self, e, Bsp::<_, RenderBox<'a, E>, RenderBox<'a, E>>); + edn_try_delegate!(self, e, Fill::<_, RenderBox<'a, E>>); + edn_try_delegate!(self, e, Fixed::<_, _, RenderBox<'a, E>>); + edn_try_delegate!(self, e, Min::<_, _, RenderBox<'a, E>>); + edn_try_delegate!(self, e, Max::<_, _, RenderBox<'a, E>>); + edn_try_delegate!(self, e, Shrink::<_, _, RenderBox<'a, E>>); + edn_try_delegate!(self, e, Expand::<_, _, RenderBox<'a, E>>); + edn_try_delegate!(self, e, Push::<_, _, RenderBox<'a, E>>); + edn_try_delegate!(self, e, Pull::<_, _, RenderBox<'a, E>>); + edn_try_delegate!(self, e, Margin::<_, _, RenderBox<'a, E>>); + edn_try_delegate!(self, e, Padding::<_, _, RenderBox<'a, E>>); EdnProvide::get_or_fail(self, &item) }, _ => EdnProvide::get_or_fail(self, &item) diff --git a/output/src/either.rs b/output/src/either.rs index 99ed273e..a104669c 100644 --- a/output/src/either.rs +++ b/output/src/either.rs @@ -7,7 +7,7 @@ impl Either { } } impl<'a, E: Output + 'a, T: EdnViewData<'a, E>> TryFromEdn<'a, T> for Either, RenderBox<'a, E>> { - fn try_from_edn (state: &'a T, head: &EdnItem<&str>, tail: &'a [EdnItem<&str>]) -> Option { + fn try_from_edn (state: &'a T, head: &EdnItem, tail: &'a [EdnItem]) -> Option { use EdnItem::*; if let (Key("either"), [condition, content, alternative]) = (head, tail) { Some(Self::new( diff --git a/output/src/transform_xy.rs b/output/src/transform_xy.rs index 351ecb5c..697fbfb6 100644 --- a/output/src/transform_xy.rs +++ b/output/src/transform_xy.rs @@ -29,7 +29,7 @@ macro_rules! transform_xy { } impl<'a, E: Output + 'a, T: EdnViewData<'a, E>> TryFromEdn<'a, T> for $Enum> { fn try_from_edn ( - state: &'a T, head: &EdnItem<&str>, tail: &'a [EdnItem<&str>] + state: &'a T, head: &EdnItem, tail: &'a [EdnItem] ) -> Option { use EdnItem::*; Some(match (head, tail) { diff --git a/output/src/transform_xy_unit.rs b/output/src/transform_xy_unit.rs index 486939be..30209da6 100644 --- a/output/src/transform_xy_unit.rs +++ b/output/src/transform_xy_unit.rs @@ -43,7 +43,7 @@ macro_rules! transform_xy_unit { } impl<'a, E: Output + 'a, T: EdnViewData<'a, E>> TryFromEdn<'a, T> for $Enum> { fn try_from_edn ( - state: &'a T, head: &EdnItem<&str>, tail: &'a [EdnItem<&str>] + state: &'a T, head: &EdnItem, tail: &'a [EdnItem] ) -> Option { use EdnItem::*; Some(match (head, tail) { diff --git a/output/src/when.rs b/output/src/when.rs index 8971b107..14649421 100644 --- a/output/src/when.rs +++ b/output/src/when.rs @@ -8,7 +8,7 @@ impl When { } impl<'a, E: Output + 'a, T: EdnViewData<'a, E>> TryFromEdn<'a, T> for When> { fn try_from_edn ( - state: &'a T, head: &EdnItem<&str>, tail: &'a [EdnItem<&str>] + state: &'a T, head: &EdnItem, tail: &'a [EdnItem] ) -> Option { use EdnItem::*; if let (Key("when"), [condition, content]) = (head, tail) { diff --git a/plugin/src/lib.rs b/plugin/src/lib.rs index 26249c1b..6da6ed8b 100644 --- a/plugin/src/lib.rs +++ b/plugin/src/lib.rs @@ -1,6 +1,9 @@ mod plugin; pub use self::plugin::*; mod lv2; pub use self::lv2::*; - +pub(crate) use std::cmp::Ord; +pub(crate) use std::fmt::{Debug, Formatter}; +pub(crate) use std::sync::{Arc, RwLock}; +pub(crate) use std::thread::JoinHandle; pub(crate) use ::tek_jack::{*, jack::*}; pub(crate) use ::tek_tui::{ *, @@ -10,8 +13,3 @@ pub(crate) use ::tek_tui::{ ratatui::prelude::*, crossterm::event::*, }; - -pub(crate) use std::cmp::Ord; -pub(crate) use std::fmt::{Debug, Formatter}; -pub(crate) use std::sync::{Arc, RwLock}; -pub(crate) use std::thread::JoinHandle; diff --git a/tui/src/tui_input.rs b/tui/src/tui_input.rs index 31f55408..10ae3705 100644 --- a/tui/src/tui_input.rs +++ b/tui/src/tui_input.rs @@ -54,7 +54,7 @@ impl EdnInput for TuiIn { false } } - fn get_event > (item: &EdnItem) -> Option { + fn get_event (item: &EdnItem) -> Option { match item { EdnItem::Sym(s) => KeyMatcher::new(s).build(), _ => None } } }