sequence decorators
This commit is contained in:
parent
87ed4ef1ca
commit
b0b91af2ad
2 changed files with 258 additions and 1 deletions
256
nested/src/sequence/decorator.rs
Normal file
256
nested/src/sequence/decorator.rs
Normal file
|
@ -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<T>
|
||||
where T: Send + Sync + 'static
|
||||
{
|
||||
pub(super) opening: T,
|
||||
pub(super) closing: T,
|
||||
pub(super) items: Arc<dyn SequenceView<Item = T>>,
|
||||
|
||||
pub(super) cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = T>>>>,
|
||||
pub(super) proj_helper: ProjectionHelper<(), Self>,
|
||||
}
|
||||
|
||||
impl<T> View for Wrapped<T>
|
||||
where T: Clone + Send + Sync + 'static
|
||||
{
|
||||
type Msg = usize;
|
||||
}
|
||||
|
||||
impl<T> SequenceView for Wrapped<T>
|
||||
where T: Clone + Send + Sync + 'static
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn len(&self) -> Option<usize> {
|
||||
Some(self.items.len()? + 2)
|
||||
}
|
||||
|
||||
fn get(&self, idx: &usize) -> Option<Self::Item> {
|
||||
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<T> {
|
||||
fn wrap(&self, opening: T, closing: T) -> OuterViewPort<dyn SequenceView<Item = T>>;
|
||||
}
|
||||
|
||||
impl<T> Wrap<T> for OuterViewPort<dyn SequenceView<Item = T>>
|
||||
where T: Clone + Send + Sync + 'static
|
||||
{
|
||||
fn wrap(&self, opening: T, closing: T) -> OuterViewPort<dyn SequenceView<Item = T>> {
|
||||
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<T>, 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<T>
|
||||
where T: Send + Sync + 'static
|
||||
{
|
||||
pub(super) delimiter: T,
|
||||
pub(super) items: Arc<dyn SequenceView<Item = T>>,
|
||||
|
||||
pub(super) cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = T>>>>,
|
||||
pub(super) proj_helper: ProjectionHelper<(), Self>,
|
||||
}
|
||||
|
||||
impl<T> View for Separated<T>
|
||||
where T: Clone + Send + Sync + 'static
|
||||
{
|
||||
type Msg = usize;
|
||||
}
|
||||
|
||||
impl<T> SequenceView for Separated<T>
|
||||
where T: Clone + Send + Sync + 'static
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn len(&self) -> Option<usize> {
|
||||
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<T> {
|
||||
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<T> {
|
||||
fn separate(&self, delimiter: T) -> OuterViewPort<dyn SequenceView<Item = T>>;
|
||||
}
|
||||
|
||||
impl<T> Separate<T> for OuterViewPort<dyn SequenceView<Item = T>>
|
||||
where T: Clone + Send + Sync + 'static
|
||||
{
|
||||
fn separate(&self, delimiter: T) -> OuterViewPort<dyn SequenceView<Item = T>> {
|
||||
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<T>, 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<dyn TerminalView>;
|
||||
}
|
||||
|
||||
impl PTYSeqDecorate for OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>
|
||||
{
|
||||
fn pty_decorate(
|
||||
&self,
|
||||
style: SeqDecorStyle,
|
||||
depth: usize
|
||||
) -> OuterViewPort<dyn TerminalView> {
|
||||
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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue