From 47b8900adcbbae7a09fd92bd2159050b5f654d54 Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Sat, 7 Jan 2023 04:37:44 +0100 Subject: [PATCH] implement tree cursor widget as projection pipeline --- nested/src/list/cursor.rs | 6 +++ nested/src/list/editor.rs | 71 ++++++++++++++++++++++-- nested/src/list/nav.rs | 11 ++++ nested/src/singleton/to_sequence.rs | 4 +- nested/src/terminal/mod.rs | 24 +++++++-- nested/src/tree/nav.rs | 52 +++++++++++++++++- nested/src/tree/node.rs | 20 ++++++- nested/src/vec/buffer.rs | 8 ++- shell/src/main.rs | 84 ++++------------------------- 9 files changed, 191 insertions(+), 89 deletions(-) diff --git a/nested/src/list/cursor.rs b/nested/src/list/cursor.rs index 9f8d0d9..de21c01 100644 --- a/nested/src/list/cursor.rs +++ b/nested/src/list/cursor.rs @@ -4,6 +4,12 @@ pub enum ListCursorMode { Select } +impl Default for ListCursorMode { + fn default() -> Self { + ListCursorMode::Select + } +} + #[derive(Clone, Copy, Eq, PartialEq)] pub struct ListCursor { pub mode: ListCursorMode, diff --git a/nested/src/list/editor.rs b/nested/src/list/editor.rs index 7a456f0..f4b225e 100644 --- a/nested/src/list/editor.rs +++ b/nested/src/list/editor.rs @@ -6,11 +6,12 @@ use { ListCursor, ListSegment, ListSegmentSequence, + ListCursorMode }, sequence::{SequenceView}, singleton::{SingletonBuffer, SingletonView}, terminal::{TerminalView}, - tree::NestedNode, + tree::{NestedNode, TreeNav}, vec::{VecBuffer, MutableVecAccess}, PtySegment }, @@ -23,6 +24,9 @@ pub struct ListEditor { pub(super) cursor: SingletonBuffer, pub(crate) data: VecBuffer, + pub(super) addr_port: OuterViewPort>, + pub(super) mode_port: OuterViewPort>, + pub(crate) ctx: Arc>, pub(super) typ: TypeTerm, pub(super) depth: usize, @@ -35,16 +39,74 @@ impl ListEditor { typ: TypeTerm, depth: usize ) -> Self { + let mut cursor = SingletonBuffer::new(ListCursor::default()); + let mut data = VecBuffer::::new(); + ListEditor { - cursor: SingletonBuffer::new(ListCursor::default()), - data: VecBuffer::::new(), + mode_port: cursor + .get_port() + .map({ + let data = data.clone(); + move |c| { + let ip = SingletonBuffer::new(c.mode).get_port(); + match c.mode { + ListCursorMode::Insert => ip, + ListCursorMode::Select => { + if let Some(idx) = c.idx { + data.get(idx as usize).get_mode_view() + } else { + ip + } + } + } + } + }) + .flatten(), + + addr_port: VecBuffer::>>::with_data( + vec![ + cursor.get_port() + .map( + |x| { + // todo implement this with filter_map + let mut b = VecBuffer::new(); + if let Some(i) = x.idx { + b.push(i); + } + b.get_port().to_sequence() + } + ) + .to_sequence() + .flatten(), + cursor.get_port() + .map({ + let data = data.clone(); + move |cur| { + if cur.mode == ListCursorMode::Select { + if let Some(idx) = cur.idx { + if idx >= 0 && idx < data.len() as isize { + return data.get(idx as usize).get_addr_view(); + } + } + } + OuterViewPort::default() + } + }) + .to_sequence() + .flatten() + ]) + .get_port() + .to_sequence() + .flatten(), + cursor, + data, ctx, typ, depth, cur_dist: Arc::new(RwLock::new(0)), } } - + pub fn get_seg_seq_view( &self, ) -> OuterViewPort>> { @@ -77,6 +139,7 @@ impl ListEditor { None } } + pub fn get_item_mut(&mut self) -> Option> { if let Some(idx) = self.cursor.get().idx { let idx = crate::utils::modulo(idx as isize, self.data.len() as isize) as usize; diff --git a/nested/src/list/nav.rs b/nested/src/list/nav.rs index d2d2a2a..920d174 100644 --- a/nested/src/list/nav.rs +++ b/nested/src/list/nav.rs @@ -1,10 +1,13 @@ use { crate::{ + core::{OuterViewPort}, + sequence::{SequenceView}, list::{ ListCursor, ListCursorMode, ListEditor }, tree::{TreeCursor, TreeNav, TreeNavResult}, + singleton::SingletonView, Nested }, cgmath::Vector2 @@ -13,6 +16,14 @@ use { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> impl TreeNav for ListEditor { + fn get_addr_view(&self) -> OuterViewPort> { + self.addr_port.clone() + } + + fn get_mode_view(&self) -> OuterViewPort> { + self.mode_port.clone() + } + fn get_cursor_warp(&self) -> TreeCursor { let cur = self.cursor.get(); match cur.mode { diff --git a/nested/src/singleton/to_sequence.rs b/nested/src/singleton/to_sequence.rs index c69c038..21579b9 100644 --- a/nested/src/singleton/to_sequence.rs +++ b/nested/src/singleton/to_sequence.rs @@ -52,11 +52,11 @@ where type Item = SrcView::Item; fn get(&self, _idx: &usize) -> Option { - Some(self.src_view.as_ref().unwrap().get()) + Some(self.src_view.as_ref()?.get()) } fn len(&self) -> Option { - Some(1) + Some(if self.src_view.is_some() { 1 } else { 0 }) } } diff --git a/nested/src/terminal/mod.rs b/nested/src/terminal/mod.rs index 5194930..8a6f470 100644 --- a/nested/src/terminal/mod.rs +++ b/nested/src/terminal/mod.rs @@ -40,11 +40,9 @@ use { }; pub fn make_label(s: &str) -> OuterViewPort { - let label_port = ViewPort::new(); - let _label = VecBuffer::with_data(s.chars().collect(), label_port.inner()); + let label = VecBuffer::with_data(s.chars().collect()); - let v = label_port - .outer() + let v = label.get_port() .to_sequence() .map(|c| TerminalAtom::from(c)) .to_index() @@ -55,3 +53,21 @@ pub fn make_label(s: &str) -> OuterViewPort { v } + +impl OuterViewPort { + pub fn with_style(&self, style: TerminalStyle) -> OuterViewPort { + self.map_item( + move |_idx, a| + a.add_style_front(style) + ) + } + + pub fn with_fg_color(&self, col: (u8, u8, u8)) -> OuterViewPort { + self.with_style(TerminalStyle::fg_color(col)) + } + + pub fn with_bg_color(&self, col: (u8, u8, u8)) -> OuterViewPort { + self.with_style(TerminalStyle::bg_color(col)) + } +} + diff --git a/nested/src/tree/nav.rs b/nested/src/tree/nav.rs index 36b7ff0..47e1275 100644 --- a/nested/src/tree/nav.rs +++ b/nested/src/tree/nav.rs @@ -1,7 +1,15 @@ use { crate::list::ListCursorMode, crate::tree::TreeCursor, - cgmath::Vector2 + crate::vec::VecBuffer, + crate::core::{OuterViewPort}, + crate::sequence::{SequenceView, decorator::Separate}, + crate::singleton::{SingletonBuffer, SingletonView}, + cgmath::Vector2, + crate::{ + terminal::{TerminalView, TerminalStyle, make_label} + + } }; #[derive(Clone, Copy, Eq, PartialEq)] @@ -21,6 +29,8 @@ impl From for TerminalEditorResult { } */ + + pub trait TreeNav { /* CORE */ @@ -28,6 +38,14 @@ pub trait TreeNav { TreeCursor::default() } + fn get_addr_view(&self) -> OuterViewPort> { + VecBuffer::::new().get_port().to_sequence() + } + + fn get_mode_view(&self) -> OuterViewPort> { + SingletonBuffer::new(ListCursorMode::Select).get_port() + } + fn get_cursor_warp(&self) -> TreeCursor { TreeCursor::default() } @@ -119,10 +137,40 @@ pub trait TreeNav { } } } - + self.goto(c) } } } + + fn get_cursor_widget(&self) -> OuterViewPort { + VecBuffer::with_data( + vec![ + make_label("@").with_fg_color((150, 80,230)), + self.get_addr_view() + .map(|i| + make_label(&format!("{}", i)).with_fg_color((0, 100, 20))) + .separate(make_label(".").with_fg_color((150, 80,230))) + .to_grid_horizontal() + .flatten(), + make_label(":").with_fg_color((150, 80,230)), + self.get_mode_view() + .map(|mode| { + make_label( + match mode { + ListCursorMode::Insert => "INSERT", + ListCursorMode::Select => "SELECT" + }) + .with_fg_color((200, 200, 20)) + }) + .to_grid() + .flatten(), + make_label(":").with_fg_color((150, 80,230)) + ] + ).get_port() + .to_sequence() + .to_grid_horizontal() + .flatten() + } } diff --git a/nested/src/tree/node.rs b/nested/src/tree/node.rs index 724db8f..81d8a22 100644 --- a/nested/src/tree/node.rs +++ b/nested/src/tree/node.rs @@ -4,12 +4,14 @@ use { crate::{ core::{ViewPort, OuterViewPort, AnyOuterViewPort}, type_system::{ReprTree, Context}, - singleton::{SingletonBuffer}, + singleton::{SingletonBuffer, SingletonView}, sequence::SequenceView, terminal::{TerminalView, TerminalEvent, TerminalEditor, TerminalEditorResult}, diagnostics::{Diagnostics, Message}, tree::{TreeNav, TreeCursor, TreeNavResult}, + list::{ListCursorMode}, commander::ObjCommander, + vec::VecBuffer, Nested } }; @@ -62,6 +64,22 @@ impl TreeNav for NestedNode { } } + fn get_addr_view(&self) -> OuterViewPort> { + if let Some(tn) = self.tree_nav.as_ref() { + tn.read().unwrap().get_addr_view() + } else { + OuterViewPort::default() + } + } + + fn get_mode_view(&self) -> OuterViewPort> { + if let Some(tn) = self.tree_nav.as_ref() { + tn.read().unwrap().get_mode_view() + } else { + OuterViewPort::default() + } + } + fn get_cursor_warp(&self) -> TreeCursor { if let Some(tn) = self.tree_nav.as_ref() { tn.read().unwrap().get_cursor_warp() diff --git a/nested/src/vec/buffer.rs b/nested/src/vec/buffer.rs index 77116c6..66a1098 100644 --- a/nested/src/vec/buffer.rs +++ b/nested/src/vec/buffer.rs @@ -34,7 +34,7 @@ impl VecBuffer where T: Clone + Send + Sync + 'static, { - pub fn with_data(data: Vec, port: InnerViewPort>>) -> Self { + pub fn with_data_port(data: Vec, port: InnerViewPort>>) -> Self { let data = Arc::new(RwLock::new(data)); port.set_view(Some(data.clone())); @@ -48,8 +48,12 @@ where } } + pub fn with_data(data: Vec) -> Self { + VecBuffer::with_data_port(data, ViewPort::new().into_inner()) + } + pub fn with_port(port: InnerViewPort>>) -> Self { - VecBuffer::with_data(vec![], port) + VecBuffer::with_data_port(vec![], port) } pub fn new() -> Self { diff --git a/shell/src/main.rs b/shell/src/main.rs index 80369af..f8360fe 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -13,6 +13,7 @@ use { core::{port::UpdateTask, Observer, AnyOuterViewPort, ViewPort}, type_system::{Context, ReprTree}, index::IndexArea, + singleton::{SingletonView, SingletonBuffer}, list::{ListCursorMode, PTYListEditor}, sequence::{decorator::{SeqDecorStyle, Separate}}, terminal::{ @@ -121,14 +122,10 @@ async fn main() { }); let mut cur_size = nested::singleton::SingletonBuffer::new(Vector2::new(10, 10)); - let mut status_chars = VecBuffer::new(); - + table.insert_iter(vec![ (Point2::new(0, 0), magic.clone()), - ( - Point2::new(0, 1), - status_chars.get_port().to_sequence().to_grid_horizontal(), - ), + (Point2::new(0, 1), process_list_editor.editor.read().unwrap().get_cursor_widget()), (Point2::new(0, 2), magic.clone()), (Point2::new(0, 3), make_label(" ")), (Point2::new(0, 4), @@ -162,12 +159,7 @@ async fn main() { ) .separate({ let mut buf = IndexBuffer::new(); - buf.insert(Point2::new(1,0), - make_label(" ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~") - .map_item( - |p,a| - a.add_style_front(TerminalStyle::fg_color((40,40,40))) - ) + buf.insert(Point2::new(1,0), make_label(" ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~").with_fg_color((40,40,40)) ); buf.get_port() }) @@ -183,17 +175,14 @@ async fn main() { |entry| { let mut b = VecBuffer::new(); b.push( - make_label("@") - .map_item(|_p,a| a - .add_style_back(TerminalStyle::bold(true)) - .add_style_back(TerminalStyle::fg_color((120,120,0)))) + make_label("@").with_style( + TerminalStyle::bold(true) + .add(TerminalStyle::fg_color((120,120,0)))) ); for x in entry.addr.iter() { b.push( - make_label(&format!("{}", x)) - .map_item(|_p,a| a - .add_style_back(TerminalStyle::fg_color((0, 100, 20)))) + make_label(&format!("{}", x)).with_fg_color((0, 100, 20)) ); b.push( make_label(".") @@ -220,14 +209,9 @@ async fn main() { ).to_grid_vertical().flatten()) ]); - + let (_w, _h) = termion::terminal_size().unwrap(); -/* - compositor - .write() - .unwrap() - .push(monstera::make_monstera().offset(Vector2::new(w as i16 - 38, 0))); -*/ + compositor .write() .unwrap() @@ -307,54 +291,6 @@ async fn main() { process_list_editor.send_cmd(&ev); } } - - status_chars.clear(); - let cur = process_list_editor.editor.read().unwrap().get_cursor(); - - if cur.tree_addr.len() > 0 { - status_chars.push(TerminalAtom::new( - '@', - TerminalStyle::fg_color((150, 80,230)).add(TerminalStyle::bold(true)), - )); - for x in cur.tree_addr { - for c in format!("{}", x).chars() { - status_chars - .push(TerminalAtom::new(c, TerminalStyle::fg_color((0, 100, 20)))); - } - status_chars.push(TerminalAtom::new( - '.', - TerminalStyle::fg_color((150, 80,230)) - )); - } - - status_chars.push(TerminalAtom::new( - ':', - TerminalStyle::fg_color((150, 80,230)).add(TerminalStyle::bold(true)), - )); - for c in match cur.leaf_mode { - ListCursorMode::Insert => "INSERT", - ListCursorMode::Select => "SELECT" - } - .chars() - { - status_chars.push(TerminalAtom::new( - c, - TerminalStyle::fg_color((200, 200, 20)), - )); - } - status_chars.push(TerminalAtom::new( - ':', - TerminalStyle::fg_color((150, 80,230)).add(TerminalStyle::bold(true)), - - )); - } else { - for c in "Press to enter".chars() { - status_chars.push(TerminalAtom::new( - c, - TerminalStyle::fg_color((200, 200, 20)), - )); - } - } } drop(term);