From 5fef75e24f9050c17edf26cec9d6d724e86bde7e Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Sun, 19 Jun 2022 23:13:21 +0200 Subject: [PATCH] listeditor cleanup --- nested/src/char_editor.rs | 68 +++ nested/src/color.rs | 25 ++ nested/src/index/buffer.rs | 6 +- nested/src/integer/editor.rs | 3 + nested/src/lib.rs | 32 +- nested/src/list/cursor.rs | 37 +- nested/src/list/editor.rs | 748 ++----------------------------- nested/src/list/editor_view.rs | 122 ----- nested/src/list/mod.rs | 12 +- nested/src/list/nav.rs | 240 ++++++++++ nested/src/list/pty_editor.rs | 208 +++++++++ nested/src/list/segment.rs | 176 ++++++++ nested/src/list/sexpr.rs | 270 ----------- nested/src/make_editor.rs | 129 +++--- nested/src/modulo.rs | 10 + nested/src/product/editor.rs | 53 ++- nested/src/product/element.rs | 61 +-- nested/src/product/nav.rs | 100 ++--- nested/src/sequence/decorator.rs | 6 +- nested/src/string_editor.rs | 151 ------- nested/src/tree_nav.rs | 126 ++++-- shell/src/command.rs | 194 ++++++++ shell/src/main.rs | 57 ++- shell/src/process.rs | 87 ++-- shell/src/pty.rs | 2 +- 25 files changed, 1342 insertions(+), 1581 deletions(-) create mode 100644 nested/src/char_editor.rs create mode 100644 nested/src/color.rs delete mode 100644 nested/src/list/editor_view.rs create mode 100644 nested/src/list/nav.rs create mode 100644 nested/src/list/pty_editor.rs create mode 100644 nested/src/list/segment.rs delete mode 100644 nested/src/list/sexpr.rs create mode 100644 nested/src/modulo.rs delete mode 100644 nested/src/string_editor.rs create mode 100644 shell/src/command.rs diff --git a/nested/src/char_editor.rs b/nested/src/char_editor.rs new file mode 100644 index 0000000..4cd771e --- /dev/null +++ b/nested/src/char_editor.rs @@ -0,0 +1,68 @@ +use { + crate::{ + core::{OuterViewPort, ViewPort}, + list::{ListEditor}, + sequence::{SequenceView, SequenceViewExt}, + singleton::{SingletonBuffer, SingletonView}, + terminal::{ + TerminalAtom, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, + TerminalView, + }, + tree_nav::{TerminalTreeEditor, TreeCursor, TreeNav, TreeNavResult}, + }, + std::sync::Arc, + std::sync::RwLock, + termion::event::{Event, Key}, + cgmath::Vector2 +}; + +pub struct CharEditor { + data: SingletonBuffer> +} + +impl CharEditor { + pub fn new() -> Self { + CharEditor { + data: SingletonBuffer::new(None) + } + } + + pub fn get_port(&self) -> OuterViewPort>> { + self.data.get_port() + } +} + +impl TreeNav for CharEditor {} +impl TerminalEditor for CharEditor { + fn get_term_view(&self) -> OuterViewPort { + self.data + .get_port() + .map(move |c| { + TerminalAtom::new( + c.unwrap_or('?'), + TerminalStyle::fg_color((100, 140, 100)), + ) + }) + .to_grid() + } + + fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { + match event { + TerminalEvent::Input(Event::Key(Key::Char('\n'))) => TerminalEditorResult::Exit, + TerminalEvent::Input(Event::Key(Key::Char(c))) => { + self.data.set(Some(*c)); + TerminalEditorResult::Exit + } + TerminalEvent::Input(Event::Key(Key::Backspace)) + | TerminalEvent::Input(Event::Key(Key::Delete)) => { + self.data.set(None); + TerminalEditorResult::Exit + } + _ => TerminalEditorResult::Exit, + } + } +} + +impl TerminalTreeEditor for CharEditor {} + + diff --git a/nested/src/color.rs b/nested/src/color.rs new file mode 100644 index 0000000..e592626 --- /dev/null +++ b/nested/src/color.rs @@ -0,0 +1,25 @@ +use { + crate::terminal::TerminalStyle, +}; + +pub fn bg_style_from_depth(depth: usize) -> TerminalStyle { + if depth == 0 { + TerminalStyle::default() + } else { + TerminalStyle::bg_color(( + (30.0 / ( 0.90*depth as f64 )) as u8, + (30.0 / ( 0.93*depth as f64 )) as u8, + (50.0 / ( 0.95*depth as f64 )) as u8 + )) + } +} + +pub fn fg_style_from_depth(depth: usize) -> TerminalStyle { + match depth % 3 { + 0 => TerminalStyle::fg_color((200, 200, 80)), + 1 => TerminalStyle::fg_color((80, 200, 200)), + 2 => TerminalStyle::fg_color((150, 150, 200)), + _ => TerminalStyle::default() + } +} + diff --git a/nested/src/index/buffer.rs b/nested/src/index/buffer.rs index bf86073..e6e53d1 100644 --- a/nested/src/index/buffer.rs +++ b/nested/src/index/buffer.rs @@ -1,6 +1,6 @@ use { crate::{ - core::{InnerViewPort, ViewPort, Observer, ObserverBroadcast, View}, + core::{InnerViewPort, OuterViewPort, ViewPort, Observer, ObserverBroadcast, View}, index::{IndexArea, IndexView}, }, std::sync::RwLock, @@ -64,6 +64,10 @@ where IndexBuffer::with_port(ViewPort::new().into_inner()) } + pub fn get_port(&self) -> OuterViewPort> { + self.port.0.outer() + } + pub fn insert(&mut self, key: Key, item: Item) { self.data.write().unwrap().insert(key.clone(), item); self.port.notify(&IndexArea::Set(vec![key])); diff --git a/nested/src/integer/editor.rs b/nested/src/integer/editor.rs index 1c1fd17..a2c8231 100644 --- a/nested/src/integer/editor.rs +++ b/nested/src/integer/editor.rs @@ -127,6 +127,9 @@ impl TreeNav for PosIntEditor { fn get_cursor(&self) -> TreeCursor { self.digits_editor.get_cursor() } + fn get_cursor_warp(&self) -> TreeCursor { + self.digits_editor.get_cursor_warp() + } fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { self.digits_editor.goto(cur) } diff --git a/nested/src/lib.rs b/nested/src/lib.rs index bda3e80..9addcac 100644 --- a/nested/src/lib.rs +++ b/nested/src/lib.rs @@ -1,24 +1,34 @@ #![feature(trait_alias)] +// general pub mod core; pub mod projection; +pub mod bimap; +pub mod modulo; +pub use modulo::modulo; -pub mod grid; +// semantics +pub mod singleton; +pub mod sequence; pub mod index; -pub mod integer; +pub mod grid; + +// implementation +pub mod vec; + +// editors +pub mod tree_nav; pub mod product; pub mod list; -pub mod sequence; -pub mod singleton; -pub mod terminal; -pub mod vec; + +// high-level types +pub mod char_editor; +pub mod integer; pub mod make_editor; -pub mod tree_nav; - -pub mod string_editor; - -pub mod bimap; +// display +pub mod color; +pub mod terminal; pub fn magic_header() { eprintln!("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>"); diff --git a/nested/src/list/cursor.rs b/nested/src/list/cursor.rs index b2c54ce..9f8d0d9 100644 --- a/nested/src/list/cursor.rs +++ b/nested/src/list/cursor.rs @@ -1,33 +1,34 @@ #[derive(Clone, Copy, Eq, PartialEq)] pub enum ListCursorMode { Insert, - Select, - Modify, + Select } #[derive(Clone, Copy, Eq, PartialEq)] pub struct ListCursor { pub mode: ListCursorMode, - pub idx: Option, + pub idx: Option, +} + +impl ListCursor { + pub fn home() -> Self { + ListCursor { + mode: ListCursorMode::Insert, + idx: Some(0) + } + } + + pub fn none() -> Self { + ListCursor { + mode: ListCursorMode::Insert, + idx: None, + } + } } impl Default for ListCursor { fn default() -> Self { - ListCursor { - mode: ListCursorMode::Select, - idx: None, - } + ListCursor::none() } } -/* -pub trait ListNav { - fn pxev(&mut self) -> ListNavResult; - fn nexd(&mut self) -> ListNavResult; - fn pua(&mut self) -> ListNavResult; - fn end(&mut self) -> ListNavResult; - - fn set_cursor(&mut self, new_cursor: Option) -> ListNavResult; - fn get_cursor(&self) -> Option; -} -*/ diff --git a/nested/src/list/editor.rs b/nested/src/list/editor.rs index 849f1a1..39fd85c 100644 --- a/nested/src/list/editor.rs +++ b/nested/src/list/editor.rs @@ -2,10 +2,11 @@ use { crate::{ core::{OuterViewPort, ViewPort}, list::{ - editor_view::{ListEditorView, ListEditorViewSegment}, - ListCursor, ListCursorMode, ListDecoration, SExprView, + ListCursor, ListCursorMode, + ListSegment, ListSegmentSequence, + segment::PTYSegment }, - sequence::SequenceView, + sequence::{SequenceView}, singleton::{SingletonBuffer, SingletonView}, terminal::{ make_label, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, @@ -13,696 +14,62 @@ use { }, tree_nav::{TerminalTreeEditor, TreeCursor, TreeNav, TreeNavResult}, vec::VecBuffer, + color::{bg_style_from_depth, fg_style_from_depth} }, std::sync::{Arc, RwLock}, termion::event::{Event, Key}, }; -#[derive(Clone, Copy)] -pub enum ListEditorStyle { - HorizontalSexpr, - VerticalSexpr, - Tuple(usize), - Path, - String, - Clist, - Hex, - Plain, +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +pub struct ListEditor +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static +{ + pub(super) cursor: SingletonBuffer, + pub(super) data: VecBuffer>>, + pub(super) make_item_editor: Box Arc> + Send + Sync>, + + pub(super) depth: usize, + pub(super) cur_dist: Arc>, } -pub struct ListEditor -where - ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, - FnMakeItemEditor: Fn() -> Arc>, +impl ListEditor +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static { - cursor: SingletonBuffer, - data: VecBuffer>>, - - cursor_port: ViewPort>, - data_port: ViewPort>>>>, - - make_item_editor: FnMakeItemEditor, - - style: ListEditorStyle, - _level: usize, - cur_dist: Arc>, -} - -impl TreeNav for ListEditor -where - ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, - FnMakeItemEditor: Fn() -> Arc>, -{ - fn get_cursor(&self) -> TreeCursor { - let cur = self.cursor.get(); - match cur.mode { - ListCursorMode::Insert | ListCursorMode::Select => TreeCursor { - leaf_mode: cur.mode, - tree_addr: if let Some(i) = cur.idx { - vec![i] - } else { - vec![] - }, - }, - ListCursorMode::Modify => { - if let Some(i) = cur.idx { - if i < self.data.len() { - let mut sub_cur = self.data.get(i).read().unwrap().get_cursor(); - sub_cur.tree_addr.insert(0, i); - return sub_cur; - } - } - TreeCursor { - leaf_mode: cur.mode, - tree_addr: vec![], - } - } + pub fn new(make_item_editor: impl Into Arc> + Send + Sync>>, depth: usize) -> Self { + ListEditor { + cursor: SingletonBuffer::new(ListCursor::default()), + data: VecBuffer::>>::new(), + make_item_editor: make_item_editor.into(), + depth, + cur_dist: Arc::new(RwLock::new(0)), } } - fn goto(&mut self, new_cur: TreeCursor) -> TreeNavResult { - let old_cur = self.cursor.get(); - if old_cur.mode == ListCursorMode::Modify { - if let Some(i) = old_cur.idx { - let ce = self.data.get_mut(i); - let mut cur_edit = ce.write().unwrap(); - cur_edit.goto(TreeCursor::default()); - } - } - - if new_cur.tree_addr.len() == 1 { - self.cursor.set(ListCursor { - mode: new_cur.leaf_mode, - idx: Some(new_cur.tree_addr[0]), - }); - TreeNavResult::Continue - } else if new_cur.tree_addr.len() > 1 && new_cur.tree_addr[0] < self.data.len() { - self.cursor.set(ListCursor { - mode: ListCursorMode::Modify, - idx: Some(new_cur.tree_addr[0]), - }); - - let ne = self.data.get_mut(new_cur.tree_addr[0]); - let mut nxt_edit = ne.write().unwrap(); - - nxt_edit.goto(TreeCursor { - leaf_mode: new_cur.leaf_mode, - tree_addr: new_cur.tree_addr[1..].iter().cloned().collect(), - }); - - TreeNavResult::Continue - } else { - self.cursor.set(ListCursor { - mode: new_cur.leaf_mode, - idx: None, - }); - TreeNavResult::Continue - } - } - - fn goto_end(&mut self) -> TreeNavResult { - let mut cur = self.cursor.get(); - let i = cur.idx.unwrap_or(0); - - if self.data.len() == 0 && cur.idx.is_none() { - self.cursor.set(ListCursor { - mode: ListCursorMode::Insert, - idx: Some(0), - }); - return TreeNavResult::Continue; - } - - if i < self.data.len() { - match cur.mode { - ListCursorMode::Insert => { - if i < self.data.len() || cur.idx.is_none() { - cur.idx = Some(self.data.len()); - self.cursor.set(cur); - TreeNavResult::Continue - } else { - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit - } - } - ListCursorMode::Select => { - if self.data.len() == 0 && cur.idx.is_none() { - self.cursor.set(ListCursor { - mode: ListCursorMode::Insert, - idx: Some(0), - }); - return TreeNavResult::Continue; - } - - if i + 1 < self.data.len() || cur.idx.is_none() { - cur.idx = Some(self.data.len() - 1); - self.cursor.set(cur); - TreeNavResult::Continue - } else { - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit - } - } - ListCursorMode::Modify => { - let ce = self.data.get_mut(i); - let mut cur_edit = ce.write().unwrap(); - let cur_mode = cur_edit.get_cursor().leaf_mode; - let depth = cur_edit.get_cursor().tree_addr.len(); - match cur_edit.goto_end() { - TreeNavResult::Continue => TreeNavResult::Continue, - TreeNavResult::Exit => { - drop(cur_edit); - - self.up(); - - if i + 1 < self.data.len() { - self.set_mode(ListCursorMode::Select); - self.nexd(); - - for _x in 1..depth { - self.dn(); - self.goto_home(); - } - - self.set_leaf_mode(cur_mode); - self.dn(); - self.goto_end(); - - return TreeNavResult::Continue; - } - - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit - } - } - } - } - } else { - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit - } - } - - fn goto_home(&mut self) -> TreeNavResult { - let mut cur = self.cursor.get(); - if self.data.len() == 0 && cur.idx.is_none() { - self.cursor.set(ListCursor { - mode: ListCursorMode::Insert, - idx: Some(0), - }); - return TreeNavResult::Continue; - } - - match cur.mode { - ListCursorMode::Insert | ListCursorMode::Select => { - if cur.idx != Some(0) { - self.cursor.set(ListCursor { - mode: if self.data.len() == 0 { - ListCursorMode::Insert - } else { - cur.mode - }, - idx: Some(0), - }); - TreeNavResult::Continue - } else { - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit - } - } - ListCursorMode::Modify => { - if let Some(ce) = self.get_item() { - let mut cur_edit = ce.write().unwrap(); - let cur_mode = cur_edit.get_cursor().leaf_mode; - let depth = cur_edit.get_cursor().tree_addr.len(); - - match cur_edit.goto_home() { - TreeNavResult::Exit => { - drop(cur_edit); - - if let Some(i) = cur.idx { - if i > 0 { - self.set_mode(ListCursorMode::Select); - self.pxev(); - - for _x in 1..depth { - self.dn(); - self.goto_end(); - } - - self.dn(); - self.set_leaf_mode(cur_mode); - //self.goto_home(); - return TreeNavResult::Continue; - } - } - } - TreeNavResult::Continue => { return TreeNavResult::Continue; } - }; - } - - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit - } - } - } - - fn up(&mut self) -> TreeNavResult { - let cur = self.cursor.get(); - if cur.mode == ListCursorMode::Modify { - if let Some(i) = cur.idx { - let ce = self.data.get_mut(i); - let mut cur_edit = ce.write().unwrap(); - let mode = cur_edit.get_cursor().leaf_mode; - - match cur_edit.up() { - TreeNavResult::Exit => { - self.set_mode(mode); - } - TreeNavResult::Continue => {} - } - - TreeNavResult::Continue - } else { - TreeNavResult::Exit - } - } else { - self.cursor.set(ListCursor { - mode: cur.mode, - idx: None, - }); - TreeNavResult::Exit - } - } - - fn dn(&mut self) -> TreeNavResult { - let mut cur = self.cursor.get(); - - if cur.idx.is_none() { - self.goto_home() - } else { - match cur.mode { - ListCursorMode::Insert | ListCursorMode::Select => { - if let Some(i) = cur.idx { - if i < self.data.len() { - self.set_mode(ListCursorMode::Modify); - self.data.get_mut(i).write().unwrap().goto(TreeCursor { - leaf_mode: cur.mode, - tree_addr: vec![], - }); - self.data.get_mut(i).write().unwrap().dn(); - *self.cur_dist.write().unwrap() += 1; - } - } - TreeNavResult::Continue - } - ListCursorMode::Modify => self.get_item().unwrap().write().unwrap().dn(), - } - } - } - - fn pxev(&mut self) -> TreeNavResult { - let mut cur = self.cursor.get(); - if let Some(i) = cur.idx { - match cur.mode { - ListCursorMode::Insert | ListCursorMode::Select => { - if i > 0 { - cur.idx = Some(i - 1); - self.cursor.set(cur); - TreeNavResult::Continue - } else { - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit - } - } - ListCursorMode::Modify => { - let ce = self.get_item().unwrap(); - let mut cur_edit = ce.write().unwrap(); - - let cur_mode = cur_edit.get_cursor().leaf_mode; - let depth = cur_edit.get_cursor().tree_addr.len(); - - match cur_edit.pxev() { - TreeNavResult::Exit => { - drop(cur_edit); - self.up(); - - if i > 0 { - self.set_mode(ListCursorMode::Select); - self.pxev(); - - for _x in 1..depth { - self.dn(); - self.goto_end(); - } - - self.set_leaf_mode(cur_mode); - self.dn(); - self.goto_end(); - TreeNavResult::Continue - } else { - TreeNavResult::Exit - } - } - TreeNavResult::Continue => TreeNavResult::Continue, - } - } - } - } else { - TreeNavResult::Exit - } - } - - fn nexd(&mut self) -> TreeNavResult { - let mut cur = self.cursor.get(); - if let Some(i) = cur.idx { - match cur.mode { - ListCursorMode::Insert => { - if i < self.data.len() { - cur.idx = Some(i + 1); - self.cursor.set(cur); - TreeNavResult::Continue - } else { - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit - } - } - ListCursorMode::Select => { - if i + 1 < self.data.len() { - cur.idx = Some(i + 1); - self.cursor.set(cur); - TreeNavResult::Continue - } else { - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit - } - } - ListCursorMode::Modify => { - let ce = self.data.get(i); - let mut cur_edit = ce.write().unwrap(); - - let depth = cur_edit.get_cursor().tree_addr.len(); - let cur_mode = cur_edit.get_cursor().leaf_mode; - - match cur_edit.nexd() { - TreeNavResult::Exit => { - drop(cur_edit); - drop(ce); - //self.up(); - - if i + 1 < self.data.len() { - self.set_mode(ListCursorMode::Select); - self.nexd(); - - for _x in 1..depth { - self.dn(); - } - - self.set_leaf_mode(cur_mode); - self.dn(); - - TreeNavResult::Continue - } else { - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit - } - } - TreeNavResult::Continue => TreeNavResult::Continue, - } - } - } - } else { - TreeNavResult::Exit - } - } -} - -impl TerminalEditor for ListEditor -where - ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, - FnMakeItemEditor: Fn() -> Arc>, -{ - fn get_term_view(&self) -> OuterViewPort { - match self.style { - ListEditorStyle::HorizontalSexpr => self.horizontal_sexpr_view(), - ListEditorStyle::VerticalSexpr => self.vertical_sexpr_view(), - ListEditorStyle::Tuple(depth) => self.tuple_view(depth), - ListEditorStyle::Path => self.path_view(), - ListEditorStyle::String => self.string_view(), - ListEditorStyle::Clist => self.clist_view(), - ListEditorStyle::Hex => self.hex_view(), - ListEditorStyle::Plain => self.plain_view(), - } - } - - fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { - let mut cur = self.cursor.get(); - if let Some(idx) = cur.idx { - match cur.mode { - ListCursorMode::Insert => match event { - TerminalEvent::Input(Event::Key(Key::Backspace)) => { - if idx > 0 && idx <= self.data.len() { - cur.idx = Some(idx - 1); - self.cursor.set(cur); - self.data.remove(idx - 1); - TerminalEditorResult::Continue - } else { - TerminalEditorResult::Exit - } - } - TerminalEvent::Input(Event::Key(Key::Delete)) => { - if idx < self.data.len() { - self.data.remove(idx); - TerminalEditorResult::Continue - } else { - TerminalEditorResult::Exit - } - } - TerminalEvent::Input(Event::Key(Key::Char('\t'))) - | TerminalEvent::Input(Event::Key(Key::Insert)) => { - self.set_mode(ListCursorMode::Select); - TerminalEditorResult::Continue - } - _ => { - let new_edit = (self.make_item_editor)(); - self.data.insert(idx, new_edit.clone()); - self.set_mode(ListCursorMode::Modify); - let mut ne = new_edit.write().unwrap(); - - match ne.handle_terminal_event(event) { - TerminalEditorResult::Exit => { - self.cursor.set(ListCursor { - mode: ListCursorMode::Insert, - idx: Some(idx + 1), - }); - } - _ => {} - } - TerminalEditorResult::Continue - } - }, - ListCursorMode::Select => match event { - TerminalEvent::Input(Event::Key(Key::Char('\t'))) - | TerminalEvent::Input(Event::Key(Key::Insert)) => { - self.set_mode(ListCursorMode::Insert); - TerminalEditorResult::Continue - } - TerminalEvent::Input(Event::Key(Key::Delete)) => { - self.data.remove(idx); - - if self.data.len() == 0 { - self.cursor.set(ListCursor::default()); - } else if idx == self.data.len() { - self.cursor.set(ListCursor { - mode: ListCursorMode::Select, - idx: Some(idx - 1), - }); - } - TerminalEditorResult::Continue - } - _ => TerminalEditorResult::Continue, - }, - ListCursorMode::Modify => { - let ce = self.data.get_mut(idx); - let mut cur_edit = ce.write().unwrap(); - - match cur_edit.handle_terminal_event(event) { - TerminalEditorResult::Exit => { - cur_edit.up(); - drop(cur_edit); - drop(ce); - - match event { - TerminalEvent::Input(Event::Key(Key::Backspace)) => { - // todo: join instead of remove - self.cursor.set(ListCursor { - mode: ListCursorMode::Insert, - idx: Some(idx), - }); - - self.data.remove(idx); - } - _ => { - // todo: split - - self.cursor.set(ListCursor { - mode: ListCursorMode::Insert, - idx: Some(idx + 1), - }); - } - } - } - TerminalEditorResult::Continue => {} - } - - TerminalEditorResult::Continue - } - } - } else { - TerminalEditorResult::Continue - } - } -} - -impl TerminalTreeEditor for ListEditor -where - ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, - FnMakeItemEditor: Fn() -> Arc> + Send + Sync, -{} - -impl ListEditor -where - ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, - FnMakeItemEditor: Fn() -> Arc>, -{ pub fn get_seg_seq_view( &self, ) -> OuterViewPort>> { - let segment_view_port = ViewPort::>::new(); - ListEditorView::new( - self.cursor_port.outer(), - self.data_port - .outer() - .to_sequence() - .map(|ed| ed.read().unwrap().get_term_view()), + let segment_view_port = ViewPort::>>::new(); + ListSegmentSequence::new( + self.get_cursor_port(), + self.get_data_port(), segment_view_port.inner(), + self.depth ); - - segment_view_port.into_outer().map(move |segment| { - let cursor_col = (90, 60, 200); - match segment { - ListEditorViewSegment::InsertCursor => { - make_label("|").map_item(move |_pt, atom| { - atom.add_style_back(TerminalStyle::fg_color(cursor_col)) - .add_style_back(TerminalStyle::bold(true)) - }) - } - ListEditorViewSegment::Select(sub_view) => sub_view.map_item(move |_pt, atom| { - let old_col = atom.style.bg_color.unwrap_or(cursor_col); - atom.add_style_front(TerminalStyle::bg_color(( - (old_col.0 as f32 * 0.4) as u8, - (old_col.1 as f32 * 0.4) as u8, - (old_col.2 as f32 * 0.4) as u8, - ))) - }), - ListEditorViewSegment::Modify(sub_view) => { - sub_view.clone().map_item( - move |_pt, atom| { - let old_col = atom.style.bg_color.unwrap_or(cursor_col); - atom.add_style_front(TerminalStyle::bg_color(( - (old_col.0 as f32 * 0.4) as u8, - (old_col.1 as f32 * 0.4) as u8, - (old_col.2 as f32 * 0.4) as u8, - ))) - }, //.add_style_back(TerminalStyle::bold(true)) - ) - } - ListEditorViewSegment::View(sub_view) => sub_view.clone(), - } - }) - } - - pub fn horizontal_sexpr_view(&self) -> OuterViewPort { - self.get_seg_seq_view().horizontal_sexpr_view(1) - } - - pub fn vertical_sexpr_view(&self) -> OuterViewPort { - self.get_seg_seq_view().vertical_sexpr_view(0) - } - - pub fn path_view(&self) -> OuterViewPort { - self.get_seg_seq_view() - .decorate("<", ">", "/", 0) - .to_grid_horizontal() - .flatten() - } - - pub fn string_view(&self) -> OuterViewPort { - self.get_seg_seq_view() - .decorate("\"", "\"", "", 1) - .to_grid_horizontal() - .flatten() - } - - pub fn clist_view(&self) -> OuterViewPort { - self.get_seg_seq_view() - .decorate("{", "}", ", ", 1) - .to_grid_horizontal() - .flatten() - } - - pub fn tuple_view(&self, depth: usize) -> OuterViewPort { - self.get_seg_seq_view() - .decorate("(", ")", ", ", depth) - .to_grid_horizontal() - .flatten() - } - - pub fn hex_view(&self) -> OuterViewPort { - self.get_seg_seq_view() - .decorate("0x", "", "", 0) - .to_grid_horizontal() - .flatten() - } - - pub fn plain_view(&self) -> OuterViewPort { - self.get_seg_seq_view().to_grid_horizontal().flatten() - } - - pub fn new(make_item_editor: FnMakeItemEditor, style: ListEditorStyle) -> Self { - let cursor_port = ViewPort::new(); - let data_port = ViewPort::new(); - let cursor = SingletonBuffer::new(ListCursor::default(), cursor_port.inner()); - let data = VecBuffer::>>::new(data_port.inner()); - - let mut le = ListEditor { - data, - data_port, - cursor, - cursor_port, - - style, - make_item_editor, - _level: 0, - cur_dist: Arc::new(RwLock::new(0)), - }; - le.set_style(style); - le - } - - pub fn set_style(&mut self, style: ListEditorStyle) { - self.style = style; + segment_view_port.into_outer().map(move |segment| segment.pty_view()) } pub fn get_data_port(&self) -> OuterViewPort>>> { - self.data_port.outer().to_sequence() + self.data.get_port().to_sequence() } - pub fn get_list_cursor_port(&self) -> OuterViewPort> { - self.cursor_port.outer() + pub fn get_cursor_port(&self) -> OuterViewPort> { + self.cursor.get_port() } pub fn get_item(&self) -> Option>> { if let Some(idx) = self.cursor.get().idx { + let idx = crate::modulo(idx as isize, self.data.len() as isize) as usize; if idx < self.data.len() { Some(self.data.get(idx)) } else { @@ -716,50 +83,5 @@ where pub fn clear(&mut self) { self.data.clear(); } - - fn set_idx(&mut self, idx: isize) { - let cur = self.cursor.get(); - let mode = cur.mode; - - if idx < 0 { - self.cursor.set(ListCursor { - mode, - idx: Some((self.data.len() as isize + idx) as usize), - }); - } else { - self.cursor.set(ListCursor { - mode, - idx: Some(idx as usize), - }); - } - } - - fn set_mode(&mut self, mode: ListCursorMode) { - let mut cur = self.cursor.get(); - - if cur.mode == ListCursorMode::Insert && mode != ListCursorMode::Insert { - if let Some(idx) = cur.idx { - if idx == self.data.len() && idx > 0 { - cur.idx = Some(idx - 1); - } - } - } - - cur.mode = mode; - - self.cursor.set(cur); - } -} - -impl ListEditor -where - ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, - FnMakeItemEditor: Fn() -> Arc>, -{ - fn set_leaf_mode(&mut self, mode: ListCursorMode) { - let mut c = self.get_cursor(); - c.leaf_mode = mode; - self.goto(c); - } } diff --git a/nested/src/list/editor_view.rs b/nested/src/list/editor_view.rs deleted file mode 100644 index 0e0c724..0000000 --- a/nested/src/list/editor_view.rs +++ /dev/null @@ -1,122 +0,0 @@ -use { - crate::{ - core::{InnerViewPort, Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View}, - list::{ListCursor, ListCursorMode}, - projection::ProjectionHelper, - sequence::SequenceView, - singleton::SingletonView, - terminal::TerminalView, - }, - std::sync::Arc, - std::sync::RwLock, -}; - -pub enum ListEditorViewSegment { - InsertCursor, - View(OuterViewPort), - Select(OuterViewPort), - Modify(OuterViewPort), -} - -pub struct ListEditorView { - cursor: Arc>, - data: Arc>>, - cur_cursor: ListCursor, - - cast: Arc>>>, - proj_helper: ProjectionHelper, -} - -impl View for ListEditorView { - type Msg = usize; -} - -impl SequenceView for ListEditorView { - type Item = ListEditorViewSegment; - - fn len(&self) -> Option { - match self.cursor.get().mode { - ListCursorMode::Insert => { - Some(self.data.len()? + if self.cur_cursor.idx.is_some() { 1 } else { 0 }) - } - _ => self.data.len(), - } - } - - fn get(&self, idx: &usize) -> Option { - Some(if let Some(cur) = self.cur_cursor.idx { - match self.cur_cursor.mode { - ListCursorMode::Select => { - if *idx == cur { - ListEditorViewSegment::Select(self.data.get(&idx)?) - } else { - ListEditorViewSegment::View(self.data.get(&idx)?) - } - } - ListCursorMode::Insert => { - if *idx < cur { - ListEditorViewSegment::View(self.data.get(&idx)?) - } else if *idx == cur { - ListEditorViewSegment::InsertCursor - } else { - ListEditorViewSegment::View(self.data.get(&(idx - 1))?) - } - } - ListCursorMode::Modify => { - if *idx == cur { - ListEditorViewSegment::Modify(self.data.get(&idx)?) - } else { - ListEditorViewSegment::View(self.data.get(&idx)?) - } - } - } - } else { - ListEditorViewSegment::View(self.data.get(&idx)?) - }) - } -} - -impl ListEditorView { - pub fn new( - cursor_port: OuterViewPort>, - data_port: OuterViewPort>>, - out_port: InnerViewPort>, - ) -> Arc> { - let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone()); - let proj = Arc::new(RwLock::new(ListEditorView { - cur_cursor: ListCursor::default(), - cursor: proj_helper.new_singleton_arg(0, cursor_port, |s: &mut Self, _msg| { - let _old_cursor = s.cur_cursor; - let new_cursor = s.cursor.get(); - s.cur_cursor = new_cursor; - - s.cast.notify_each(0..=s.data.len().unwrap_or(0) + 1); - }), - data: proj_helper.new_sequence_arg(1, data_port, |s: &mut Self, idx| { - if let Some(cur_idx) = s.cur_cursor.idx { - match s.cur_cursor.mode { - ListCursorMode::Insert => { - if *idx < cur_idx { - s.cast.notify(idx); - } else { - s.cast.notify(&(*idx + 1)); - } - } - _ => { - s.cast.notify(idx); - } - } - } else { - s.cast.notify(idx); - } - }), - cast: out_port.get_broadcast(), - proj_helper, - })); - - proj.write().unwrap().proj_helper.set_proj(&proj); - out_port.set_view(Some(proj.clone())); - - proj - } -} diff --git a/nested/src/list/mod.rs b/nested/src/list/mod.rs index 5af6bfe..fd5a86f 100644 --- a/nested/src/list/mod.rs +++ b/nested/src/list/mod.rs @@ -1,8 +1,12 @@ + pub mod cursor; +pub mod segment; pub mod editor; -pub mod editor_view; -pub mod sexpr; +pub mod nav; +pub mod pty_editor; pub use cursor::{ListCursor, ListCursorMode}; -pub use editor::{ListEditor, ListEditorStyle}; -pub use sexpr::{ListDecoration, SExprView}; +pub use segment::{ListSegment, ListSegmentSequence}; +pub use editor::ListEditor; +pub use pty_editor::PTYListEditor; + diff --git a/nested/src/list/nav.rs b/nested/src/list/nav.rs new file mode 100644 index 0000000..2ae0c93 --- /dev/null +++ b/nested/src/list/nav.rs @@ -0,0 +1,240 @@ +use { + crate::{ + core::{OuterViewPort, ViewPort}, + list::{ + ListCursor, ListCursorMode, + ListSegment, ListSegmentSequence, + ListEditor + }, + sequence::SequenceView, + singleton::{SingletonBuffer, SingletonView}, + terminal::{ + make_label, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, + TerminalView, + }, + tree_nav::{TerminalTreeEditor, TreeCursor, TreeNav, TreeNavResult}, + vec::VecBuffer, + color::{bg_style_from_depth, fg_style_from_depth} + }, + std::sync::{Arc, RwLock}, + termion::event::{Event, Key}, + cgmath::Vector2 +}; + +impl TreeNav for ListEditor +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static +{ + fn get_cursor_warp(&self) -> TreeCursor { + let cur = self.cursor.get(); + match cur.mode { + ListCursorMode::Insert => TreeCursor { + leaf_mode: cur.mode, + tree_addr: if let Some(i) = cur.idx { + vec![ + i - self.data.len() as isize - 1 + ] + } else { + vec![] + }, + }, + ListCursorMode::Select => { + if let Some(i) = cur.idx { + if i < self.data.len() as isize { + let mut sub_cur = self.data.get(i as usize).read().unwrap().get_cursor_warp(); + sub_cur.tree_addr.insert(0, i as isize - self.data.len() as isize); + return sub_cur; + } + } + TreeCursor { + leaf_mode: cur.mode, + tree_addr: vec![], + } + } + } + } + + fn get_cursor(&self) -> TreeCursor { + let cur = self.cursor.get(); + match cur.mode { + ListCursorMode::Insert => TreeCursor { + leaf_mode: cur.mode, + tree_addr: if let Some(i) = cur.idx { + vec![i] + } else { + vec![] + }, + }, + ListCursorMode::Select => { + if let Some(i) = cur.idx { + if i < self.data.len() as isize { + let mut sub_cur = self.data.get(i as usize).read().unwrap().get_cursor(); + sub_cur.tree_addr.insert(0, i as isize); + return sub_cur; + } + } + TreeCursor { + leaf_mode: cur.mode, + tree_addr: vec![], + } + } + } + } + + fn goto(&mut self, new_cur: TreeCursor) -> TreeNavResult { + let old_cur = self.cursor.get(); + if let Some(i) = old_cur.idx { + if i < self.data.len() as isize { + let ce = self.data.get_mut(i as usize); + let mut cur_edit = ce.write().unwrap(); + cur_edit.goto(TreeCursor::none()); + } + } + + match new_cur.tree_addr.len() { + 0 => { + self.cursor.set(ListCursor { + mode: new_cur.leaf_mode, + idx: None, + }); + TreeNavResult::Continue + } + 1 => { + self.cursor.set(ListCursor { + mode: new_cur.leaf_mode, + idx: Some(crate::modulo(new_cur.tree_addr[0], if new_cur.leaf_mode == ListCursorMode::Insert { 1 } else { 0 } + self.data.len() as isize)), + }); + TreeNavResult::Continue + } + _ => { + let idx = crate::modulo(new_cur.tree_addr[0], self.data.len() as isize); + + self.cursor.set(ListCursor { + mode: ListCursorMode::Select, + idx: Some(idx), + }); + + let item = self.data.get_mut(idx as usize); + let mut item_edit = item.write().unwrap(); + + item_edit.goto(TreeCursor { + leaf_mode: new_cur.leaf_mode, + tree_addr: new_cur.tree_addr[1..].iter().cloned().collect(), + }); + + TreeNavResult::Continue + } + } + } + + fn goby(&mut self, direction: Vector2) -> TreeNavResult { + let mut cur = self.get_cursor(); + match cur.tree_addr.len() { + 0 => { + + if direction.y < 0 { + // up + TreeNavResult::Exit + } else if direction.y > 0 { + // dn + self.cursor.set(ListCursor::home()); + self.goby(Vector2::new(direction.x, direction.y-1)); + TreeNavResult::Continue + } else { + TreeNavResult::Continue + } + }, + + 1 => { + if direction.y > 0 { + // dn + if cur.tree_addr[0] < self.data.len() as isize { + let item = self.data.get_mut(cur.tree_addr[0] as usize); + let mut item_edit = item.write().unwrap(); + + if item_edit.goby(Vector2::new(direction.x, direction.y)) == TreeNavResult::Continue { + self.cursor.set(ListCursor { + mode: ListCursorMode::Select, + idx: Some(cur.tree_addr[0]) + }) + } + } + + TreeNavResult::Continue + + } else if direction.y < 0 { + // up + + self.cursor.set(ListCursor::none()); + TreeNavResult::Exit + } else { + // horizontal + + if (cur.tree_addr[0]+direction.x >= 0) && + (cur.tree_addr[0]+direction.x < + self.data.len() as isize + + if cur.leaf_mode == ListCursorMode::Insert { 1 } else { 0 }) + { + self.cursor.set(ListCursor { + mode: cur.leaf_mode, + idx: Some(cur.tree_addr[0] + direction.x) + }); + TreeNavResult::Continue + } else { + self.cursor.set(ListCursor::none()); + TreeNavResult::Exit + } + } + }, + depth => { + // nested + + let item = self.data.get_mut(cur.tree_addr[0] as usize); + let mut item_edit = item.write().unwrap(); + + match item_edit.goby(direction) { + TreeNavResult::Exit => { + if direction.y < 0 { + // up + self.cursor.set(ListCursor { + mode: cur.leaf_mode, + idx: Some(cur.tree_addr[0]) + }); + + TreeNavResult::Continue + } else if direction.y > 0 { + // dn + + TreeNavResult::Continue + } else { + // horizontal + drop(item_edit); + + if (cur.tree_addr[0]+direction.x >= 0) && + (cur.tree_addr[0]+direction.x < self.data.len() as isize) + { + if direction.x < 0 { + cur.tree_addr[0] -= 1; + for i in 1..depth { + cur.tree_addr[i] = -1; + } + } else { + cur.tree_addr[0] += 1; + for i in 1..depth { + cur.tree_addr[i] = 0; + } + } + + self.goto(cur) + } else { + self.cursor.set(ListCursor::none()); + TreeNavResult::Exit + } + } + } + TreeNavResult::Continue => TreeNavResult::Continue + } + } + } + } +} + diff --git a/nested/src/list/pty_editor.rs b/nested/src/list/pty_editor.rs new file mode 100644 index 0000000..f3f0a8d --- /dev/null +++ b/nested/src/list/pty_editor.rs @@ -0,0 +1,208 @@ +use { + crate::{ + core::{OuterViewPort, ViewPort}, + list::{ + ListCursor, ListCursorMode, + ListSegment, ListSegmentSequence, + ListEditor + }, + sequence::{SequenceView, decorator::{SeqDecorStyle, PTYSeqDecorate}}, + singleton::{SingletonBuffer, SingletonView}, + terminal::{ + make_label, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, + TerminalView, + }, + tree_nav::{TerminalTreeEditor, TreeCursor, TreeNav, TreeNavResult}, + vec::VecBuffer, + color::{bg_style_from_depth, fg_style_from_depth} + }, + std::sync::{Arc, RwLock}, + termion::event::{Event, Key}, + cgmath::Vector2 +}; + +pub struct PTYListEditor +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static +{ + pub editor: ListEditor, + + style: SeqDecorStyle, + depth: usize, + + port: ViewPort +} + +impl PTYListEditor +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static +{ + pub fn new( + make_item_editor: Box Arc> + Send + Sync>, + style: SeqDecorStyle, + depth: usize + ) -> Self { + let port = ViewPort::new(); + PTYListEditor { + editor: ListEditor::new(make_item_editor, depth), + style, + depth, + port + } + } + + pub fn get_data_port(&self) -> OuterViewPort>>> { + self.editor.get_data_port() + } + + pub fn clear(&mut self) { + self.editor.clear(); + } + + pub fn get_item(&self) -> Option>> { + self.editor.get_item() + } + + pub fn set_depth(&mut self, depth: usize) { + self.depth = depth; + } + + pub fn set_style(&mut self, style: SeqDecorStyle) { + self.style = style; + } +} + +impl TerminalEditor for PTYListEditor +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static +{ + fn get_term_view(&self) -> OuterViewPort { + self.editor + .get_seg_seq_view() + .pty_decorate(self.style, self.depth) + } + + fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { + let mut cur = self.editor.cursor.get(); + if let Some(idx) = cur.idx { + match cur.mode { + ListCursorMode::Insert => match event { + TerminalEvent::Input(Event::Key(Key::Backspace)) => { + if idx > 0 && idx <= self.editor.data.len() as isize { + cur.idx = Some(idx as isize - 1); + self.editor.cursor.set(cur); + self.editor.data.remove(idx as usize - 1); + + if self.editor.data.len() > 0 { + TerminalEditorResult::Continue + } else { + TerminalEditorResult::Exit + } + } else { + TerminalEditorResult::Exit + } + } + TerminalEvent::Input(Event::Key(Key::Delete)) => { + if idx < self.editor.data.len() as isize { + self.editor.data.remove(idx as usize); + TerminalEditorResult::Continue + } else { + TerminalEditorResult::Exit + } + } + TerminalEvent::Input(Event::Key(Key::Char('\t'))) + | TerminalEvent::Input(Event::Key(Key::Insert)) => { + self.editor.set_leaf_mode(ListCursorMode::Select); + TerminalEditorResult::Continue + } + TerminalEvent::Input(Event::Key(Key::Char('\n'))) => { + self.editor.goto(TreeCursor::none()); + TerminalEditorResult::Exit + } + _ => { + let new_edit = (self.editor.make_item_editor)(); + self.editor.data.insert(idx as usize, new_edit.clone()); + self.editor.set_leaf_mode(ListCursorMode::Select); + + let mut ne = new_edit.write().unwrap(); + ne.goto(TreeCursor::home()); + + match ne.handle_terminal_event(event) { + TerminalEditorResult::Exit => { + self.editor.cursor.set(ListCursor { + mode: ListCursorMode::Insert, + idx: Some(idx as isize + 1), + }); + } + _ => {} + } + TerminalEditorResult::Continue + } + }, + ListCursorMode::Select => { + match event { + TerminalEvent::Input(Event::Key(Key::Char('\t'))) + | TerminalEvent::Input(Event::Key(Key::Insert)) => { + self.editor.set_leaf_mode(ListCursorMode::Insert); + TerminalEditorResult::Continue + } + ev => { + if let Some(e) = self.editor.get_item() { + match e.write().unwrap().handle_terminal_event(ev) { + TerminalEditorResult::Exit => { + + match ev { + TerminalEvent::Input(Event::Key(Key::Backspace)) => { + self.editor.data.remove(idx as usize); + self.editor.cursor.set(ListCursor { + mode: ListCursorMode::Insert, + idx: Some(idx as isize), + }); + } + _ => { + self.editor.cursor.set(ListCursor { + mode: ListCursorMode::Insert, + idx: Some(idx as isize + 1), + }); + } + } + } + TerminalEditorResult::Continue => { + + } + } + } + + TerminalEditorResult::Continue + } + } + } + } + } else { + TerminalEditorResult::Continue + } + } +} + +impl TreeNav for PTYListEditor +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static +{ + fn get_cursor_warp(&self) -> TreeCursor { + self.editor.get_cursor_warp() + } + + fn get_cursor(&self) -> TreeCursor { + self.editor.get_cursor() + } + + fn goby(&mut self, direction: Vector2) -> TreeNavResult { + self.editor.goby(direction) + } + + fn goto(&mut self, cursor: TreeCursor) -> TreeNavResult { + self.editor.goto(cursor) + } +} + + +impl TerminalTreeEditor for PTYListEditor +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static +{} + diff --git a/nested/src/list/segment.rs b/nested/src/list/segment.rs new file mode 100644 index 0000000..bd4a825 --- /dev/null +++ b/nested/src/list/segment.rs @@ -0,0 +1,176 @@ +use { + crate::{ + core::{InnerViewPort, Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View}, + list::{ListCursor, ListCursorMode}, + projection::ProjectionHelper, + sequence::SequenceView, + singleton::SingletonView, + terminal::{TerminalView, TerminalStyle, make_label}, + tree_nav::TerminalTreeEditor, + color::{bg_style_from_depth, fg_style_from_depth} + }, + std::sync::Arc, + std::sync::RwLock, +}; + +pub enum ListSegment +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static +{ + InsertCursor, + Item { + editor: Arc>, + depth: usize, + cur_dist: isize, + } +} + +pub trait PTYSegment { + fn pty_view(&self) -> OuterViewPort; +} + +impl PTYSegment for ListSegment +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static +{ + fn pty_view(&self) -> OuterViewPort { + match self { + ListSegment::InsertCursor => { + make_label("|") + .map_item(move |_pt, atom| { + atom.add_style_back(bg_style_from_depth(0)) + .add_style_back(TerminalStyle::bold(true)) + }) + } + ListSegment::Item{ editor, depth, cur_dist } => { + let e = editor.clone(); + let d = *depth; + editor.read().unwrap().get_term_view().map_item(move |_pt, atom| { + let cur_depth = e.read().unwrap().get_cursor().tree_addr.len(); + atom.add_style_back(bg_style_from_depth(cur_depth)) + .add_style_back(fg_style_from_depth(d+cur_depth)) + }) + } + } + } +} + +pub struct ListSegmentSequence +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static +{ + data: Arc>>>, + cursor: Arc>, + + depth: usize, + cur_cursor: ListCursor, + + cast: Arc>>>>, + proj_helper: ProjectionHelper, +} + +impl View for ListSegmentSequence +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static +{ + type Msg = usize; +} + +impl SequenceView for ListSegmentSequence +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static +{ + type Item = ListSegment; + + fn len(&self) -> Option { + match self.cur_cursor.mode { + ListCursorMode::Insert => { + Some(self.data.len()? + if self.cur_cursor.idx.is_some() { 1 } else { 0 }) + } + _ => self.data.len(), + } + } + + fn get(&self, idx: &usize) -> Option { + let c = self.cursor.get(); + Some(if let Some(mut cur) = c.idx { + match c.mode { + ListCursorMode::Select => { + ListSegment::Item { + editor: self.data.get(idx)?, + depth: self.depth, + cur_dist: cur - *idx as isize + } + } + ListCursorMode::Insert => { + if *idx < cur as usize { + ListSegment::Item { + editor: self.data.get(idx)?, + depth: self.depth, + cur_dist: cur - *idx as isize + } + } else if *idx == cur as usize { + ListSegment::InsertCursor + } else { + ListSegment::Item { + editor: self.data.get(&(*idx - 1))?, + depth: self.depth, + cur_dist: cur - (*idx as isize - 1) + } + } + } + } + } else { + ListSegment::Item { + editor: self.data.get(&idx)?, + depth: self.depth, + cur_dist: *idx as isize + 1 + } + }) + } +} + +impl ListSegmentSequence +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static +{ + pub fn new( + cursor_port: OuterViewPort>, + data_port: OuterViewPort>>>, + out_port: InnerViewPort>>, + depth: usize + ) -> Arc> { + let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone()); + let proj = Arc::new(RwLock::new(ListSegmentSequence { + cur_cursor: cursor_port.get_view().get(), + depth, + cursor: proj_helper.new_singleton_arg(0, cursor_port, |s: &mut Self, _msg| { + let _old_cursor = s.cur_cursor; + s.cur_cursor = s.cursor.get(); + + // todo: optimize + s.cast.notify_each(0..=s.data.len().unwrap_or(0) + 1); + }), + + data: proj_helper.new_sequence_arg(1, data_port, |s: &mut Self, idx| { + if let Some(mut cur_idx) = s.cur_cursor.idx { + match s.cur_cursor.mode { + ListCursorMode::Insert => { + if *idx < cur_idx as usize { + s.cast.notify(idx); + } else { + s.cast.notify(&(*idx + 1)); + } + } + _ => { + s.cast.notify(idx); + } + } + } else { + s.cast.notify(idx); + } + }), + cast: out_port.get_broadcast(), + proj_helper, + })); + + proj.write().unwrap().proj_helper.set_proj(&proj); + out_port.set_view(Some(proj.clone())); + + proj + } +} diff --git a/nested/src/list/sexpr.rs b/nested/src/list/sexpr.rs deleted file mode 100644 index 53c374f..0000000 --- a/nested/src/list/sexpr.rs +++ /dev/null @@ -1,270 +0,0 @@ -use { - crate::{ - core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View, ViewPort}, - index::IndexArea, - projection::ProjectionHelper, - sequence::SequenceView, - terminal::{make_label, TerminalStyle, TerminalView}, - }, - cgmath::Point2, - std::sync::Arc, - std::sync::RwLock, -}; - -//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> - -pub struct ListDecorator { - opening_port: OuterViewPort, - closing_port: OuterViewPort, - delim_port: OuterViewPort, - items: Arc>>, - - list_style: TerminalStyle, - item_style: TerminalStyle, - - cast: Arc>>>>, - proj_helper: ProjectionHelper<(), Self>, -} - -impl View for ListDecorator { - type Msg = usize; -} - -impl SequenceView for ListDecorator { - type Item = OuterViewPort; - - fn len(&self) -> Option { - let l = self.items.len()?; - Some(if l == 0 { 2 } else { 2 * l + 1 }) - } - - fn get(&self, idx: &usize) -> Option { - let item_idx = idx / 2; - let list_style = self.list_style.clone(); - let item_style = self.item_style.clone(); - let l = self.items.len().unwrap_or(0); - Some(if *idx == 0 { - self.opening_port - .clone() - .map_item(move |_, atom| atom.add_style_back(list_style)) - } else if (l == 0 && *idx == 1) || *idx == 2 * l { - self.closing_port - .clone() - .map_item(move |_, atom| atom.add_style_back(list_style)) - } else if idx % 2 == 0 { - self.delim_port - .clone() - .map_item(move |_, atom| atom.add_style_back(list_style)) - } else { - self.items - .get(&item_idx)? - .map_item(move |_, atom| atom.add_style_back(item_style)) - }) - } -} - -impl ListDecorator { - pub fn new( - opening: &str, - closing: &str, - delim: &str, - level: usize, - items_port: OuterViewPort>>, - out_port: InnerViewPort>>, - ) -> Arc> { - let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone()); - - let li = Arc::new(RwLock::new(ListDecorator { - opening_port: make_label(opening), - closing_port: make_label(closing), - delim_port: make_label(delim), - items: proj_helper.new_sequence_arg((), items_port, |s: &mut Self, item_idx| { - s.cast.notify(&(*item_idx * 2 + 1)); - s.cast.notify(&(*item_idx * 2 + 2)); - }), - list_style: TerminalStyle::fg_color(match level { - 0 => (200, 120, 10), - 1 => (120, 200, 10), - _ => (255, 255, 255), - }), - item_style: TerminalStyle::fg_color(match level { - _ => (255, 255, 255), - }), - cast: out_port.get_broadcast(), - proj_helper, - })); - - li.write().unwrap().proj_helper.set_proj(&li); - - out_port.set_view(Some(li.clone())); - li - } -} - -pub trait ListDecoration { - fn decorate( - &self, - opening: &str, - closing: &str, - delim: &str, - level: usize, - ) -> OuterViewPort>>; -} - -impl ListDecoration for OuterViewPort>> { - fn decorate( - &self, - opening: &str, - closing: &str, - delim: &str, - level: usize, - ) -> OuterViewPort>> { - let port = ViewPort::new(); - ListDecorator::new(opening, closing, delim, level, self.clone(), port.inner()); - port.into_outer() - } -} - -//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> - -use crate::{grid::GridView, index::IndexView}; - -pub struct VerticalSexprDecorator { - opening_port: OuterViewPort, - closing_port: OuterViewPort, - items: Arc>>, - - list_style: TerminalStyle, - item_style: TerminalStyle, - - cast: Arc>>>>, - proj_helper: ProjectionHelper<(), Self>, -} - -impl View for VerticalSexprDecorator { - type Msg = IndexArea>; -} - -impl IndexView> for VerticalSexprDecorator { - type Item = OuterViewPort; - - fn area(&self) -> IndexArea> { - IndexArea::Range( - Point2::new(0, 0) - ..=Point2::new(2, std::cmp::max(self.items.len().unwrap() as i16 - 1, 0)), - ) - } - - fn get(&self, pt: &Point2) -> Option { - if pt.y < 0 { - return None; - } - let item_idx = pt.y as usize; - let list_style = self.list_style.clone(); - let item_style = self.item_style.clone(); - let l = self.items.len().unwrap_or(0); - - match pt.x { - 0 => { - if pt.y == 0 { - Some( - self.opening_port - .clone() - .map_item(move |_, atom| atom.add_style_back(list_style)), - ) - } else { - None - } - } - 1 => { - if item_idx < l { - Some( - self.items - .get(&item_idx)? - .map_item(move |_, atom| atom.add_style_back(item_style)), - ) - } else { - None - } - } - 2 => { - if (l == 0 && pt.y == 0) || (item_idx + 1 == l) { - Some( - self.closing_port - .clone() - .map_item(move |_, atom| atom.add_style_back(list_style)), - ) - } else { - None - } - } - _ => None, - } - } -} - -impl VerticalSexprDecorator { - pub fn new( - opening: &str, - closing: &str, - level: usize, - items_port: OuterViewPort>>, - out_port: InnerViewPort>>, - ) -> Arc> { - let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone()); - - let li = Arc::new(RwLock::new(VerticalSexprDecorator { - opening_port: make_label(opening), - closing_port: make_label(closing), - items: proj_helper.new_sequence_arg((), items_port, |s: &mut Self, item_idx| { - s.cast.notify(&IndexArea::Range( - Point2::new(0, *item_idx as i16)..=Point2::new(2, *item_idx as i16), - )); - }), - list_style: TerminalStyle::fg_color(match level { - 0 => (200, 120, 10), - 1 => (120, 200, 10), - 2 => (200, 10, 120), - _ => (255, 255, 255), - }), - item_style: TerminalStyle::fg_color(match level { - _ => (255, 255, 255), - }), - cast: out_port.get_broadcast(), - proj_helper, - })); - - li.write().unwrap().proj_helper.set_proj(&li); - - out_port.set_view(Some(li.clone())); - li - } -} - -pub trait SExprView { - fn horizontal_sexpr_view(&self, level: usize) -> OuterViewPort; - fn vertical_bar_view(&self, level: usize) -> OuterViewPort; - fn vertical_sexpr_view(&self, level: usize) -> OuterViewPort; -} - -impl SExprView for OuterViewPort>> { - fn horizontal_sexpr_view(&self, level: usize) -> OuterViewPort { - let port = ViewPort::new(); - ListDecorator::new("(", ")", " ", level, self.clone(), port.inner()); - - port.into_outer().to_grid_horizontal().flatten() - } - - fn vertical_bar_view(&self, level: usize) -> OuterViewPort { - let port = ViewPort::new(); - ListDecorator::new("Λ", "V", "|", level, self.clone(), port.inner()); - - port.into_outer().to_grid_vertical().flatten() - } - - fn vertical_sexpr_view(&self, level: usize) -> OuterViewPort { - let port = ViewPort::new(); - VerticalSexprDecorator::new("(", ")", level, self.clone(), port.inner()); - port.into_outer().flatten() - } -} diff --git a/nested/src/make_editor.rs b/nested/src/make_editor.rs index 975f741..ad4a1ed 100644 --- a/nested/src/make_editor.rs +++ b/nested/src/make_editor.rs @@ -1,24 +1,17 @@ use { crate::{ - core::{ViewPort, OuterViewPort, Observer, port::UpdateTask, TypeTerm, TypeLadder, Context}, - terminal::{ - Terminal, TerminalAtom, TerminalCompositor, TerminalEditor, - TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView, - make_label - }, - sequence::{SequenceView}, - tree_nav::{TreeNav, TerminalTreeEditor, TreeCursor, TreeNavResult}, - vec::{VecBuffer, MutableVecAccess}, - index::buffer::IndexBuffer, + core::{TypeLadder, Context}, + terminal::{TerminalView}, + tree_nav::{TerminalTreeEditor}, integer::PosIntEditor, - string_editor::{StringEditor, CharEditor}, - list::{ListEditor, ListCursorMode, ListEditorStyle}, - product::editor::ProductEditor + list::{ListEditor, PTYListEditor}, + sequence::{decorator::{SeqDecorStyle}}, + product::editor::ProductEditor, + char_editor::CharEditor }, - cgmath::{Point2, Vector2}, - std::{sync::{Arc, RwLock}, ops::{Deref, DerefMut}}, - termion::event::{Event, Key}, + cgmath::Vector2, + std::sync::{Arc, RwLock}, }; pub fn make_editor(ctx: Arc>, t: &TypeLadder, depth: usize) -> Arc> { @@ -30,44 +23,70 @@ pub fn make_editor(ctx: Arc>, t: &TypeLadder, depth: usize) -> A Arc::new(RwLock::new(PosIntEditor::new(10))) as Arc> } else if t[0] == c.type_term_from_str("( String )").unwrap() { - Arc::new(RwLock::new(StringEditor::new())) as Arc> + Arc::new(RwLock::new( + PTYListEditor::new( + Box::new(|| { + Arc::new(RwLock::new(CharEditor::new())) + }), + SeqDecorStyle::DoubleQuote, + depth + ) + )) } else if t[0] == c.type_term_from_str("( List Char )").unwrap() { - Arc::new(RwLock::new(ListEditor::new( - || { Arc::new(RwLock::new(CharEditor::new())) }, - ListEditorStyle::Plain - ))) as Arc> + Arc::new(RwLock::new( + PTYListEditor::new( + Box::new( + || { Arc::new(RwLock::new(CharEditor::new())) } + ), + SeqDecorStyle::Plain, + depth + ) + )) as Arc> } else if t[0] == c.type_term_from_str("( List ℕ )").unwrap() { - Arc::new(RwLock::new(ListEditor::new( - || { - Arc::new(RwLock::new(PosIntEditor::new(16))) - }, - ListEditorStyle::HorizontalSexpr - ))) as Arc> + Arc::new(RwLock::new( + PTYListEditor::new( + Box::new(|| { + Arc::new(RwLock::new(PosIntEditor::new(16))) + }), + SeqDecorStyle::EnumSet, + depth + ) + )) as Arc> } else if t[0] == c.type_term_from_str("( Path )").unwrap() { - Arc::new(RwLock::new(ListEditor::new( - || { - Arc::new(RwLock::new(ListEditor::new( - || { - Arc::new(RwLock::new(CharEditor::new())) - }, - ListEditorStyle::Plain - ))) - }, - ListEditorStyle::Path + let d = depth + 1; + Arc::new(RwLock::new(PTYListEditor::new( + Box::new({ + let d= depth +1; + move || { + Arc::new(RwLock::new(PTYListEditor::new( + Box::new(|| { + Arc::new(RwLock::new(CharEditor::new())) + }), + SeqDecorStyle::Plain, + d + ))) + }}), + SeqDecorStyle::Path, + depth ))) as Arc> } else if t[0] == c.type_term_from_str("( List RGB )").unwrap() { - Arc::new(RwLock::new(ListEditor::new({ - let ctx = ctx.clone(); - move || { - make_editor(ctx.clone(), &vec![ ctx.read().unwrap().type_term_from_str("( RGB )").unwrap() ], depth+1) - } - }, - ListEditorStyle::VerticalSexpr - ))) as Arc> + Arc::new(RwLock::new( + PTYListEditor::::new( + Box::new({ + let d = depth+1; + let ctx = ctx.clone(); + move || { + make_editor(ctx.clone(), &vec![ ctx.read().unwrap().type_term_from_str("( RGB )").unwrap() ], d) + } + }), + SeqDecorStyle::VerticalSexpr, + depth + ) + )) as Arc> } else if t[0] == c.type_term_from_str("( RGB )").unwrap() { Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone()) @@ -92,14 +111,18 @@ pub fn make_editor(ctx: Arc>, t: &TypeLadder, depth: usize) -> A )) as Arc> } else if t[0] == c.type_term_from_str("( List Term )").unwrap() { - Arc::new(RwLock::new(ListEditor::new({ - let ctx = ctx.clone(); - move || { - make_editor(ctx.clone(), &vec![ ctx.read().unwrap().type_term_from_str("( Term )").unwrap() ], depth+1) - } - }, - ListEditorStyle::Tuple(depth) - ))) as Arc> + Arc::new(RwLock::new( + PTYListEditor::::new( + Box::new({ + let ctx = ctx.clone(); + move || { + make_editor(ctx.clone(), &vec![ ctx.read().unwrap().type_term_from_str("( Term )").unwrap() ], depth+1) + } + }), + SeqDecorStyle::Tuple, + depth + ) + )) as Arc> } else { // else: term Arc::new(RwLock::new( diff --git a/nested/src/modulo.rs b/nested/src/modulo.rs new file mode 100644 index 0000000..dc8ae8e --- /dev/null +++ b/nested/src/modulo.rs @@ -0,0 +1,10 @@ + +pub fn modulo(a: isize, b: isize) -> isize { + if b > 0 { + ((a % b) + b) % b + } else { + 0 + } +} + + diff --git a/nested/src/product/editor.rs b/nested/src/product/editor.rs index 8dfd0aa..48823e2 100644 --- a/nested/src/product/editor.rs +++ b/nested/src/product/editor.rs @@ -1,24 +1,19 @@ - use { crate::{ - core::{ViewPort, OuterViewPort, Observer, port::UpdateTask, TypeTerm, TypeLadder, Context}, + core::{ViewPort, OuterViewPort, TypeLadder, Context}, terminal::{ - Terminal, TerminalAtom, TerminalCompositor, TerminalEditor, - TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView, - make_label + TerminalEditor, TerminalEditorResult, + TerminalEvent, TerminalView }, sequence::{SequenceView}, - tree_nav::{TreeNav, TerminalTreeEditor, TreeCursor, TreeNavResult}, + tree_nav::{TreeNav, TerminalTreeEditor, TreeNavResult}, vec::{VecBuffer, MutableVecAccess}, - index::buffer::IndexBuffer, - integer::PosIntEditor, - string_editor::{StringEditor, CharEditor}, - list::{ListEditor, ListCursorMode, ListEditorStyle}, + list::ListCursorMode, product::{element::ProductEditorElement}, make_editor::make_editor }, - cgmath::{Point2, Vector2}, - std::{sync::{Arc, RwLock}, ops::{Deref, DerefMut}}, + cgmath::Vector2, + std::sync::{Arc, RwLock}, termion::event::{Event, Key}, }; @@ -31,8 +26,8 @@ pub struct ProductEditor { pub(super) ctx: Arc>, - pub(super) cursor: Option, - pub(super) depth: usize + pub(super) cursor: Option, + pub(super) depth: usize, } impl ProductEditor { @@ -46,7 +41,7 @@ impl ProductEditor { }); ProductEditor { - elements: VecBuffer::new(port.inner()), + elements: VecBuffer::with_port(port.inner()), el_port, el_view_port, n_indices: Vec::new(), @@ -57,9 +52,9 @@ impl ProductEditor { depth } } - + pub fn with_t(mut self, t: &str) -> Self { - self.elements.push(ProductEditorElement::T(t.to_string())); + self.elements.push(ProductEditorElement::T(t.to_string(), self.depth)); self } @@ -68,22 +63,24 @@ impl ProductEditor { self.elements.push(ProductEditorElement::N{ t: n, editor: None, - select: false + cur_depth: 0 }); self.n_indices.push(elem_idx); self } - pub fn get_editor_element(&self, idx: usize) -> Option { - if let Some(i) = self.n_indices.get(idx) { + pub fn get_editor_element(&self, mut idx: isize) -> Option { + idx = crate::modulo(idx, self.n_indices.len() as isize); + if let Some(i) = self.n_indices.get(idx as usize) { Some(self.elements.get(*i)) } else { None } } - pub fn get_editor_element_mut(&mut self, idx: usize) -> Option> { - if let Some(i) = self.n_indices.get(idx) { + pub fn get_editor_element_mut(&mut self, mut idx: isize) -> Option> { + idx = crate::modulo(idx, self.n_indices.len() as isize); + if let Some(i) = self.n_indices.get(idx as usize) { Some(self.elements.get_mut(*i)) } else { None @@ -98,14 +95,14 @@ impl ProductEditor { self.get_editor_element_mut(self.cursor?) } - pub fn get_editor(&self, idx: usize) -> Option>> { - if let Some(ProductEditorElement::N{ t: _, editor, select: _ }) = self.get_editor_element(idx) { + pub fn get_editor(&self, idx: isize) -> Option>> { + if let Some(ProductEditorElement::N{ t: _, editor, cur_depth: _ }) = self.get_editor_element(idx) { editor } else { None } } - + pub fn get_cur_editor(&self) -> Option>> { self.get_editor(self.cursor?) } @@ -123,14 +120,15 @@ impl TerminalEditor for ProductEditor { } fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() { - *select = true; + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_cur_element_mut().as_deref_mut() { + *cur_depth = self.get_cursor().tree_addr.len(); if let Some(e) = editor.clone() { match e.clone().write().unwrap().handle_terminal_event(event) { TerminalEditorResult::Exit => match event { TerminalEvent::Input(Event::Key(Key::Backspace)) => { *editor = None; + *cur_depth -= 1; TerminalEditorResult::Continue } _ => { @@ -149,6 +147,7 @@ impl TerminalEditor for ProductEditor { *editor = Some(e.clone()); e.write().unwrap().dn(); let x = e.write().unwrap().handle_terminal_event(event); + *cur_depth = self.get_cursor().tree_addr.len(); x } } else { diff --git a/nested/src/product/element.rs b/nested/src/product/element.rs index 3387f86..1c19232 100644 --- a/nested/src/product/element.rs +++ b/nested/src/product/element.rs @@ -1,72 +1,55 @@ use { crate::{ - core::{ViewPort, OuterViewPort, Observer, port::UpdateTask, TypeTerm, TypeLadder, Context}, + core::{OuterViewPort, TypeLadder, Context}, terminal::{ - Terminal, TerminalAtom, TerminalCompositor, TerminalEditor, - TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView, + TerminalEditor, TerminalStyle, TerminalView, make_label }, - sequence::{SequenceView}, - tree_nav::{TreeNav, TerminalTreeEditor, TreeCursor, TreeNavResult}, - vec::{VecBuffer, MutableVecAccess}, - index::buffer::IndexBuffer, - integer::PosIntEditor, - string_editor::{StringEditor, CharEditor}, - list::{ListEditor, ListCursorMode, ListEditorStyle} + tree_nav::{TerminalTreeEditor}, + color::{bg_style_from_depth, fg_style_from_depth} }, - cgmath::{Point2, Vector2}, std::{sync::{Arc, RwLock}, ops::{Deref, DerefMut}}, termion::event::{Event, Key}, }; - #[derive(Clone)] pub enum ProductEditorElement { - T( String ), + T( String, usize ), N { t: TypeLadder, editor: Option>>, - select: bool + cur_depth: usize } } impl ProductEditorElement { pub fn get_view(&self, ctx: Arc>) -> OuterViewPort { match self { - ProductEditorElement::T(t) => + ProductEditorElement::T(t, depth) => make_label(t.as_str()) - .map_item( - |i, x| - x.add_style_back(TerminalStyle::fg_color((0,120,200))) - ), + .map_item({ + let depth = *depth; + move |i, x| + x.add_style_back(fg_style_from_depth(depth)) + } + ), - ProductEditorElement::N {t: _, editor: Some(e), select} => + ProductEditorElement::N { t: _, editor: Some(e), cur_depth } => e.read().unwrap() .get_term_view() - .map_item({ let select = *select; + .map_item({ let cur_depth = *cur_depth;//e.read().unwrap().get_cursor().tree_addr.len()+1; move |i, x| x - .add_style_back(TerminalStyle::fg_color((250,210,0))) - .add_style_back( - if select { - TerminalStyle::bg_color((40,40,40)) - } else { - TerminalStyle::default() - } - ) + .add_style_back(fg_style_from_depth(cur_depth))//fg_color((250,210,0))) + .add_style_back(bg_style_from_depth(cur_depth)) }), - ProductEditorElement::N{t, editor: None, select} => + ProductEditorElement::N{ t, editor: None, cur_depth } => make_label(&ctx.read().unwrap().type_term_to_str(&t[0])) - .map_item({ let select = *select; - move |i, x| x + .map_item({ + let cur_depth = *cur_depth; + move |i, x| x .add_style_back(TerminalStyle::fg_color((130,90,40))) - .add_style_back( - if select { - TerminalStyle::bg_color((40,40,40)) - } else { - TerminalStyle::default() - } - ) + .add_style_back(bg_style_from_depth(cur_depth)) }) } } diff --git a/nested/src/product/nav.rs b/nested/src/product/nav.rs index 10c83ac..7e50a5e 100644 --- a/nested/src/product/nav.rs +++ b/nested/src/product/nav.rs @@ -1,20 +1,8 @@ use { crate::{ - core::{ViewPort, OuterViewPort, Observer, port::UpdateTask, TypeTerm, TypeLadder, Context}, - terminal::{ - Terminal, TerminalAtom, TerminalCompositor, TerminalEditor, - TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView, - make_label - }, - sequence::{SequenceView}, - tree_nav::{TreeNav, TerminalTreeEditor, TreeCursor, TreeNavResult}, - vec::{VecBuffer, MutableVecAccess}, - index::buffer::IndexBuffer, - integer::PosIntEditor, - string_editor::{StringEditor, CharEditor}, - list::{ListEditor, ListCursorMode, ListEditorStyle}, - product::{element::ProductEditorElement, ProductEditor}, - make_editor::make_editor + list::ListCursorMode, + tree_nav::{TreeNav, TreeNavResult, TreeCursor, TerminalTreeEditor}, + product::{element::ProductEditorElement, ProductEditor} }, cgmath::{Point2, Vector2}, std::{sync::{Arc, RwLock}, ops::{Deref, DerefMut}}, @@ -44,23 +32,23 @@ impl TreeNav for ProductEditor { fn goto(&mut self, mut c: TreeCursor) -> TreeNavResult { if let Some(mut element) = self.get_cur_element_mut() { - if let ProductEditorElement::N{ t, editor, select } = element.deref_mut() { + if let ProductEditorElement::N{ t, editor, cur_depth } = element.deref_mut() { if let Some(e) = editor { e.write().unwrap().goto(TreeCursor::default()); } - *select = false; + *cur_depth = self.get_cursor().tree_addr.len(); } } if c.tree_addr.len() > 0 { - self.cursor = Some(c.tree_addr.remove(0)); + self.cursor = Some(c.clone().tree_addr.remove(0)); if let Some(mut element) = self.get_cur_element_mut() { - if let ProductEditorElement::N{ t, editor, select } = element.deref_mut() { + if let ProductEditorElement::N{ t, editor, cur_depth } = element.deref_mut() { if let Some(e) = editor { - e.write().unwrap().goto(c); + e.write().unwrap().goto(c.clone()); } - *select = true; + *cur_depth = c.tree_addr.len() + 1; } } @@ -71,9 +59,13 @@ impl TreeNav for ProductEditor { } } + fn goby(&mut self, direction: Vector2) -> TreeNavResult { + TreeNavResult::Exit + } +/* fn goto_home(&mut self) -> TreeNavResult { if let Some(c) = self.cursor { - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() { + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_cur_element_mut().as_deref_mut() { if let Some(e) = editor { let mut ce = e.write().unwrap(); @@ -84,7 +76,7 @@ impl TreeNav for ProductEditor { return match ce.goto_home() { TreeNavResult::Exit => { drop(ce); - *select = false; + *cur_depth = 0; match self.pxev() { TreeNavResult::Exit => TreeNavResult::Exit, @@ -105,11 +97,11 @@ impl TreeNav for ProductEditor { } } - *select = false; + *cur_depth = 0; if c != 0 { self.cursor = Some(0); - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() { - *select = true; + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_cur_element_mut().as_deref_mut() { + *cur_depth = self.get_cursor().tree_addr.len() + 1; } return TreeNavResult::Continue; } @@ -121,7 +113,7 @@ impl TreeNav for ProductEditor { fn goto_end(&mut self) -> TreeNavResult { if let Some(c) = self.cursor { - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() { + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_cur_element_mut().as_deref_mut() { if let Some(e) = editor { let mut ce = e.write().unwrap(); @@ -132,7 +124,7 @@ impl TreeNav for ProductEditor { match ce.goto_end() { TreeNavResult::Exit => { drop(ce); - *select = false; + *cur_depth = 0; if c+1 < self.n_indices.len() { match self.nexd() { @@ -158,11 +150,11 @@ impl TreeNav for ProductEditor { } } - *select = false; + *cur_depth = 0; if c < self.n_indices.len()-1 { self.cursor = Some(self.n_indices.len()-1); - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() { - *select = true; + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_cur_element_mut().as_deref_mut() { + *cur_depth = self.get_cursor().tree_addr.len(); } return TreeNavResult::Continue; } @@ -174,7 +166,7 @@ impl TreeNav for ProductEditor { fn pxev(&mut self) -> TreeNavResult { if let Some(c) = self.cursor { - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_editor_element_mut(c).as_deref_mut() { + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_editor_element_mut(c).as_deref_mut() { if let Some(e) = editor { let mut ce = e.write().unwrap(); @@ -185,12 +177,12 @@ impl TreeNav for ProductEditor { return match ce.pxev() { TreeNavResult::Exit => { drop(ce); - *select = false; + *cur_depth = 0; if c > 0 { self.cursor = Some(c-1); - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() { - *select = true; + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_cur_element_mut().as_deref_mut() { + *cur_depth = self.get_cursor().tree_addr.len(); } for _x in 1..depth { @@ -212,11 +204,11 @@ impl TreeNav for ProductEditor { } } - *select = false; + *cur_depth = 0; if c > 0 { self.cursor = Some(c-1); - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() { - *select = true; + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_cur_element_mut().as_deref_mut() { + *cur_depth = self.get_cursor().tree_addr.len(); } return TreeNavResult::Continue; } @@ -229,7 +221,7 @@ impl TreeNav for ProductEditor { fn nexd(&mut self) -> TreeNavResult { if let Some(c) = self.cursor.clone() { - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_editor_element_mut(c).as_deref_mut() { + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_editor_element_mut(c).as_deref_mut() { if let Some(e) = editor { let mut ce = e.write().unwrap(); @@ -240,16 +232,17 @@ impl TreeNav for ProductEditor { return match ce.nexd() { TreeNavResult::Exit => { drop(ce); - *select = false; + *cur_depth = 0; if c+1 < self.n_indices.len() { self.cursor = Some(c+1); - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() { - *select = true; + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_cur_element_mut().as_deref_mut() { + *cur_depth = self.get_cursor().tree_addr.len(); } for _x in 1..depth { self.dn(); + self.goto_home(); } self.dn(); @@ -266,11 +259,11 @@ impl TreeNav for ProductEditor { } } - *select = false; + *cur_depth = 0; if c+1 < self.n_indices.len() { self.cursor = Some(c+1); - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() { - *select = true; + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_cur_element_mut().as_deref_mut() { + *cur_depth = self.get_cursor().tree_addr.len(); } return TreeNavResult::Continue; @@ -283,15 +276,16 @@ impl TreeNav for ProductEditor { } fn up(&mut self) -> TreeNavResult { - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() { + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_cur_element_mut().as_deref_mut() { if let Some(e) = editor { let mut ce = e.write().unwrap(); + *cur_depth = ce.get_cursor().tree_addr.len(); if ce.get_cursor().tree_addr.len() > 0 { ce.up(); return TreeNavResult::Continue; } } - *select = false; + *cur_depth = 0; } self.cursor = None; @@ -300,24 +294,26 @@ impl TreeNav for ProductEditor { fn dn(&mut self) -> TreeNavResult { if let Some(c) = self.cursor { - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_editor_element_mut(c).as_deref_mut() { + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_editor_element_mut(c).as_deref_mut() { if let Some(e) = editor { e.write().unwrap().dn(); } else { let e = make_editor(self.ctx.clone(), t, self.depth+1); - e.write().unwrap().goto_home(); + e.write().unwrap().dn(); *editor = Some(e); } + *cur_depth = self.get_cursor().tree_addr.len(); } } else { self.cursor = Some(0); - if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() { - *select = true; + if let Some(ProductEditorElement::N{ t, editor, cur_depth }) = self.get_cur_element_mut().as_deref_mut() { + *cur_depth = self.get_cursor().tree_addr.len(); } } TreeNavResult::Continue - } +} + */ } impl TerminalTreeEditor for ProductEditor {} diff --git a/nested/src/sequence/decorator.rs b/nested/src/sequence/decorator.rs index df7be0a..b379056 100644 --- a/nested/src/sequence/decorator.rs +++ b/nested/src/sequence/decorator.rs @@ -228,13 +228,13 @@ impl PTYSeqDecorate for OuterViewPort self - .separate(make_label(",")) + .separate(make_label(", ")) .wrap(make_label("("), make_label(")")) .to_grid_horizontal() .flatten(), SeqDecorStyle::EnumSet => self - .separate(make_label(",")) + .separate(make_label(", ")) .wrap(make_label("{"), make_label("}")) .to_grid_horizontal() .flatten(), @@ -246,7 +246,7 @@ impl PTYSeqDecorate for OuterViewPort self - .wrap(make_label("0"), make_label("")) + .wrap(make_label("0x"), make_label("")) .to_grid_horizontal() .flatten(), } diff --git a/nested/src/string_editor.rs b/nested/src/string_editor.rs deleted file mode 100644 index a6e00e4..0000000 --- a/nested/src/string_editor.rs +++ /dev/null @@ -1,151 +0,0 @@ -use { - crate::{ - core::{OuterViewPort, ViewPort}, - list::{sexpr::ListDecoration, ListEditor}, - sequence::{SequenceView, SequenceViewExt}, - singleton::{SingletonBuffer, SingletonView}, - terminal::{ - TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView, - }, - tree_nav::{TreeCursor, TreeNav, TreeNavResult, TerminalTreeEditor}, - }, - std::sync::Arc, - std::sync::RwLock, - termion::event::{Event, Key}, -}; - -//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> - -pub struct CharEditor { - data: SingletonBuffer>, - data_port: ViewPort>>, -} - -impl CharEditor { - pub fn new() -> Self { - let data_port = ViewPort::new(); - CharEditor { - data: SingletonBuffer::new(None, data_port.inner()), - data_port, - } - } - - pub fn get_data_port(&self) -> OuterViewPort>> { - self.data_port.outer() - } -} - -impl TreeNav for CharEditor {} -impl TerminalEditor for CharEditor { - fn get_term_view(&self) -> OuterViewPort { - crate::terminal::make_label(&if let Some(c) = self.data.get() { - c.to_string() - } else { - "".to_string() - }) - } - - fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { - match event { - TerminalEvent::Input(Event::Key(Key::Char('\n'))) => TerminalEditorResult::Continue, - TerminalEvent::Input(Event::Key(Key::Char(c))) => { - self.data.set(Some(*c)); - TerminalEditorResult::Exit - } - TerminalEvent::Input(Event::Key(Key::Backspace)) - | TerminalEvent::Input(Event::Key(Key::Delete)) => { - self.data.set(None); - TerminalEditorResult::Exit - } - _ => TerminalEditorResult::Continue, - } - } -} - -impl TerminalTreeEditor for CharEditor {} - -//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> - -pub struct StringEditor { - chars_editor: - ListEditor Arc> + Send + Sync + 'static>>, -} - -impl StringEditor { - pub fn new() -> Self { - StringEditor { - chars_editor: ListEditor::new( - Box::new(move || Arc::new(RwLock::new(CharEditor::new()))), - crate::list::ListEditorStyle::String, - ), - } - } - - pub fn get_data_port(&self) -> OuterViewPort> { - self.chars_editor - .get_data_port() - .map(|char_editor| char_editor.read().unwrap().data.get().unwrap_or('?')) - } - - pub fn get_plain_editor_view(&self) -> OuterViewPort { - self.chars_editor - .get_seg_seq_view() - .to_grid_horizontal() - .flatten() - } - - pub fn get_string(&self) -> String { - self.get_data_port().get_view().unwrap().iter().collect() - } -} - -impl TreeNav for StringEditor { - fn get_cursor(&self) -> TreeCursor { - self.chars_editor.get_cursor() - } - fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { - self.chars_editor.goto(cur) - } - fn goto_home(&mut self) -> TreeNavResult { - self.chars_editor.goto_home() - } - fn goto_end(&mut self) -> TreeNavResult { - self.chars_editor.goto_end() - } - fn pxev(&mut self) -> TreeNavResult { - self.chars_editor.pxev() - } - fn nexd(&mut self) -> TreeNavResult { - self.chars_editor.nexd() - } - fn up(&mut self) -> TreeNavResult { - self.chars_editor.up() - } - fn dn(&mut self) -> TreeNavResult { - self.chars_editor.dn() - } -} - -impl TerminalEditor for StringEditor { - fn get_term_view(&self) -> OuterViewPort { - self.chars_editor - .get_seg_seq_view() - .decorate("\"", "\"", "", 1) - .to_grid_horizontal() - .flatten() - .map_item(|_idx, atom| atom.add_style_back(TerminalStyle::fg_color((120, 200, 10)))) - } - - fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { - match event { - TerminalEvent::Input(Event::Key(Key::Char('\n'))) => { - self.chars_editor.up(); - TerminalEditorResult::Exit - } - event => self.chars_editor.handle_terminal_event(event), - } - } -} - -impl TerminalTreeEditor for StringEditor {} - diff --git a/nested/src/tree_nav.rs b/nested/src/tree_nav.rs index 800a82e..e56a70e 100644 --- a/nested/src/tree_nav.rs +++ b/nested/src/tree_nav.rs @@ -1,4 +1,7 @@ -use crate::list::ListCursorMode; +use { + crate::list::ListCursorMode, + cgmath::Vector2 +}; #[derive(Clone, Copy, Eq, PartialEq)] pub enum TreeNavResult { @@ -20,49 +23,43 @@ impl From for TerminalEditorResult { #[derive(Clone, Eq, PartialEq)] pub struct TreeCursor { pub leaf_mode: ListCursorMode, - pub tree_addr: Vec, + pub tree_addr: Vec, } impl TreeCursor { pub fn home() -> Self { TreeCursor { - leaf_mode: ListCursorMode::Select, + leaf_mode: ListCursorMode::Insert, tree_addr: vec![0] } } + + pub fn none() -> Self { + TreeCursor { + leaf_mode: ListCursorMode::Insert, + tree_addr: vec![], + } + } } impl Default for TreeCursor { fn default() -> Self { - TreeCursor { - leaf_mode: ListCursorMode::Select, - tree_addr: vec![], - } + TreeCursor::none() } } pub trait TreeNav { - fn up(&mut self) -> TreeNavResult { - TreeNavResult::Exit + /* CORE + */ + fn get_cursor(&self) -> TreeCursor { + TreeCursor::default() } - fn dn(&mut self) -> TreeNavResult { - TreeNavResult::Exit + fn get_cursor_warp(&self) -> TreeCursor { + TreeCursor::default() } - fn pxev(&mut self) -> TreeNavResult { - TreeNavResult::Exit - } - - fn nexd(&mut self) -> TreeNavResult { - TreeNavResult::Exit - } - - fn goto_home(&mut self) -> TreeNavResult { - TreeNavResult::Exit - } - - fn goto_end(&mut self) -> TreeNavResult { + fn goby(&mut self, direction: Vector2) -> TreeNavResult { TreeNavResult::Exit } @@ -70,8 +67,85 @@ pub trait TreeNav { TreeNavResult::Exit } - fn get_cursor(&self) -> TreeCursor { - TreeCursor::default() + /* HULL + */ + fn set_addr(&mut self, addr: isize) -> TreeNavResult { + let mut c = self.get_cursor(); + c.tree_addr[0] = addr; + self.goto(c) + } + + fn set_leaf_mode(&mut self, new_leaf_mode: ListCursorMode) -> TreeNavResult { + let mut c = self.get_cursor(); + c.leaf_mode = new_leaf_mode; + self.goto(c) + } + + fn up(&mut self) -> TreeNavResult { + self.goby(Vector2::new(0, -1)) + } + + fn dn(&mut self) -> TreeNavResult { + self.goby(Vector2::new(0, 1)) + } + + fn pxev(&mut self) -> TreeNavResult { + self.goby(Vector2::new(-1, 0)) + } + + fn nexd(&mut self) -> TreeNavResult { + self.goby(Vector2::new(1, 0)) + } + + // TODO + fn qpxev(&mut self) -> TreeNavResult { + let mut c = self.get_cursor(); + match c.tree_addr.len() { + 0 => { + self.goto(TreeCursor::home()) + }, + depth => { + if c.tree_addr[depth-1] != 0 { + c.tree_addr[depth-1] = 0; + } else { + for i in (0..depth-1).rev() { + if c.tree_addr[i] == 0 { + c.tree_addr[i] = -1; + } else { + c.tree_addr[i] -=1; + break; + } + } + } + + self.goto(c) + } + } + } + + fn qnexd(&mut self) -> TreeNavResult { + let mut c = self.get_cursor_warp(); + match c.tree_addr.len() { + 0 => { + TreeNavResult::Exit + }, + depth => { + if c.tree_addr[depth-1] != -1 { + c.tree_addr[depth-1] = -1; + } else { + for i in (0..depth-1).rev() { + if c.tree_addr[i] == -1 { + c.tree_addr[i] = 0; + } else { + c.tree_addr[i] += 1; + break; + } + } + } + + self.goto(c) + } + } } } diff --git a/shell/src/command.rs b/shell/src/command.rs new file mode 100644 index 0000000..b408f4c --- /dev/null +++ b/shell/src/command.rs @@ -0,0 +1,194 @@ +use { + std::{ + sync::{Arc, RwLock}, + collections::HashMap + }, + cgmath::{Point2}, + termion::event::{Event, Key}, + nested::{ + list::{sexpr::ListDecoration, ListEditor, ListEditorStyle}, + core::TypeTerm, + core::{OuterViewPort, ViewPort}, + index::{IndexArea, IndexView}, + string_editor::StringEditor, + vec::VecBuffer, + terminal::{ + TerminalAtom, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView, make_label + }, + tree_nav::{TreeCursor, TreeNav, TreeNavResult}, + } +}; + +trait Action { + fn make_editor(&self) -> + (Arc>, + Arc>); +} + +pub struct ActCd {} +impl Action for ActCd { + fn make_editor(&self) -> + (Arc>, + Arc>) + { + let ed = + Arc::new(RwLock::new(ListEditor::new( + Box::new(|| { + Arc::new(RwLock::new(StringEditor::new())) + }) as Box Arc> + Send + Sync>, + ListEditorStyle::HorizontalSexpr, + ))); + //Arc::new(RwLock::new(StringEditor::new())); + + (ed.clone() as Arc>, ed as Arc>) + } +} + + +pub struct Commander { + cmds: HashMap>, + + symbol_editor: StringEditor, + cmd_editor: Option<( + Arc>, + Arc> + )>, + + view_elements: VecBuffer>, + out_port: OuterViewPort, +} + +impl Commander { + pub fn new() -> Self { + let port = ViewPort::new(); + let mut view_elements = VecBuffer::new(port.inner()); + let symbol_editor = StringEditor::new(); + + view_elements.push(symbol_editor.get_plain_editor_view()); + + let mut cmds = HashMap::new(); + cmds.insert("cd".into(), Arc::new(ActCd{}) as Arc); + cmds.insert("echo".into(), Arc::new(ActCd{}) as Arc); + cmds.insert("ls".into(), Arc::new(ActCd{}) as Arc); + + let mut c = Commander { + cmds, + symbol_editor, + cmd_editor: None, + view_elements, + out_port: port.outer() + .to_sequence() + .to_grid_horizontal() + .flatten() + }; + + c + } +} + +impl TerminalEditor for Commander { + fn get_term_view(&self) -> OuterViewPort { + self.out_port.clone() + } + + fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { + if let Some(cmd_editor) = self.cmd_editor.as_ref() { + match event { + TerminalEvent::Input(Event::Key(Key::Char('\n'))) => { + // run + cmd_editor.1.write().unwrap().up(); + TerminalEditorResult::Exit + } + event => { + cmd_editor.0.write().unwrap().handle_terminal_event(event) + } + } + } else { + match event { + TerminalEvent::Input(Event::Key(Key::Char(' '))) | + TerminalEvent::Input(Event::Key(Key::Char('\n'))) => { + let symbol = self.symbol_editor.get_string(); + + if let Some(action) = self.cmds.get(&symbol) { + let editor = action.make_editor(); + + self.symbol_editor.up(); + self.view_elements.push(make_label(" ")); + self.view_elements.push(editor.0.read().unwrap().get_term_view()); + + editor.1.write().unwrap().goto_home(); + self.cmd_editor = Some(editor); + } + + TerminalEditorResult::Continue + } + + event => { + self.symbol_editor.handle_terminal_event(event) + } + } + } + } +} + +impl TreeNav for Commander { + fn get_cursor(&self) -> TreeCursor { + if let Some(cmd_editor) = self.cmd_editor.as_ref() { + cmd_editor.1.write().unwrap().get_cursor() + } else { + self.symbol_editor.get_cursor() + } + } + + fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { + if let Some(cmd_editor) = self.cmd_editor.as_ref() { + cmd_editor.1.write().unwrap().goto(cur) + } else { + self.symbol_editor.goto(cur) + } + } + fn goto_home(&mut self) -> TreeNavResult { + if let Some(cmd_editor) = self.cmd_editor.as_ref() { + cmd_editor.1.write().unwrap().goto_home() + } else { + self.symbol_editor.goto_home() + } + } + fn goto_end(&mut self) -> TreeNavResult { + if let Some(cmd_editor) = self.cmd_editor.as_ref() { + cmd_editor.1.write().unwrap().goto_end() + } else { + self.symbol_editor.goto_end() + } + } + fn pxev(&mut self) -> TreeNavResult { + if let Some(cmd_editor) = self.cmd_editor.as_ref() { + cmd_editor.1.write().unwrap().pxev() + } else { + self.symbol_editor.pxev() + } + } + fn nexd(&mut self) -> TreeNavResult { + if let Some(cmd_editor) = self.cmd_editor.as_ref() { + cmd_editor.1.write().unwrap().nexd() + } else { + self.symbol_editor.nexd() + } + } + fn up(&mut self) -> TreeNavResult { + if let Some(cmd_editor) = self.cmd_editor.as_ref() { + cmd_editor.1.write().unwrap().up() + } else { + self.symbol_editor.up() + } + } + fn dn(&mut self) -> TreeNavResult { + if let Some(cmd_editor) = self.cmd_editor.as_ref() { + cmd_editor.1.write().unwrap().dn() + } else { + self.symbol_editor.dn() + } + } +} + + diff --git a/shell/src/main.rs b/shell/src/main.rs index 0062802..43f8353 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -13,12 +13,13 @@ use { nested::{ core::{port::UpdateTask, Observer, OuterViewPort, ViewPort}, index::IndexArea, - list::{ListCursorMode, ListEditor, ListEditorStyle}, + list::{ListCursorMode, PTYListEditor}, + sequence::{decorator::{SeqDecorStyle}}, terminal::{ make_label, Terminal, TerminalAtom, TerminalCompositor, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView, }, - tree_nav::{TerminalTreeEditor, TreeCursor, TreeNavResult}, + tree_nav::{TreeNav, TerminalTreeEditor, TreeCursor, TreeNavResult}, vec::VecBuffer, }, std::sync::{Arc, RwLock}, @@ -34,9 +35,7 @@ async fn main() { let term_writer = term.get_writer(); async_std::task::spawn(async move { - let table_port = - ViewPort::>>::new(); - let mut table_buf = nested::index::buffer::IndexBuffer::new(table_port.inner()); + let mut table = nested::index::buffer::IndexBuffer::new(); let magic = make_label("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>").map_item(|pos, atom| { @@ -47,21 +46,17 @@ async fn main() { ))) }); - let cur_size_port = ViewPort::new(); - let mut cur_size = - nested::singleton::SingletonBuffer::new(Vector2::new(10, 10), cur_size_port.inner()); + let mut cur_size = nested::singleton::SingletonBuffer::new(Vector2::new(10, 10)); + let mut status_chars = VecBuffer::new(); - let status_chars_port = ViewPort::new(); - let mut status_chars = VecBuffer::new(status_chars_port.inner()); - - let mut process_list_editor = ListEditor::new( + let mut process_list_editor = PTYListEditor::new( Box::new(|| Arc::new(RwLock::new(ProcessLauncher::new()))), - ListEditorStyle::VerticalSexpr, + SeqDecorStyle::VerticalSexpr, + 0 ); - let plist_vec_port = ViewPort::new(); - let mut plist = VecBuffer::new(plist_vec_port.inner()); - + let mut plist = VecBuffer::new(); + let mut plist_port = plist.get_port(); async_std::task::spawn(async move { let (w, _h) = termion::terminal_size().unwrap(); let mut x: usize = 0; @@ -89,13 +84,13 @@ async fn main() { }); let plot_port = ViewPort::new(); - let _plot = crate::plot::Plot::new(plist_vec_port.outer().to_sequence(), plot_port.inner()); + let _plot = crate::plot::Plot::new(plist_port.to_sequence(), plot_port.inner()); - table_buf.insert_iter(vec![ + table.insert_iter(vec![ (Point2::new(0, 0), magic.clone()), ( Point2::new(0, 1), - status_chars_port.outer().to_sequence().to_grid_horizontal(), + status_chars.get_port().to_sequence().to_grid_horizontal(), ), (Point2::new(0, 2), magic.clone()), (Point2::new(0, 3), process_list_editor.get_term_view()), @@ -104,8 +99,7 @@ async fn main() { let (w, h) = termion::terminal_size().unwrap(); compositor.write().unwrap().push( - plot_port - .outer() + plot_port.outer() .map_item(|pt, a| { a.add_style_back(TerminalStyle::fg_color(( 255 - pt.y as u8 * 8, @@ -124,7 +118,7 @@ async fn main() { compositor .write() .unwrap() - .push(table_port.outer().flatten().offset(Vector2::new(3, 0))); + .push(table.get_port().flatten().offset(Vector2::new(3, 0))); process_list_editor.goto(TreeCursor { leaf_mode: ListCursorMode::Insert, @@ -165,8 +159,7 @@ async fn main() { )); for c in match cur.leaf_mode { ListCursorMode::Insert => "INSERT", - ListCursorMode::Select => "SELECT", - ListCursorMode::Modify => "MODIFY", + ListCursorMode::Select => "SELECT" } .chars() { @@ -226,19 +219,19 @@ async fn main() { TerminalEvent::Input(Event::Key(Key::Up)) => { if process_list_editor.up() == TreeNavResult::Exit { process_list_editor.dn(); - process_list_editor.goto_home(); } } TerminalEvent::Input(Event::Key(Key::Down)) => { - if process_list_editor.dn() == TreeNavResult::Continue { - process_list_editor.goto_home(); - } + process_list_editor.dn(); + // == TreeNavResult::Continue { + //process_list_editor.goto_home(); + //} } TerminalEvent::Input(Event::Key(Key::Home)) => { - process_list_editor.goto_home(); + process_list_editor.qpxev(); } TerminalEvent::Input(Event::Key(Key::End)) => { - process_list_editor.goto_end(); + process_list_editor.qnexd(); } ev => { if process_list_editor.get_cursor().leaf_mode == ListCursorMode::Select { @@ -256,10 +249,10 @@ async fn main() { process_list_editor.nexd(); } TerminalEvent::Input(Event::Key(Key::Char('u'))) => { - process_list_editor.goto_home(); + process_list_editor.qpxev(); } TerminalEvent::Input(Event::Key(Key::Char('o'))) => { - process_list_editor.goto_end(); + process_list_editor.qnexd(); } _ => { process_list_editor.handle_terminal_event(&ev); diff --git a/shell/src/process.rs b/shell/src/process.rs index 27d4c27..c7f15bf 100644 --- a/shell/src/process.rs +++ b/shell/src/process.rs @@ -2,10 +2,10 @@ use { crate::pty::{PTYStatus, PTY}, nested::{ core::{OuterViewPort, ViewPort}, - list::{sexpr::ListDecoration, ListCursorMode, ListEditor, ListEditorStyle}, - sequence::{SequenceView, SequenceViewExt}, + list::{ListCursorMode, PTYListEditor}, + sequence::{SequenceView, SequenceViewExt, decorator::{SeqDecorStyle, Separate, Wrap}}, singleton::SingletonView, - string_editor::CharEditor, + char_editor::CharEditor, terminal::{ TerminalAtom, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView, @@ -15,13 +15,14 @@ use { std::sync::Arc, std::sync::RwLock, termion::event::{Event, Key}, + cgmath::Vector2 }; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> pub struct ProcessArg { editor: - ListEditor Arc> + Send + Sync + 'static>>, + PTYListEditor, } impl ProcessArg { @@ -30,7 +31,7 @@ impl ProcessArg { char_editor .read() .unwrap() - .get_data_port() + .get_port() .get_view() .unwrap() .get() @@ -41,10 +42,7 @@ impl ProcessArg { impl TerminalEditor for ProcessArg { fn get_term_view(&self) -> OuterViewPort { - self.editor - .get_seg_seq_view() - .to_grid_horizontal() - .flatten() + self.editor.get_term_view() } fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { @@ -64,32 +62,21 @@ impl TreeNav for ProcessArg { fn get_cursor(&self) -> TreeCursor { self.editor.get_cursor() } + fn get_cursor_warp(&self) -> TreeCursor { + self.editor.get_cursor_warp() + } fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { self.editor.goto(cur) } - fn goto_home(&mut self) -> TreeNavResult { - self.editor.goto_home() - } - fn goto_end(&mut self) -> TreeNavResult { - self.editor.goto_end() - } - fn pxev(&mut self) -> TreeNavResult { - self.editor.pxev() - } - fn nexd(&mut self) -> TreeNavResult { - self.editor.nexd() - } - fn up(&mut self) -> TreeNavResult { - self.editor.up() - } - fn dn(&mut self) -> TreeNavResult { - self.editor.dn() + fn goby(&mut self, dir: Vector2) -> TreeNavResult { + self.editor.goby(dir) } } +impl TerminalTreeEditor for ProcessArg {} + pub struct ProcessLauncher { - cmd_editor: - ListEditor Arc> + Send + Sync + 'static>>, + cmd_editor: PTYListEditor, pty: Option, _ptybox: Arc>, suspended: bool, @@ -109,16 +96,18 @@ impl ProcessLauncher { let box_port = ViewPort::::new(); let compositor = nested::terminal::TerminalCompositor::new(comp_port.inner()); - let cmd_editor = ListEditor::new( + let cmd_editor = PTYListEditor::new( Box::new(|| { Arc::new(RwLock::new(ProcessArg { - editor: ListEditor::new( + editor: PTYListEditor::new( Box::new(|| Arc::new(RwLock::new(CharEditor::new()))), - ListEditorStyle::Plain, + SeqDecorStyle::Plain, + 1 ), })) }) as Box Arc> + Send + Sync>, - ListEditorStyle::Plain, + SeqDecorStyle::HorizontalSexpr, + 0 ); compositor.write().unwrap().push( @@ -127,11 +116,7 @@ impl ProcessLauncher { .map_item(|_idx, x| x.add_style_back(TerminalStyle::fg_color((90, 120, 100)))), ); compositor.write().unwrap().push( - cmd_editor - .get_seg_seq_view() - .decorate("$(", ")", " ", 0) - .to_grid_horizontal() - .flatten(), + cmd_editor.get_term_view() ); ProcessLauncher { @@ -251,6 +236,9 @@ impl TreeNav for ProcessLauncher { fn get_cursor(&self) -> TreeCursor { self.cmd_editor.get_cursor() } + fn get_cursor_warp(&self) -> TreeCursor { + self.cmd_editor.get_cursor_warp() + } fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { self.suspended = false; @@ -269,27 +257,10 @@ impl TreeNav for ProcessLauncher { } } - fn goto_home(&mut self) -> TreeNavResult { - self.cmd_editor.goto_home() + fn goby(&mut self, dir: Vector2) -> TreeNavResult { + self.cmd_editor.goby(dir) } - fn goto_end(&mut self) -> TreeNavResult { - self.cmd_editor.goto_end() - } - - fn pxev(&mut self) -> TreeNavResult { - self.cmd_editor.pxev() - } - - fn nexd(&mut self) -> TreeNavResult { - self.cmd_editor.nexd() - } - - fn up(&mut self) -> TreeNavResult { - self.cmd_editor.up() - } - - fn dn(&mut self) -> TreeNavResult { - self.cmd_editor.dn() - } } + +impl TerminalTreeEditor for ProcessLauncher {} diff --git a/shell/src/pty.rs b/shell/src/pty.rs index e74edb8..cc5fb6f 100644 --- a/shell/src/pty.rs +++ b/shell/src/pty.rs @@ -57,7 +57,7 @@ impl PTY { if let Ok(child) = pair.slave.spawn_command(cmd) { let mut reader = pair.master.try_clone_reader().unwrap(); - let mut status_buf = SingletonBuffer::new( + let mut status_buf = SingletonBuffer::with_port( PTYStatus::Running { pid: child.process_id().expect(""), },