From 21f7043ef050a7871f497032e56b89a5b199fd92 Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Fri, 14 Oct 2022 23:42:35 +0200 Subject: [PATCH] product editor: fix background color highlighting introduce update_segment() to simplify updating of meta information of segments --- nested/src/char_editor.rs | 5 +- nested/src/color.rs | 21 ++-- nested/src/list/nav.rs | 73 ++++++++++--- nested/src/list/segment.rs | 21 +++- nested/src/make_editor.rs | 43 +++++++- nested/src/product/editor.rs | 95 ++++++++++------- nested/src/product/nav.rs | 187 +++++++++++++++++----------------- nested/src/product/segment.rs | 44 +++++--- nested/src/tree_nav.rs | 2 +- shell/src/command.rs | 115 +++++++++++++++------ shell/src/main.rs | 100 +++++++++--------- 11 files changed, 449 insertions(+), 257 deletions(-) diff --git a/nested/src/char_editor.rs b/nested/src/char_editor.rs index 7b235f4..ce7b222 100644 --- a/nested/src/char_editor.rs +++ b/nested/src/char_editor.rs @@ -42,9 +42,8 @@ impl TerminalEditor for CharEditor { self.data .get_port() .map(move |c| { - TerminalAtom::new( - c.unwrap_or('?'), - TerminalStyle::fg_color((100, 140, 100)), + TerminalAtom::from( + c.unwrap_or('?') ) }) .to_grid() diff --git a/nested/src/color.rs b/nested/src/color.rs index 08aaec7..d723636 100644 --- a/nested/src/color.rs +++ b/nested/src/color.rs @@ -4,22 +4,19 @@ use { pub fn bg_style_from_depth(depth: usize) -> TerminalStyle { match depth { - 0 => TerminalStyle::default(), - 1 => TerminalStyle::bg_color((20,20,20)), - 2 => TerminalStyle::default(), - 3 => TerminalStyle::default(), - 4 => TerminalStyle::default(), - 5 => TerminalStyle::default(), - _ => TerminalStyle::bg_color((80,80,80)) + 1 => TerminalStyle::bg_color((40,40,40)), + _ => TerminalStyle::default(), } } 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)).add(TerminalStyle::bold(true)), - 2 => TerminalStyle::fg_color((80, 80, 200)), - 3 => TerminalStyle::fg_color((200, 80, 200)), + match depth % 6 { + 0 => TerminalStyle::fg_color((40, 180, 230)), + 1 => TerminalStyle::fg_color((120, 120, 120)), + 2 => TerminalStyle::fg_color((230, 180, 40)), + 3 => TerminalStyle::fg_color((80, 180, 200)), + 4 => TerminalStyle::fg_color((70, 90, 180)), + 5 => TerminalStyle::fg_color((200, 190, 70)), _ => TerminalStyle::default() } } diff --git a/nested/src/list/nav.rs b/nested/src/list/nav.rs index a1fbd39..e667fac 100644 --- a/nested/src/list/nav.rs +++ b/nested/src/list/nav.rs @@ -43,6 +43,11 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static 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; + } else { + return TreeCursor { + leaf_mode: ListCursorMode::Select, + tree_addr: vec![ i as isize - self.data.len() as isize ], + }; } } TreeCursor { @@ -68,12 +73,19 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static 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; + if sub_cur.tree_addr.len() > 0 { + sub_cur.tree_addr.insert(0, i as isize); + return sub_cur; + } else { + return TreeCursor { + leaf_mode: ListCursorMode::Select, + tree_addr: vec![ i ], + }; + } } } TreeCursor { - leaf_mode: cur.mode, + leaf_mode: ListCursorMode::Select, tree_addr: vec![], } } @@ -99,10 +111,22 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static TreeNavResult::Continue } 1 => { + let idx = crate::modulo(new_cur.tree_addr[0], if new_cur.leaf_mode == ListCursorMode::Insert { 1 } else { 0 } + self.data.len() as isize); + 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)), + idx: Some(idx), }); + + if new_cur.leaf_mode == ListCursorMode::Select { + let item = self.data.get_mut(idx as usize); + let mut item_edit = item.write().unwrap(); + item_edit.goto(TreeCursor { + leaf_mode: ListCursorMode::Select, + tree_addr: vec![] + }); + } + TreeNavResult::Continue } _ => { @@ -116,7 +140,6 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static 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(), @@ -137,11 +160,18 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static if direction.y < 0 { // up - self.cursor.set(ListCursor::none()); + self.cursor.set(ListCursor { + mode: cur.leaf_mode, + idx: None + }); TreeNavResult::Exit } else if direction.y > 0 { // dn - self.cursor.set(ListCursor::home()); + self.cursor.set(ListCursor { + mode: if self.data.len() > 0 { cur.leaf_mode } else { ListCursorMode::Insert }, + idx: Some(0) + }); + self.goby(Vector2::new(direction.x, direction.y-1)); TreeNavResult::Continue } else { @@ -168,8 +198,10 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static } else if direction.y < 0 { // up - - self.cursor.set(ListCursor::none()); + self.cursor.set(ListCursor { + mode: cur.leaf_mode, + idx: None + }); TreeNavResult::Exit } else { // horizontal @@ -179,13 +211,27 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static self.data.len() as isize + if cur.leaf_mode == ListCursorMode::Insert { 1 } else { 0 }) { + let idx = cur.tree_addr[0] + direction.x; self.cursor.set(ListCursor { mode: if self.data.len() == 0 { ListCursorMode::Insert } else { cur.leaf_mode }, - idx: Some(cur.tree_addr[0] + direction.x) + idx: Some(idx) }); + + if idx < self.data.len() as isize { + let item = self.data.get_mut(idx as usize); + let mut item_edit = item.write().unwrap(); + item_edit.goto(TreeCursor { + leaf_mode: cur.leaf_mode, + tree_addr: vec![] + }); + } + TreeNavResult::Continue } else { - self.cursor.set(ListCursor::none()); + self.cursor.set(ListCursor { + mode: cur.leaf_mode, + idx: None + }); TreeNavResult::Exit } } @@ -232,7 +278,10 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static self.goto(cur) } else { - self.cursor.set(ListCursor::none()); + self.cursor.set(ListCursor { + mode: cur.leaf_mode, + idx: None + }); TreeNavResult::Exit } } diff --git a/nested/src/list/segment.rs b/nested/src/list/segment.rs index ef0a147..09cbd0e 100644 --- a/nested/src/list/segment.rs +++ b/nested/src/list/segment.rs @@ -36,16 +36,27 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static ListSegment::InsertCursor => { make_label("|") .map_item(move |_pt, atom| { - atom.add_style_back(bg_style_from_depth(0)) - .add_style_back(TerminalStyle::bold(true)) + atom.add_style_front(TerminalStyle::fg_color((150,80,230))) + .add_style_front(TerminalStyle::bold(true)) }) } ListSegment::Item{ editor, depth, cur_dist } => { let e = editor.clone(); let d = *depth; + let cur_dist = *cur_dist; 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)) + let c = e.read().unwrap().get_cursor(); + let cur_depth = c.tree_addr.len(); + let select = + cur_dist == 0 && + if c.leaf_mode == ListCursorMode::Select { + cur_depth == 0 + } else { + cur_depth == 1 + }; + atom + .add_style_back(bg_style_from_depth(if select { 1 } else { 0 })) + .add_style_back(TerminalStyle::bold(select)) .add_style_back(fg_style_from_depth(d)) }) } @@ -110,7 +121,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static ListSegment::Item { editor: self.data.get(&(*idx - 1))?, depth: self.depth, - cur_dist: cur - (*idx as isize - 1) + cur_dist: cur - *idx as isize } } } diff --git a/nested/src/make_editor.rs b/nested/src/make_editor.rs index e807b66..14de5fd 100644 --- a/nested/src/make_editor.rs +++ b/nested/src/make_editor.rs @@ -33,6 +33,25 @@ pub fn make_editor(ctx: Arc>, t: &TypeLadder, depth: usize) -> A ) )) + } else if t[0] == c.type_term_from_str("( List String )").unwrap() { + 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("( String )").unwrap()], + d + ) + } + }), + SeqDecorStyle::EnumSet, + depth + ) + )) as Arc> + } else if t[0] == c.type_term_from_str("( List Char )").unwrap() { Arc::new(RwLock::new( PTYListEditor::new( @@ -40,7 +59,7 @@ pub fn make_editor(ctx: Arc>, t: &TypeLadder, depth: usize) -> A || { Arc::new(RwLock::new(CharEditor::new())) } ), SeqDecorStyle::Plain, - depth + depth+1 ) )) as Arc> @@ -56,10 +75,9 @@ pub fn make_editor(ctx: Arc>, t: &TypeLadder, depth: usize) -> A )) as Arc> } else if t[0] == c.type_term_from_str("( Path )").unwrap() { - let d = depth + 1; Arc::new(RwLock::new(PTYListEditor::new( Box::new({ - let d= depth +1; + let d= depth+1; move || { Arc::new(RwLock::new(PTYListEditor::new( Box::new(|| { @@ -73,6 +91,25 @@ pub fn make_editor(ctx: Arc>, t: &TypeLadder, depth: usize) -> A depth ))) as Arc> + } else if t[0] == c.type_term_from_str("( List Path )").unwrap() { + 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("( Path )").unwrap()], + d + ) + } + }), + SeqDecorStyle::EnumSet, + depth + ) + )) as Arc> + } else if t[0] == c.type_term_from_str("( List RGB )").unwrap() { Arc::new(RwLock::new( PTYListEditor::::new( diff --git a/nested/src/product/editor.rs b/nested/src/product/editor.rs index 2b9db9f..128e79a 100644 --- a/nested/src/product/editor.rs +++ b/nested/src/product/editor.rs @@ -38,7 +38,7 @@ impl ProductEditor { depth } } - + pub fn with_t(mut self, pos: Point2, t: &str) -> Self { self.segments.insert(pos, ProductEditorSegment::T(t.to_string(), self.depth)); self @@ -48,7 +48,9 @@ impl ProductEditor { self.segments.insert(pos, ProductEditorSegment::N{ t: n, editor: None, - cur_depth: 0 + ed_depth: self.depth + 1, + cur_depth: 0, + cur_dist: isize::MAX }); self.n_indices.push(pos); self @@ -81,7 +83,7 @@ impl ProductEditor { } pub fn get_editor(&self, idx: isize) -> Option>> { - if let ProductEditorSegment::N{ t: _, editor, cur_depth: _ } = self.get_editor_segment(idx) { + if let ProductEditorSegment::N{ t: _, editor, ed_depth: _, cur_depth: _, cur_dist: _ } = self.get_editor_segment(idx) { editor } else { unreachable!() @@ -97,6 +99,30 @@ impl ProductEditor { c.leaf_mode = mode; self.goto(c); } + + pub fn update_segment(&mut self, idx: isize) { + if let Some(ProductEditorSegment::N{ t: _, editor, ed_depth: _, cur_depth, cur_dist }) = self.get_editor_segment_mut(idx).deref_mut() { + let cur = self.get_cursor(); + + if cur.tree_addr.len() > 0 { + if cur.tree_addr[0] == idx { + *cur_depth = cur.tree_addr.len(); + } + + *cur_dist = cur.tree_addr[0] - idx + } else { + *cur_dist = isize::MAX; + }; + } else { + unreachable!() + } + } + + pub fn update_cur_segment(&mut self) { + if let Some(c) = self.cursor { + self.update_segment(c); + } + } } impl TerminalEditor for ProductEditor { @@ -110,40 +136,41 @@ impl TerminalEditor for ProductEditor { fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { if let Some(mut segment) = self.get_cur_segment_mut().as_deref_mut() { - if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = segment.deref_mut() { - *cur_depth = self.get_cursor().tree_addr.len(); - if let Some(e) = editor.clone() { - let mut ce = e.write().unwrap(); - match ce.handle_terminal_event(event) { - TerminalEditorResult::Exit => - match event { - TerminalEvent::Input(Event::Key(Key::Backspace)) => { - *editor = None; - *cur_depth = 1; - TerminalEditorResult::Continue - } - _ => { - *cur_depth = ce.get_cursor().tree_addr.len(); - drop(ce); - match self.nexd() { - TreeNavResult::Continue => TerminalEditorResult::Continue, - TreeNavResult::Exit => TerminalEditorResult::Exit + if let Some(ProductEditorSegment::N{ t, editor, ed_depth, cur_depth, cur_dist }) = segment.deref_mut() { + *cur_depth = self.get_cursor().tree_addr.len(); + + if let Some(e) = editor.clone() { + let mut ce = e.write().unwrap(); + match ce.handle_terminal_event(event) { + TerminalEditorResult::Exit => + match event { + TerminalEvent::Input(Event::Key(Key::Backspace)) => { + *editor = None; + *cur_depth = 1; + TerminalEditorResult::Continue } - } - }, - TerminalEditorResult::Continue => { - *cur_depth = ce.get_cursor().tree_addr.len(); - TerminalEditorResult::Continue + _ => { + *cur_depth = ce.get_cursor().tree_addr.len(); + drop(ce); + match self.nexd() { + TreeNavResult::Continue => TerminalEditorResult::Continue, + TreeNavResult::Exit => TerminalEditorResult::Exit + } + } + }, + TerminalEditorResult::Continue => { + *cur_depth = ce.get_cursor().tree_addr.len(); + TerminalEditorResult::Continue + } } + } else { + let e = make_editor(self.ctx.clone(), t, *ed_depth+1); + *editor = Some(e.clone()); + e.write().unwrap().dn(); + let x = e.write().unwrap().handle_terminal_event(event); + *cur_depth = e.write().unwrap().get_cursor().tree_addr.len(); + x } - } else { - let e = make_editor(self.ctx.clone(), t, self.depth+1); - *editor = Some(e.clone()); - e.write().unwrap().dn(); - let x = e.write().unwrap().handle_terminal_event(event); - *cur_depth = e.write().unwrap().get_cursor().tree_addr.len(); - x - } } else { unreachable!() } diff --git a/nested/src/product/nav.rs b/nested/src/product/nav.rs index 803e9b2..a0d8338 100644 --- a/nested/src/product/nav.rs +++ b/nested/src/product/nav.rs @@ -52,13 +52,14 @@ impl TreeNav for ProductEditor { } fn goto(&mut self, mut c: TreeCursor) -> TreeNavResult { + let old_cursor = self.cursor; + if let Some(mut segment) = self.get_cur_segment_mut() { - if let Some(ProductEditorSegment::N{ t: _t, editor, cur_depth }) = segment.deref_mut() { + if let Some(ProductEditorSegment::N{ t: _t, editor, ed_depth, cur_depth, cur_dist:_ }) = segment.deref_mut() { if let Some(e) = editor { let mut e = e.write().unwrap(); e.goto(TreeCursor::none()); } - *cur_depth = 0; } } @@ -66,23 +67,34 @@ impl TreeNav for ProductEditor { self.cursor = Some(crate::modulo(c.tree_addr.remove(0), self.n_indices.len() as isize)); if let Some(mut element) = self.get_cur_segment_mut() { - if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() { + if let Some(ProductEditorSegment::N{ t, editor, ed_depth, cur_depth, cur_dist:_ }) = element.deref_mut() { if let Some(e) = editor { e.write().unwrap().goto(c.clone()); } else if c.tree_addr.len() > 0 { // create editor - let e = make_editor(self.ctx.clone(), t, self.depth+1); + let e = make_editor(self.ctx.clone(), t, *ed_depth+1); *editor = Some(e.clone()); let mut e = e.write().unwrap(); e.goto(c.clone()); } - *cur_depth = c.tree_addr.len(); } } + if let Some(i) = old_cursor{ + self.update_segment(i); + } + + if let Some(i) = self.cursor { + self.update_segment(i); + } + TreeNavResult::Continue } else { self.cursor = None; + + if let Some(i) = old_cursor { + self.update_segment(i); + } TreeNavResult::Exit } } @@ -94,12 +106,7 @@ impl TreeNav for ProductEditor { 0 => { if direction.y > 0 { self.cursor = Some(0); - - if let Some(mut element) = self.get_cur_segment_mut() { - if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() { - *cur_depth = 1; - } - } + self.update_segment(0); self.goby(Vector2::new(direction.x, direction.y-1)); TreeNavResult::Continue @@ -113,134 +120,130 @@ impl TreeNav for ProductEditor { if direction.y > 0 { // dn if let Some(mut element) = self.get_cur_segment_mut() { - if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() { + if let Some(ProductEditorSegment::N{ t, editor, ed_depth, cur_depth, cur_dist:_ }) = element.deref_mut() { if let Some(e) = editor { let mut e = e.write().unwrap(); e.goby(direction); - *cur_depth = e.get_cursor().tree_addr.len() + 1; } else { // create editor - let e = make_editor(self.ctx.clone(), t, self.depth+1); + let e = make_editor(self.ctx.clone(), t, *ed_depth+1); *editor = Some(e.clone()); let mut e = e.write().unwrap(); e.goby(direction); - *cur_depth = e.get_cursor().tree_addr.len() + 1; } } } + + self.update_segment(cur.tree_addr[0]); TreeNavResult::Continue } else if direction.y < 0 { // up - if let Some(mut element) = self.get_cur_segment_mut() { - if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() { - *cur_depth = 0; - } - } + let old_cursor = self.cursor; self.cursor = None; + if let Some(i) = old_cursor { + self.update_segment(i); + } TreeNavResult::Exit } else { - if let Some(mut element) = self.get_cur_segment_mut() { - if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() { - *cur_depth = 0; - } - } + let old_cursor = self.cursor; - // horizontal if (cur.tree_addr[0]+direction.x >= 0) && (cur.tree_addr[0]+direction.x < self.n_indices.len() as isize) { - if let Some(mut element) = self.get_cur_segment_mut() { - if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() { - *cur_depth = 0; - } - } - self.cursor = Some(cur.tree_addr[0] + direction.x); - if let Some(mut element) = self.get_cur_segment_mut() { - if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() { - *cur_depth = 1; - } + + self.update_cur_segment(); + if let Some(i) = old_cursor { + self.update_segment(i); } TreeNavResult::Continue } else { self.cursor = None; + if let Some(i) = old_cursor { + self.update_segment(i); + } TreeNavResult::Exit } } } depth => { - if let Some(mut element) = self.get_cur_segment_mut() { - if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() { - if let Some(e) = editor { - let mut ce = e.write().unwrap(); - //\\//\\//\\//\\ - // horizontal // - //\\//\\//\\//\\ - match ce.goby(direction) { - TreeNavResult::Exit => { - *cur_depth = 1; - drop(ce); - drop(e); + let old_cursor = self.cursor; + let nav_result = + if let Some(mut element) = self.get_cur_segment_mut() { + if let Some(ProductEditorSegment::N{ t, editor, ed_depth, cur_depth, cur_dist:_ }) = element.deref_mut() { + if let Some(e) = editor { + let mut ce = e.write().unwrap(); + //\\//\\//\\//\\ + // horizontal // + //\\//\\//\\//\\ + match ce.goby(direction) { + TreeNavResult::Exit => { + *cur_depth = 1; + drop(ce); + drop(e); - if direction.y < 0 { - if depth <= (1-direction.y) as usize { - // up - *cur_depth = 1; - TreeNavResult::Continue - } else { - panic!("unplausible direction.y on exit"); - TreeNavResult::Continue - } - } else if direction.y > 0 { - // dn - *cur_depth = depth + direction.y as usize; - - TreeNavResult::Continue - } else if direction.y == 0 { - // horizontal - - if direction.x != 0 { - *cur_depth = 0; - } - - if (cur.tree_addr[0]+direction.x >= 0) && - (cur.tree_addr[0]+direction.x < self.n_indices.len() as isize) - { - if direction.x < 0 { - cur.tree_addr[0] -= 1; - for i in 1..depth { - cur.tree_addr[i] = -1; - } + if direction.y < 0 { + if depth <= (1-direction.y) as usize { + // up + TreeNavResult::Continue } else { - cur.tree_addr[0] += 1; - for i in 1..depth { - cur.tree_addr[i] = 0; - } + panic!("unplausible direction.y on exit"); + TreeNavResult::Continue + } + } else if direction.y > 0 { + // dn + TreeNavResult::Continue + } else if direction.y == 0 { + // horizontal + + if direction.x != 0 { + *cur_depth = 0; } - self.goto(cur) + if (cur.tree_addr[0]+direction.x >= 0) && + (cur.tree_addr[0]+direction.x < self.n_indices.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 = None; + TreeNavResult::Exit + } } else { - self.cursor = None; - TreeNavResult::Exit + TreeNavResult::Continue } - } else { + } + TreeNavResult::Continue => { TreeNavResult::Continue } } - TreeNavResult::Continue => { - *cur_depth = (depth as isize + direction.y - 1) as usize; - TreeNavResult::Continue - } + } else { + TreeNavResult::Continue } } else { TreeNavResult::Continue } } else { TreeNavResult::Continue - } - } else { - TreeNavResult::Continue + }; + + if let Some(i) = old_cursor { + self.update_segment(i); } + + self.update_cur_segment(); + return nav_result; } } } diff --git a/nested/src/product/segment.rs b/nested/src/product/segment.rs index b984a69..84587f2 100644 --- a/nested/src/product/segment.rs +++ b/nested/src/product/segment.rs @@ -5,6 +5,7 @@ use { TerminalEditor, TerminalStyle, TerminalView, make_label }, + list::{ListCursorMode}, tree_nav::{TerminalTreeEditor}, color::{bg_style_from_depth, fg_style_from_depth} }, @@ -18,7 +19,9 @@ pub enum ProductEditorSegment { N { t: TypeLadder, editor: Option>>, - cur_depth: usize + ed_depth: usize, + cur_depth: usize, + cur_dist: isize } } @@ -30,30 +33,47 @@ impl ProductEditorSegment { .map_item({ let depth = *depth; move |i, x| - x.add_style_back(fg_style_from_depth(depth)) + x.add_style_back(fg_style_from_depth(depth)).add_style_back(TerminalStyle::italic(true)) } ), - ProductEditorSegment::N { t: _, editor: Some(e), cur_depth } => + ProductEditorSegment::N { t: _, editor: Some(e), ed_depth, cur_depth, cur_dist } => e.read().unwrap() .get_term_view() .map_item({ let e = e.clone(); + let d = *ed_depth; + let cur_dist = *cur_dist; + move |i, x| { - let cur_depth = e.read().unwrap().get_cursor().tree_addr.len(); - x - .add_style_back(fg_style_from_depth(cur_depth))//fg_color((250,210,0))) - .add_style_back(bg_style_from_depth(cur_depth)) + let c = e.read().unwrap().get_cursor(); + let cur_depth = c.tree_addr.len(); + let select = + cur_dist == 0 && + if c.leaf_mode == ListCursorMode::Select { + cur_depth == 0 + } else { + cur_depth == 1 + }; + + return x + .add_style_back(bg_style_from_depth(if select { 1 } else { 0 })) + .add_style_back(TerminalStyle::bold(select)) + .add_style_back(fg_style_from_depth(d)); } }), - ProductEditorSegment::N{ t, editor: None, cur_depth } => + ProductEditorSegment::N{ t, editor: None, ed_depth, cur_depth, cur_dist } => make_label(&ctx.read().unwrap().type_term_to_str(&t[0])) .map_item({ - let cur_depth = 0; - move |i, x| x - .add_style_back(TerminalStyle::fg_color((130,90,40))) - .add_style_back(bg_style_from_depth(cur_depth)) + let cur_depth = *cur_depth; + let ed_depth = *ed_depth; + let cur_dist = *cur_dist; + + move |i, x| + x.add_style_back(TerminalStyle::fg_color((130,90,40))) + .add_style_back(bg_style_from_depth(if cur_dist == 0 { 1 } else { 0 })) + .add_style_back(TerminalStyle::bold(cur_dist == 0)) }) } } diff --git a/nested/src/tree_nav.rs b/nested/src/tree_nav.rs index e56a70e..3079c4a 100644 --- a/nested/src/tree_nav.rs +++ b/nested/src/tree_nav.rs @@ -36,7 +36,7 @@ impl TreeCursor { pub fn none() -> Self { TreeCursor { - leaf_mode: ListCursorMode::Insert, + leaf_mode: ListCursorMode::Select, tree_addr: vec![], } } diff --git a/shell/src/command.rs b/shell/src/command.rs index 359fb28..b1ef614 100644 --- a/shell/src/command.rs +++ b/shell/src/command.rs @@ -29,22 +29,35 @@ trait Action { pub struct ActCd {} impl Action for ActCd { fn make_editor(&self, ctx: Arc>) -> Arc> { - make_editor( - ctx.clone(), - &vec![ctx.read().unwrap().type_term_from_str("( Path )").unwrap()], - 1 - ) + let depth = 1; + Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone()) + .with_n(Point2::new(0, 0), vec![ ctx.read().unwrap().type_term_from_str("( Path )").unwrap() ] ) + )) as Arc> + } +} + +pub struct ActLs {} +impl Action for ActLs { + fn make_editor(&self, ctx: Arc>) -> Arc> { + let depth = 1; + Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone()) + .with_t(Point2::new(1, 0), " Files") + .with_n(Point2::new(0, 0), vec![ ctx.read().unwrap().type_term_from_str("( List Path )").unwrap() ] ) + .with_t(Point2::new(1, 1), " Options") + .with_n(Point2::new(0, 1), vec![ ctx.read().unwrap().type_term_from_str("( List String )").unwrap() ] ) + + )) as Arc> } } pub struct ActEcho {} impl Action for ActEcho { fn make_editor(&self, ctx: Arc>) -> Arc> { - make_editor( - ctx.clone(), - &vec![ctx.read().unwrap().type_term_from_str("( String )").unwrap()], - 2 - ) + let depth = 1; + Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone()) + .with_n(Point2::new(0, 0), vec![ ctx.read().unwrap().type_term_from_str("( String )").unwrap() ] ) + + )) as Arc> } } @@ -53,12 +66,12 @@ impl Action for ActCp { fn make_editor(&self, ctx: Arc>) -> Arc> { let depth = 1; Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone()) - .with_t(Point2::new(0, 0), "Source ") - .with_n(Point2::new(1, 0), vec![ ctx.read().unwrap().type_term_from_str("( Path )").unwrap() ] ) - .with_t(Point2::new(0, 1), "Destination ") - .with_n(Point2::new(1, 1), vec![ ctx.read().unwrap().type_term_from_str("( Path )").unwrap() ] ) - .with_t(Point2::new(0, 2), "Options ") - .with_n(Point2::new(1, 2), vec![ ctx.read().unwrap().type_term_from_str("( List String )").unwrap() ] ) + .with_t(Point2::new(1, 1), " Source") + .with_n(Point2::new(0, 1), vec![ ctx.read().unwrap().type_term_from_str("( Path )").unwrap() ] ) + .with_t(Point2::new(1, 2), " Destination") + .with_n(Point2::new(0, 2), vec![ ctx.read().unwrap().type_term_from_str("( Path )").unwrap() ] ) + .with_t(Point2::new(1, 3), " Options") + .with_n(Point2::new(0, 3), vec![ ctx.read().unwrap().type_term_from_str("( List String )").unwrap() ] ) )) as Arc> } } @@ -67,6 +80,8 @@ pub struct Commander { ctx: Arc>, cmds: HashMap>, + valid: Arc>, + confirmed: bool, symbol_editor: PTYListEditor, cmd_editor: Option>>, @@ -87,17 +102,33 @@ impl Commander { 0 ); - view_elements.push(symbol_editor.get_term_view()); + let valid = Arc::new(RwLock::new(false)); + view_elements.push(symbol_editor + .get_term_view() + .map_item({ + let valid = valid.clone(); + move + |pos, mut a| { + if *valid.read().unwrap() { + a.add_style_front(TerminalStyle::fg_color((0,255,0))) + } else { + a.add_style_front(TerminalStyle::fg_color((255,0,0))) + } + } + })); let mut cmds = HashMap::new(); + cmds.insert("cd".into(), Arc::new(ActCd{}) as Arc); cmds.insert("echo".into(), Arc::new(ActEcho{}) as Arc); - cmds.insert("ls".into(), Arc::new(ActCd{}) as Arc); + cmds.insert("ls".into(), Arc::new(ActLs{}) as Arc); cmds.insert("cp".into(), Arc::new(ActCp{}) as Arc); let mut c = Commander { ctx, cmds, + valid, + confirmed: false, symbol_editor, cmd_editor: None, view_elements, @@ -118,7 +149,7 @@ impl TerminalEditor for Commander { } fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { - if let Some(cmd_editor) = self.cmd_editor.as_ref() { + if let (Some(cmd_editor), true) = (self.cmd_editor.as_ref(), self.confirmed) { match event { TerminalEvent::Input(Event::Key(Key::Char('\n'))) => { // run @@ -133,16 +164,12 @@ impl TerminalEditor for Commander { 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.ctx.clone()); - + if let Some(editor) = &self.cmd_editor { + self.confirmed = true; self.symbol_editor.up(); - self.view_elements.push(editor.read().unwrap().get_term_view()); - editor.write().unwrap().qpxev(); - self.cmd_editor = Some(editor); + + *self.view_elements.get_mut(1) = editor.read().unwrap().get_term_view(); if *event == TerminalEvent::Input(Event::Key(Key::Char('\n'))) { return self.handle_terminal_event(event); @@ -155,7 +182,31 @@ impl TerminalEditor for Commander { } event => { - self.symbol_editor.handle_terminal_event(event) + let res = self.symbol_editor.handle_terminal_event(event); + + let symbol = self.symbol_editor.get_string(); + + if let Some(action) = self.cmds.get(&symbol) { + let editor = action.make_editor(self.ctx.clone()); + + if self.view_elements.len() == 1 { + self.view_elements.push(editor.read().unwrap().get_term_view().map_item(|p,a| a.add_style_front(TerminalStyle::fg_color((80,80,80))))); + } else { + *self.view_elements.get_mut(1) = editor.read().unwrap().get_term_view().map_item(|p,a| a.add_style_front(TerminalStyle::fg_color((80,80,80)))); + } + + self.cmd_editor = Some(editor); + *self.valid.write().unwrap() = true; + } else { + self.cmd_editor = None; + *self.valid.write().unwrap() = false; + + if self.view_elements.len() > 1 { + self.view_elements.remove(1); + } + } + + res } } } @@ -164,28 +215,28 @@ impl TerminalEditor for Commander { impl TreeNav for Commander { fn get_cursor(&self) -> TreeCursor { - if let Some(cmd_editor) = self.cmd_editor.as_ref() { + if let (Some(cmd_editor), true) = (self.cmd_editor.as_ref(), self.confirmed) { cmd_editor.write().unwrap().get_cursor() } else { self.symbol_editor.get_cursor() } } fn get_cursor_warp(&self) -> TreeCursor { - if let Some(cmd_editor) = self.cmd_editor.as_ref() { + if let (Some(cmd_editor), true) = (self.cmd_editor.as_ref(), self.confirmed) { cmd_editor.write().unwrap().get_cursor_warp() } else { self.symbol_editor.get_cursor_warp() } } fn goby(&mut self, dir: Vector2) -> TreeNavResult { - if let Some(cmd_editor) = self.cmd_editor.as_ref() { + if let (Some(cmd_editor), true) = (self.cmd_editor.as_ref(), self.confirmed) { cmd_editor.write().unwrap().goby(dir) } else { self.symbol_editor.goby(dir) } } fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { - if let Some(cmd_editor) = self.cmd_editor.as_ref() { + if let (Some(cmd_editor), true) = (self.cmd_editor.as_ref(), self.confirmed) { cmd_editor.write().unwrap().goto(cur) } else { self.symbol_editor.goto(cur) diff --git a/shell/src/main.rs b/shell/src/main.rs index 36404d8..5b030f4 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -17,7 +17,7 @@ use { core::{port::UpdateTask, Observer, OuterViewPort, ViewPort, Context, TypeTerm}, index::IndexArea, list::{ListCursorMode, PTYListEditor}, - sequence::{decorator::{SeqDecorStyle}}, + sequence::{decorator::{SeqDecorStyle, Separate}}, terminal::{ make_label, Terminal, TerminalAtom, TerminalCompositor, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView, @@ -42,22 +42,37 @@ async fn main() { async_std::task::spawn(async move { loop { tp.update(); - async_std::task::sleep(std::time::Duration::from_millis(20)).await; + async_std::task::sleep(std::time::Duration::from_millis(30)).await; } }); + + // Type Context // + let mut ctx = Arc::new(RwLock::new(Context::new())); + for tn in vec![ + "MachineWord", "MachineInt", "MachineSyllab", "Bits", + "Vec", "Stream", "Json", + "Sequence", "AsciiString", "UTF-8-String", "Char", "String", + "PosInt", "Digit", "LittleEndian", "BigEndian", + "DiffStream", "ℕ", "List", "Path", "Term", "RGB", "Vec3i" + ] { ctx.write().unwrap().add_typename(tn.into()); } + + let mut process_list_editor = PTYListEditor::new( + Box::new({let ctx = ctx.clone(); move || Arc::new(RwLock::new(Commander::new(ctx.clone())))}), +/* + Box::new({ + let ctx = ctx.clone(); + move || nested::make_editor::make_editor( + ctx.clone(), + &vec![ctx.read().unwrap().type_term_from_str("( List String )").unwrap()], + 1 + )}), +*/ + SeqDecorStyle::VerticalSexpr, + 0 + ); async_std::task::spawn(async move { let mut table = nested::index::buffer::IndexBuffer::new(); - - // Type Context // - let mut ctx = Arc::new(RwLock::new(Context::new())); - for tn in vec![ - "MachineWord", "MachineInt", "MachineSyllab", "Bits", - "Vec", "Stream", "Json", - "Sequence", "AsciiString", "UTF-8-String", "Char", "String", - "PosInt", "Digit", "LittleEndian", "BigEndian", - "DiffStream", "ℕ", "List", "Path", "Term", "RGB", "Vec3i" - ] { ctx.write().unwrap().add_typename(tn.into()); } let magic = make_label("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>").map_item(|pos, atom| { @@ -71,11 +86,6 @@ async fn main() { let mut cur_size = nested::singleton::SingletonBuffer::new(Vector2::new(10, 10)); let mut status_chars = VecBuffer::new(); - let mut process_list_editor = PTYListEditor::new( - Box::new({let ctx = ctx.clone(); move || Arc::new(RwLock::new(Commander::new(ctx.clone())))}), - SeqDecorStyle::VerticalSexpr, - 0 - ); let mut plist = VecBuffer::new(); let mut plist_port = plist.get_port(); @@ -115,12 +125,18 @@ async fn main() { status_chars.get_port().to_sequence().to_grid_horizontal(), ), (Point2::new(0, 2), magic.clone()), - - (Point2::new(0, 4), process_list_editor.get_term_view()), + (Point2::new(0, 3), make_label(" ")), + (Point2::new(0, 4), + process_list_editor + .editor + .get_seg_seq_view() + .separate(make_label(" ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~").map_item(|p,a| a.add_style_front(TerminalStyle::fg_color((40,40,40))))) + .to_grid_vertical() + .flatten()), ]); let (w, h) = termion::terminal_size().unwrap(); - +/* compositor.write().unwrap().push( plot_port.outer() .map_item(|pt, a| { @@ -137,7 +153,7 @@ async fn main() { .write() .unwrap() .push(monstera::make_monstera().offset(Vector2::new(w as i16 - 38, 0))); - +*/ compositor .write() .unwrap() @@ -250,37 +266,19 @@ async fn main() { TerminalEvent::Input(Event::Key(Key::End)) => { process_list_editor.qnexd(); } + TerminalEvent::Input(Event::Key(Key::Char('\t'))) => { + let mut c = process_list_editor.get_cursor(); + c.leaf_mode = match c.leaf_mode { + ListCursorMode::Select => ListCursorMode::Insert, + ListCursorMode::Insert => ListCursorMode::Select + }; + process_list_editor.goto(c); + } ev => { - if process_list_editor.get_cursor().leaf_mode == ListCursorMode::Select { - match ev { - TerminalEvent::Input(Event::Key(Key::Char('l'))) => { - process_list_editor.up(); - } - TerminalEvent::Input(Event::Key(Key::Char('a'))) => { - process_list_editor.dn(); - } - TerminalEvent::Input(Event::Key(Key::Char('i'))) => { - process_list_editor.pxev(); - } - TerminalEvent::Input(Event::Key(Key::Char('e'))) => { - process_list_editor.nexd(); - } - TerminalEvent::Input(Event::Key(Key::Char('u'))) => { - process_list_editor.qpxev(); - } - TerminalEvent::Input(Event::Key(Key::Char('o'))) => { - process_list_editor.qnexd(); - } - _ => { - process_list_editor.handle_terminal_event(&ev); - } - } - } else { - if let TerminalEditorResult::Exit = - process_list_editor.handle_terminal_event(&ev) - { - process_list_editor.nexd(); - } + if let TerminalEditorResult::Exit = + process_list_editor.handle_terminal_event(&ev) + { + //process_list_editor.nexd(); } } }