diff --git a/edn/src/context.rs b/edn/src/context.rs index 2fde0cba..2a8aa2ca 100644 --- a/edn/src/context.rs +++ b/edn/src/context.rs @@ -1,12 +1,10 @@ use crate::*; pub trait TryFromAtom<'a, T>: Sized { + fn try_from_expr (_state: &'a T, _iter: TokenIter<'a>) -> Option { None } fn try_from_atom (state: &'a T, value: Value<'a>) -> Option { if let Exp(0, iter) = value { return Self::try_from_expr(state, iter) } None } - fn try_from_expr (_state: &'a T, _iter: TokenIter<'a>) -> Option { - None - } } pub trait TryIntoAtom: Sized { fn try_into_atom (&self) -> Option; diff --git a/edn/src/iter.rs b/edn/src/iter.rs index 4b69d6a1..90792174 100644 --- a/edn/src/iter.rs +++ b/edn/src/iter.rs @@ -1,8 +1,19 @@ use crate::*; -#[derive(Copy, Clone, Debug, Default, PartialEq)] pub struct TokenIter<'a>(pub &'a str); -const_iter!(<'a>|self: TokenIter<'a>| => Token<'a> => self.next_mut().map(|(result, _)|result)); -impl<'a> From<&'a str> for TokenIter<'a> {fn from (source: &'a str) -> Self{Self::new(source)}} +#[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)) } + pub const fn peek (&self) -> Option> { self.0.peek() } +} +impl<'a> Iterator for TokenIter<'a> { + type Item = Token<'a>; + fn next (&mut self) -> Option> { + self.0.next().map(|(item, rest)|{self.0 = rest; item}) + } +} +#[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)}} +impl<'a> SourceIter<'a> { pub const fn new (source: &'a str) -> Self { Self(source) } pub const fn chomp (&self, index: usize) -> Self { Self(split_at(self.0, index).1) } pub const fn next (mut self) -> Option<(Token<'a>, Self)> { Self::next_mut(&mut self) } @@ -22,7 +33,7 @@ pub const fn peek_src <'a> (source: &'a str) -> Option> { ' '|'\n'|'\r'|'\t' => token.grow(), '(' => - Token::new(source, start, 1, Exp(1, TokenIter(str_range(source, start, start + 1)))), + Token::new(source, start, 1, Exp(1, TokenIter::new(str_range(source, start, start + 1)))), ':'|'@' => Token::new(source, start, 1, Sym(str_range(source, start, start + 1))), '/'|'a'..='z' => diff --git a/edn/src/lib.rs b/edn/src/lib.rs index 0e6880cd..4469bf53 100644 --- a/edn/src/lib.rs +++ b/edn/src/lib.rs @@ -53,37 +53,37 @@ pub(crate) use std::fmt::{Debug, Display, Formatter, Result as FormatResult, Err assert_eq!(token, Token { source, start: 0, length: 4, value: Sym(":f00") }); let src = ""; - assert_eq!(None, TokenIter(src).next()); + assert_eq!(None, SourceIter(src).next()); let src = " \n \r \t "; - assert_eq!(None, TokenIter(src).next()); + assert_eq!(None, SourceIter(src).next()); let src = "7"; - assert_eq!(Num(7), TokenIter(src).next().unwrap().0.value); + assert_eq!(Num(7), SourceIter(src).next().unwrap().0.value); let src = " 100 "; - assert_eq!(Num(100), TokenIter(src).next().unwrap().0.value); + assert_eq!(Num(100), SourceIter(src).next().unwrap().0.value); let src = " 9a "; - assert_eq!(Err(Unexpected('a')), TokenIter(src).next().unwrap().0.value); + assert_eq!(Err(Unexpected('a')), SourceIter(src).next().unwrap().0.value); let src = " :123foo "; - assert_eq!(Sym(":123foo"), TokenIter(src).next().unwrap().0.value); + assert_eq!(Sym(":123foo"), SourceIter(src).next().unwrap().0.value); let src = " \r\r\r\n\n\n@bar456\t\t\t\t\t\t"; - assert_eq!(Sym("@bar456"), TokenIter(src).next().unwrap().0.value); + assert_eq!(Sym("@bar456"), SourceIter(src).next().unwrap().0.value); let src = "foo123"; - assert_eq!(Key("foo123"), TokenIter(src).next().unwrap().0.value); + assert_eq!(Key("foo123"), SourceIter(src).next().unwrap().0.value); let src = "foo/bar"; - assert_eq!(Key("foo/bar"), TokenIter(src).next().unwrap().0.value); + assert_eq!(Key("foo/bar"), SourceIter(src).next().unwrap().0.value); Ok(()) } #[cfg(test)] #[test] fn test_examples () -> Result<(), ParseError> { let src = include_str!("../../tek/src/view_arranger.edn"); - let mut view = TokenIter(src); + let mut view = SourceIter(src); assert_eq!(view.0, src); let mut expr = view.peek(); assert_eq!(view.0, src); @@ -91,7 +91,7 @@ pub(crate) use std::fmt::{Debug, Display, Formatter, Result as FormatResult, Err source: src, start: 0, length: src.len(), - value: Exp(0, TokenIter(&src[1..])) + value: Exp(0, SourceIter(&src[1..])) })); //panic!("{view:?}"); //panic!("{:#?}", expr); diff --git a/edn/src/token.rs b/edn/src/token.rs index d3ee2bba..0b041ea7 100644 --- a/edn/src/token.rs +++ b/edn/src/token.rs @@ -59,7 +59,7 @@ impl<'a> Token<'a> { pub const fn grow_exp (self) -> Self { let mut token = self.grow(); if let Exp(depth, _) = token.value { - token.value = Exp(depth, TokenIter(token.slice_source_exp(self.source))); + token.value = Exp(depth, TokenIter::new(token.slice_source_exp(self.source))); } else { unreachable!() } diff --git a/input/src/keymap.rs b/input/src/keymap.rs index e9695c29..28024894 100644 --- a/input/src/keymap.rs +++ b/input/src/keymap.rs @@ -8,19 +8,46 @@ pub trait KeyMap<'a> { fn command , I: AtomInput> (&'a self, state: &'a S, input: &'a I) -> Option; } +impl<'a> KeyMap<'a> for SourceIter<'a> { + fn command , I: AtomInput> (&'a self, state: &'a S, input: &'a I) + -> Option + { + let mut iter = self.clone(); + while let Some((token, rest)) = iter.next() { + iter = rest; + match token { + Token { value: Value::Exp(0, exp_iter), .. } => { + let mut exp_iter = exp_iter.clone(); + match exp_iter.next() { + Some(Token { value: Value::Sym(binding), .. }) => { + if input.matches_atom(binding) { + if let Some(command) = C::try_from_expr(state, exp_iter.clone()) { + return Some(command) + } + } + }, + _ => panic!("invalid config (expected symbol)") + } + }, + _ => panic!("invalid config (expected expression)") + } + } + None + } +} impl<'a> KeyMap<'a> for TokenIter<'a> { fn command , I: AtomInput> (&'a self, state: &'a S, input: &'a I) -> Option { - let iter = self.clone(); + let mut iter = self.clone(); while let Some(next) = iter.next() { match next { - (Token { value: Value::Exp(0, iter), .. }, _) => { - let next = iter.next(); - match next { - Some((Token { value: Value::Sym(binding), .. }, _)) => { + Token { value: Value::Exp(0, exp_iter), .. } => { + let mut exp_iter = exp_iter.clone(); + match exp_iter.next() { + Some(Token { value: Value::Sym(binding), .. }) => { if input.matches_atom(binding) { - if let Some(command) = C::try_from_expr(state, iter.clone()) { + if let Some(command) = C::try_from_expr(state, exp_iter.clone()) { return Some(command) } } @@ -62,13 +89,14 @@ impl<'a, C, T: TryFromAtom<'a, C> + Command> AtomCommand<'a, C> for T {} ))* }) => { impl<'a, $State: $Trait> TryFromAtom<'a, $State> for $Command { fn try_from_expr ($state: &$State, iter: TokenIter) -> Option { - match $iter.next() { - $(Some((Token { value: Value::Key($key), .. }, _)) => { + let iter = iter.clone(); + match iter.next() { + $(Some(Token { value: Value::Key($key), .. }) => { let iter = iter.clone(); $( let next = iter.next(); if next.is_none() { panic!("no argument: {}", stringify!($arg)); } - let ($arg, _) = next.unwrap(); + let $arg = next.unwrap(); $(let $arg: Option<$type> = Context::<$type>::get($state, &$arg.value);)? )* $(let $rest = iter.clone();)? @@ -103,13 +131,14 @@ impl<'a, C, T: TryFromAtom<'a, C> + Command> AtomCommand<'a, C> for T {} ))* }) => { impl<'a> TryFromAtom<'a, $State> for $Command { fn try_from_expr ($state: &$State, iter: TokenIter) -> Option { + let mut iter = iter.clone(); match iter.next() { - $(Some((Token { value: Value::Key($key), .. }, _)) => { - let iter = iter.clone(); + $(Some(Token { value: Value::Key($key), .. }) => { + let mut iter = iter.clone(); $( let next = iter.next(); if next.is_none() { panic!("no argument: {}", stringify!($arg)); } - let ($arg, _) = next.unwrap(); + let $arg = next.unwrap(); $(let $arg: Option<$type> = Context::<$type>::get($state, &$arg.value);)? )* $(let $rest = iter.clone();)? diff --git a/midi/src/midi_edit.rs b/midi/src/midi_edit.rs index cfb20ace..e829bdd2 100644 --- a/midi/src/midi_edit.rs +++ b/midi/src/midi_edit.rs @@ -32,7 +32,7 @@ pub trait HasEditor { pub struct MidiEditor { pub mode: PianoHorizontal, pub size: Measure, - keys: TokenIter<'static> + keys: SourceIter<'static> } has_size!(|self: MidiEditor|&self.size); content!(TuiOut: |self: MidiEditor| { @@ -92,7 +92,7 @@ impl Default for MidiEditor { Self { mode: PianoHorizontal::new(None), size: Measure::new(), - keys: TokenIter(KEYS_EDIT), + keys: SourceIter(KEYS_EDIT), } } } diff --git a/midi/src/midi_pool.rs b/midi/src/midi_pool.rs index c9b6a33f..db7edbd2 100644 --- a/midi/src/midi_pool.rs +++ b/midi/src/midi_pool.rs @@ -31,10 +31,10 @@ pub struct MidiPool { /// Mode switch pub mode: Option, - keys: TokenIter<'static>, - keys_rename: TokenIter<'static>, - keys_length: TokenIter<'static>, - keys_file: TokenIter<'static>, + keys: SourceIter<'static>, + keys_rename: SourceIter<'static>, + keys_length: SourceIter<'static>, + keys_file: SourceIter<'static>, } /// Modes for clip pool #[derive(Debug, Clone)] @@ -55,10 +55,10 @@ impl Default for MidiPool { clips: Arc::from(RwLock::from(vec![])), clip: 0.into(), mode: None, - keys: TokenIter(KEYS_POOL), - keys_rename: TokenIter(KEYS_RENAME), - keys_length: TokenIter(KEYS_LENGTH), - keys_file: TokenIter(KEYS_FILE), + keys: SourceIter(KEYS_POOL), + keys_rename: SourceIter(KEYS_RENAME), + keys_length: SourceIter(KEYS_LENGTH), + keys_file: SourceIter(KEYS_FILE), } } } diff --git a/output/src/op_align.rs b/output/src/op_align.rs index 80f58fd5..6d5c1acb 100644 --- a/output/src/op_align.rs +++ b/output/src/op_align.rs @@ -1,24 +1,33 @@ 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); -try_from_expr!(<'a, E>: Align>: |state, iter| { - if let Some((Token { value: Value::Key(key), .. }, iter)) = iter.next() { +try_from_expr!(<'a, E>: Align>: |state, iter| + if let Some(Token { value: Value::Key(key), .. }) = iter.peek() { match key { - "align/c" => return Some(Self::c(state.get_content(&iter.next()?.0.value).expect("no content"))), - "align/x" => return Some(Self::x(state.get_content(&iter.next()?.0.value).expect("no content"))), - "align/y" => return Some(Self::y(state.get_content(&iter.next()?.0.value).expect("no content"))), - "align/n" => return Some(Self::n(state.get_content(&iter.next()?.0.value).expect("no content"))), - "align/s" => return Some(Self::s(state.get_content(&iter.next()?.0.value).expect("no content"))), - "align/e" => return Some(Self::e(state.get_content(&iter.next()?.0.value).expect("no content"))), - "align/w" => return Some(Self::w(state.get_content(&iter.next()?.0.value).expect("no content"))), - "align/nw" => return Some(Self::nw(state.get_content(&iter.next()?.0.value).expect("no content"))), - "align/ne" => return Some(Self::ne(state.get_content(&iter.next()?.0.value).expect("no content"))), - "align/sw" => return Some(Self::sw(state.get_content(&iter.next()?.0.value).expect("no content"))), - "align/se" => return Some(Self::se(state.get_content(&iter.next()?.0.value).expect("no content"))), + "align/c"|"align/x"|"align/y"| + "align/n"|"align/s"|"align/e"|"align/w"| + "align/nw"|"align/sw"|"align/ne"|"align/se" => { + let _ = iter.next().unwrap(); + let c = iter.next().expect("no content specified"); + let c = state.get_content(&c.value).expect("no content provided"); + return Some(match key { + "align/c" => Self::c(c), + "align/x" => Self::x(c), + "align/y" => Self::y(c), + "align/n" => Self::n(c), + "align/s" => Self::s(c), + "align/e" => Self::e(c), + "align/w" => Self::w(c), + "align/nw" => Self::nw(c), + "align/ne" => Self::ne(c), + "align/sw" => Self::sw(c), + "align/se" => Self::se(c), + _ => unreachable!() + }) + }, _ => return None } - } -}); + }); impl Align { pub fn c (a: A) -> Self { Self(Alignment::Center, a) } pub fn x (a: A) -> Self { Self(Alignment::X, a) } diff --git a/output/src/op_bsp.rs b/output/src/op_bsp.rs index bb2342ed..bfd13e08 100644 --- a/output/src/op_bsp.rs +++ b/output/src/op_bsp.rs @@ -32,33 +32,27 @@ impl, B: Content> Content for Bsp { } } try_from_expr!(<'a, E>: Bsp, RenderBox<'a, E>>: |state, iter| { - Some(if let Some((Token { value: Value::Key("bsp/n"), .. }, iter)) = iter.next() { - let (s, iter) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no south provided"), iter)).expect("no south specified"); - let (n, _) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no north provided"), iter)).expect("no north specified"); - Self::n(s, n) - } else if let Some((Token { value: Value::Key("bsp/s"), .. }, iter)) = iter.next() { - let (n, iter) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no north provided"), iter)).expect("no north specified"); - let (s, _) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no south provided"), iter)).expect("no south specified"); - Self::s(n, s) - } else if let Some((Token { value: Value::Key("bsp/e"), .. }, iter)) = iter.next() { - let (w, iter) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no west provided"), iter)).expect("no west specified"); - let (e, _) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no east provided"), iter)).expect("no east specified"); - Self::e(w, e) - } else if let Some((Token { value: Value::Key("bsp/w"), .. }, iter)) = iter.next() { - let (e, iter) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no west provided"), iter)).expect("no west specified"); - let (w, _) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no east provided"), iter)).expect("no east specified"); - Self::w(e, w) - } else if let Some((Token { value: Value::Key("bsp/a"), .. }, iter)) = iter.next() { - let (a, iter) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no above provided"), iter)).expect("no above specified"); - let (b, _) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no below provided"), iter)).expect("no below specified"); - Self::a(a, b) - } else if let Some((Token { value: Value::Key("bsp/b"), .. }, iter)) = iter.next() { - let (a, iter) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no above provided"), iter)).expect("no above specified"); - let (b, _) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no below provided"), iter)).expect("no below specified"); - Self::b(a, b) - } else { - return None - }) + if let Some(Token { value: Value::Key(key), .. }) = iter.peek() { + match key { + "bsp/n"|"bsp/s"|"bsp/e"|"bsp/w"|"bsp/a"|"bsp/b" => { + let _ = iter.next().unwrap(); + let c1 = iter.next().expect("no content1 specified"); + let c2 = iter.next().expect("no content2 specified"); + let c1 = state.get_content(&c1.value).expect("no content1 provided"); + let c2 = state.get_content(&c2.value).expect("no content2 provided"); + return Some(match key { + "bsp/n" => Self::n(c1, c2), + "bsp/s" => Self::s(c1, c2), + "bsp/e" => Self::e(c1, c2), + "bsp/w" => Self::w(c1, c2), + "bsp/a" => Self::a(c1, c2), + "bsp/b" => Self::b(c1, c2), + _ => unreachable!(), + }) + }, + _ => return None + } + } }); impl Bsp { pub fn n (a: A, b: B) -> Self { Self(North, a, b) } diff --git a/output/src/op_cond.rs b/output/src/op_cond.rs index b7d327d4..c5446bc2 100644 --- a/output/src/op_cond.rs +++ b/output/src/op_cond.rs @@ -7,31 +7,24 @@ pub struct Either(pub bool, pub A, pub B); impl Either { pub fn new (c: bool, a: A, b: B) -> Self { Self(c, a, b) } } try_from_expr!(<'a, E>: When>: |state, iter| { if let Some(Token { value: Value::Key("when"), .. }) = iter.peek() { - let iter = iter.clone().next().unwrap().1; - let condition = iter.next(); - if let Some((ref condition, _)) = condition { - let condition = state.get(&condition.value).expect("no condition"); - if let Some((ref content, _)) = iter.next() { - let content = state.get_content(&content.value).expect("no atom"); - return Some(Self(condition, content)) - } - } + let _ = iter.next().unwrap(); + let condition = iter.next().expect("no condition specified"); + let content = iter.next().expect("no content specified"); + let condition = state.get(&condition.value).expect("no condition provided"); + let content = state.get_content(&content.value).expect("no content provided"); + return Some(Self(condition, content)) } }); try_from_expr!(<'a, E>: Either, RenderBox<'a, E>>: |state, iter| { - if let Some((Token { value: Value::Key("either"), .. }, _)) = iter.next() { - let iter = iter.clone().next().unwrap().1; - let condition = iter.next(); - if let Some((ref condition, _)) = condition { - let condition = state.get(&condition.value).expect("no condition"); - if let Some((ref content1, _)) = iter.next() { - let content1 = state.get_content(&content1.value).expect("no content1"); - if let Some((ref content2, _)) = iter.next() { - let content2 = state.get_content(&content2.value).expect("no content2"); - return Some(Self(condition, content1, content2)) - } - } - } + if let Some(Token { value: Value::Key("either"), .. }) = iter.peek() { + let _ = iter.next().unwrap(); + let condition = iter.next().expect("no condition specified"); + let content = iter.next().expect("no content specified"); + let alternate = iter.next().expect("no alternate specified"); + let condition = state.get(&condition.value).expect("no condition provided"); + let content = state.get_content(&content.value).expect("no content provided"); + let alternate = state.get_content(&alternate.value).expect("no alternate provided"); + return Some(Self(condition, content, alternate)) } }); impl> Content for When { diff --git a/output/src/op_transform.rs b/output/src/op_transform.rs index dbcd0ca2..8c534164 100644 --- a/output/src/op_transform.rs +++ b/output/src/op_transform.rs @@ -12,16 +12,21 @@ macro_rules! transform_xy { impl<'a, E: Output + 'a, T: ViewContext<'a, E>> TryFromAtom<'a, T> for $Enum> { fn try_from_expr (state: &'a T, iter: TokenIter<'a>) -> Option { - let iter = iter.clone(); - Some(if let Some((Token { value: Value::Key($x), .. }, iter)) = iter.next() { - Self::x(state.get_content(&iter.next().expect("no content").0.value).expect("no content")) - } else if let Some((Token { value: Value::Key($y), .. }, iter)) = iter.next() { - Self::y(state.get_content(&iter.next().expect("no content").0.value).expect("no content")) - } else if let Some((Token { value: Value::Key($xy), .. }, iter)) = iter.next() { - Self::xy(state.get_content(&iter.next().expect("no content").0.value).expect("no content")) - } else { - return None - }) + let mut iter = iter.clone(); + if let Some(Token { value: Value::Key(k), .. }) = iter.peek() { + if k == $x || k == $y || k == $xy { + let _ = iter.next().unwrap(); + let token = iter.next().expect("no content specified"); + let content = state.get_content(&token.value).expect("no content provided"); + return Some(match k { + $x => Self::x(content), + $y => Self::y(content), + $xy => Self::xy(content), + _ => unreachable!() + }) + } + } + None } } impl> Content for $Enum { @@ -53,22 +58,31 @@ macro_rules! transform_xy_unit { impl<'a, E: Output + 'a, T: ViewContext<'a, E>> TryFromAtom<'a, T> for $Enum> { fn try_from_expr (state: &'a T, iter: TokenIter<'a>) -> Option { - Some(if let Some((Token { value: Value::Key($x), .. }, iter)) = iter.next() { - let (x, iter) = iter.next().map(|(x, iter)|(state.get(&x.value).expect("no x provided"), iter)).expect("no x specified"); - let (c, _) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no content provided"), iter)).expect("no content specified"); - Self::x(x, c) - } else if let Some((Token { value: Value::Key($y), .. }, iter)) = iter.next() { - let (y, iter) = iter.next().map(|(y, iter)|(state.get(&y.value).expect("no y provided"), iter)).expect("no y specified"); - let (c, _) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no content provided"), iter)).expect("no content specified"); - Self::y(y, c) - } else if let Some((Token { value: Value::Key($xy), .. }, iter)) = iter.next() { - let (x, iter) = iter.next().map(|(x, iter)|(state.get(&x.value).expect("no x provided"), iter)).expect("no x specified"); - let (y, iter) = iter.next().map(|(y, iter)|(state.get(&y.value).expect("no y provided"), iter)).expect("no y specified"); - let (c, _) = iter.next().map(|(c, iter)|(state.get_content(&c.value).expect("no content provided"), iter)).expect("no content specified"); - Self::xy(x, y, c) - } else { - return None - }) + let mut iter = iter.clone(); + if let Some(Token { value: Value::Key(k), .. }) = iter.peek() { + if k == $x || k == $y { + let _ = iter.next().unwrap(); + let u = iter.next().expect("no unit specified"); + let c = iter.next().expect("no content specified"); + let u = state.get(&u.value).expect("no unit provided"); + let c = state.get_content(&c.value).expect("not content provided"); + return Some(match k { + $x => Self::x(u, c), + $y => Self::y(u, c), + _ => unreachable!(), + }) + } else if k == $xy { + let _ = iter.next().unwrap(); + let u = iter.next().expect("no unit specified"); + let v = iter.next().expect("no unit specified"); + let c = iter.next().expect("no content specified"); + let u = state.get(&u.value).expect("no unit provided"); + let v = state.get(&v.value).expect("no unit provided"); + let c = state.get_content(&c.value).expect("not content provided"); + return Some(Self::xy(u, v, c)) + } + } + None } } impl> Content for $Enum { diff --git a/output/src/view.rs b/output/src/view.rs index 90041e5b..c199258e 100644 --- a/output/src/view.rs +++ b/output/src/view.rs @@ -7,7 +7,7 @@ use crate::*; fn content (&$self) -> impl Render<$Output> { $expr } } impl<'a> ViewContext<'a, $Output> for $State { - fn get_content_custom (&'a $self, value: &Value<'a>) -> Option> { + fn get_content_sym (&'a $self, value: &Value<'a>) -> Option> { if let Value::Sym(s) = value { match *s { $($sym => Some($body),)* @@ -23,7 +23,7 @@ use crate::*; // An ephemeral wrapper around view state and view description, // that is meant to be constructed and returned from [Content::content]. -pub struct View<'a, T>(pub &'a T, pub TokenIter<'a>); +pub struct View<'a, T>(pub &'a T, pub SourceIter<'a>); impl<'a, O: Output + 'a, T: ViewContext<'a, O>> Content for View<'a, T> { fn content (&self) -> impl Render { let iter = self.1.clone(); @@ -42,14 +42,14 @@ pub trait ViewContext<'a, E: Output + 'a>: Send + Sync + Context { fn get_content (&'a self, value: &Value<'a>) -> Option> { - if let Some(builtin) = self.get_content_builtin(value) { - Some(builtin) - } else { - self.get_content_custom(value) + match value { + Value::Sym(_) => self.get_content_sym(value), + Value::Exp(_, _) => self.get_content_exp(value), + _ => panic!("only :symbols and (expressions) accepted here") } } - fn get_content_custom (&'a self, value: &Value<'a>) -> Option>; - fn get_content_builtin (&'a self, value: &Value<'a>) -> Option> { + fn get_content_sym (&'a self, value: &Value<'a>) -> Option>; + fn get_content_exp (&'a self, value: &Value<'a>) -> Option> { try_delegate!(self, *value, When::>); try_delegate!(self, *value, Either::, RenderBox<'a, E>>); try_delegate!(self, *value, Align::>); @@ -78,6 +78,7 @@ pub trait ViewContext<'a, E: Output + 'a>: Send + Sync (<$l:lifetime, $E:ident>: $Struct:ty: |$state:ident, $iter:ident|$body:expr) => { impl<$l, $E: Output + $l, T: ViewContext<$l, $E>> TryFromAtom<$l, T> for $Struct { fn try_from_expr ($state: &$l T, $iter: TokenIter<'a>) -> Option { + let mut $iter = $iter.clone(); $body; None } diff --git a/tek/src/lib.rs b/tek/src/lib.rs index b2fd35e4..53fb06d1 100644 --- a/tek/src/lib.rs +++ b/tek/src/lib.rs @@ -142,13 +142,13 @@ impl TekCli { pub history: Vec, /// View definition - pub view: TokenIter<'static>, + pub view: SourceIter<'static>, // Input definitions - pub keys: TokenIter<'static>, - pub keys_clip: TokenIter<'static>, - pub keys_track: TokenIter<'static>, - pub keys_scene: TokenIter<'static>, - pub keys_mix: TokenIter<'static>, + pub keys: SourceIter<'static>, + pub keys_clip: SourceIter<'static>, + pub keys_track: SourceIter<'static>, + pub keys_scene: SourceIter<'static>, + pub keys_mix: SourceIter<'static>, } has_size!(|self: Tek|&self.size); has_clock!(|self: Tek|self.clock); @@ -213,17 +213,17 @@ impl Tek { midi_froms: &[PortConnection], midi_tos: &[PortConnection], ) -> Usually { let tek = Self { - view: TokenIter(include_str!("./view_transport.edn")), + view: SourceIter(include_str!("./view_transport.edn")), jack: jack.clone(), color: ItemPalette::random(), clock: Clock::new(jack, bpm), midi_ins: vec![JackPort::::new(jack, "GlobalI", midi_froms)?], midi_outs: vec![JackPort::::new(jack, "GlobalO", midi_tos)?], - keys: TokenIter(KEYS_APP), - keys_clip: TokenIter(KEYS_CLIP), - keys_track: TokenIter(KEYS_TRACK), - keys_scene: TokenIter(KEYS_SCENE), - keys_mix: TokenIter(KEYS_MIX), + keys: SourceIter(KEYS_APP), + keys_clip: SourceIter(KEYS_CLIP), + keys_track: SourceIter(KEYS_TRACK), + keys_scene: SourceIter(KEYS_SCENE), + keys_mix: SourceIter(KEYS_MIX), ..Default::default() }; tek.sync_lead(sync_lead); @@ -238,7 +238,7 @@ impl Tek { let clip = MidiClip::new("Clip", true, 384usize, None, Some(ItemColor::random().into())); let clip = Arc::new(RwLock::new(clip)); Ok(Self { - view: TokenIter(include_str!("./view_sequencer.edn")), + view: SourceIter(include_str!("./view_sequencer.edn")), pool: Some((&clip).into()), editor: Some((&clip).into()), editing: false.into(), @@ -254,7 +254,7 @@ impl Tek { audio_froms: &[&[PortConnection];2], audio_tos: &[&[PortConnection];2], ) -> Usually { let app = Self { - view: TokenIter(include_str!("./view_groovebox.edn")), + view: SourceIter(include_str!("./view_groovebox.edn")), sampler: Some(Sampler::new(jack, &"sampler", midi_froms, audio_froms, audio_tos)?), ..Self::new_sequencer(jack, bpm, sync_lead, sync_follow, midi_froms, midi_tos)? }; @@ -271,7 +271,7 @@ impl Tek { scenes: usize, tracks: usize, track_width: usize, ) -> Usually { let mut arranger = Self { - view: TokenIter(include_str!("./view_arranger.edn")), + view: SourceIter(include_str!("./view_arranger.edn")), ..Self::new_groovebox( jack, bpm, sync_lead, sync_follow, midi_froms, midi_tos, audio_froms, audio_tos,