From b0b91af2adcdc6e56a6c907bede389f8b4ea3693 Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Fri, 17 Jun 2022 18:20:13 +0200 Subject: [PATCH] sequence decorators --- nested/src/sequence/decorator.rs | 256 +++++++++++++++++++++++++++++++ nested/src/sequence/mod.rs | 3 +- 2 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 nested/src/sequence/decorator.rs diff --git a/nested/src/sequence/decorator.rs b/nested/src/sequence/decorator.rs new file mode 100644 index 0000000..df7be0a --- /dev/null +++ b/nested/src/sequence/decorator.rs @@ -0,0 +1,256 @@ +use { + crate::{ + core::{View, OuterViewPort, Observer, ViewPort, ObserverBroadcast}, + projection::ProjectionHelper, + sequence::SequenceView, + terminal::{make_label, TerminalView}, + }, + std::sync::Arc, + std::sync::RwLock, +}; + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> +// Wrap +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +pub struct Wrapped +where T: Send + Sync + 'static +{ + pub(super) opening: T, + pub(super) closing: T, + pub(super) items: Arc>, + + pub(super) cast: Arc>>>, + pub(super) proj_helper: ProjectionHelper<(), Self>, +} + +impl View for Wrapped +where T: Clone + Send + Sync + 'static +{ + type Msg = usize; +} + +impl SequenceView for Wrapped +where T: Clone + Send + Sync + 'static +{ + type Item = T; + + fn len(&self) -> Option { + Some(self.items.len()? + 2) + } + + fn get(&self, idx: &usize) -> Option { + let l = self.items.len().unwrap_or((-2 as i32) as usize); + if *idx < l+2 { + Some( + if *idx == 0 { + self.opening.clone() + } else if *idx < l+1 { + self.items.get(&(*idx - 1))? + } else { + self.closing.clone() + }) + } else { + None + } + } +} + + +pub trait Wrap { + fn wrap(&self, opening: T, closing: T) -> OuterViewPort>; +} + +impl Wrap for OuterViewPort> +where T: Clone + Send + Sync + 'static +{ + fn wrap(&self, opening: T, closing: T) -> OuterViewPort> { + let port = ViewPort::new(); + + let mut proj_helper = ProjectionHelper::new(port.update_hooks.clone()); + let w = Arc::new(RwLock::new(Wrapped { + opening, + closing, + items: proj_helper.new_sequence_arg((), self.clone(), |s: &mut Wrapped, item_idx| { + s.cast.notify(&(*item_idx + 1)); + s.cast.notify(&(*item_idx + 2)); + }), + cast: port.get_cast(), + proj_helper, + })); + + w.write().unwrap().proj_helper.set_proj(&w); + port.set_view(Some(w.clone())); + port.into_outer() + } +} + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> +// Separate +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +pub struct Separated +where T: Send + Sync + 'static +{ + pub(super) delimiter: T, + pub(super) items: Arc>, + + pub(super) cast: Arc>>>, + pub(super) proj_helper: ProjectionHelper<(), Self>, +} + +impl View for Separated +where T: Clone + Send + Sync + 'static +{ + type Msg = usize; +} + +impl SequenceView for Separated +where T: Clone + Send + Sync + 'static +{ + type Item = T; + + fn len(&self) -> Option { + let l = self.items.len()?; + if l == 0 { + Some(0) + } else if l == 1 { + Some(1) + } else { + Some(l*2 - 1) + } + } + + fn get(&self, idx: &usize) -> Option { + let l = self.items.len().unwrap_or(usize::MAX); + if *idx+1 < l*2 { + if *idx % 2 == 0 { + self.items.get(&(*idx / 2)) + } else { + Some(self.delimiter.clone()) + } + } else { + None + } + } +} + +pub trait Separate { + fn separate(&self, delimiter: T) -> OuterViewPort>; +} + +impl Separate for OuterViewPort> +where T: Clone + Send + Sync + 'static +{ + fn separate(&self, delimiter: T) -> OuterViewPort> { + let port = ViewPort::new(); + + let mut proj_helper = ProjectionHelper::new(port.update_hooks.clone()); + let w = Arc::new(RwLock::new(Separated { + delimiter, + items: proj_helper.new_sequence_arg( + (), + self.clone(), + |s: &mut Separated, item_idx| { + s.cast.notify(&(*item_idx * 2)); + if *item_idx > 0 { + s.cast.notify(&(*item_idx * 2 - 1)); + } + }), + + cast: port.get_cast(), + proj_helper, + })); + + w.write().unwrap().proj_helper.set_proj(&w); + port.set_view(Some(w.clone())); + port.into_outer() + } +} + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +#[derive(Clone, Copy)] +pub enum SeqDecorStyle { + Plain, + HorizontalSexpr, + VerticalSexpr, + DoubleQuote, + Tuple, + EnumSet, + Path, + Hex +} + +pub trait PTYSeqDecorate { + fn pty_decorate( + &self, + style: SeqDecorStyle, + depth: usize + ) -> OuterViewPort; +} + +impl PTYSeqDecorate for OuterViewPort>> +{ + fn pty_decorate( + &self, + style: SeqDecorStyle, + depth: usize + ) -> OuterViewPort { + match style { + SeqDecorStyle::Plain => self + .to_grid_horizontal() + .flatten(), + + SeqDecorStyle::HorizontalSexpr => self + .separate(make_label(" ")) + .wrap(make_label("("), make_label(")")) + .to_grid_horizontal() + .flatten(), + + SeqDecorStyle::VerticalSexpr => self + .wrap(make_label("("), make_label(")")) + .to_grid_vertical() + .flatten(), + + SeqDecorStyle::DoubleQuote => self + .wrap(make_label("\""), make_label("\"")) + .to_grid_horizontal() + .flatten(), + +/* + SeqDecorStyle::FlexibleSexpr => self + .line_warp(width) + .map(|v| v.decorate(make_label(""")make_label(",") ", depth).to_grid_horizontal()) + .decorate(make_label("("), make_label(")"), "", depth) + .to_grid_vertical() + .flatten(), + */ + + SeqDecorStyle::Tuple => self + .separate(make_label(",")) + .wrap(make_label("("), make_label(")")) + .to_grid_horizontal() + .flatten(), + + SeqDecorStyle::EnumSet => self + .separate(make_label(",")) + .wrap(make_label("{"), make_label("}")) + .to_grid_horizontal() + .flatten(), + + SeqDecorStyle::Path => self + .separate(make_label("/")) + .wrap(make_label("<"), make_label(">")) + .to_grid_horizontal() + .flatten(), + + SeqDecorStyle::Hex => self + .wrap(make_label("0"), make_label("")) + .to_grid_horizontal() + .flatten(), + } + } +} + + diff --git a/nested/src/sequence/mod.rs b/nested/src/sequence/mod.rs index 4a8c270..3872995 100644 --- a/nested/src/sequence/mod.rs +++ b/nested/src/sequence/mod.rs @@ -1,7 +1,8 @@ pub mod filter; -pub mod flatten; pub mod map; pub mod seq2idx; +pub mod flatten; +pub mod decorator; pub use seq2idx::Sequence2Index;