diff --git a/nested/src/core/context.rs b/nested/src/core/context.rs index 5519265..a783512 100644 --- a/nested/src/core/context.rs +++ b/nested/src/core/context.rs @@ -1,7 +1,12 @@ use { - crate::core::{ - type_term::{TypeDict, TypeTerm}, - AnyOuterViewPort, OuterViewPort, View, + crate::{ + core::{ + type_term::{TypeDict, TypeTerm, TypeID}, + AnyOuterViewPort, OuterViewPort, View, + }, + tree_nav::{ + TerminalTreeEditor + } }, std::{ collections::HashMap, @@ -232,10 +237,20 @@ pub struct MorphismType { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> pub struct Context { + /// assigns a name to every type type_dict: TypeDict, + + /// objects + objects: HashMap, + + /// editors + editor_ctors: HashMap Option>> + Send + Sync>>, + + /// morphisms default_constructors: HashMap Object + Send + Sync>>, morphism_constructors: HashMap Object + Send + Sync>>, - objects: HashMap, + + /// recursion parent: Option>>, } @@ -243,6 +258,7 @@ impl Context { pub fn with_parent(parent: Option>>) -> Self { Context { type_dict: TypeDict::new(), + editor_ctors: HashMap::new(), default_constructors: HashMap::new(), morphism_constructors: HashMap::new(), objects: HashMap::new(), @@ -261,7 +277,27 @@ impl Context { pub fn type_term_from_str(&self, tn: &str) -> Option { self.type_dict.type_term_from_str(&tn) } + pub fn type_term_to_str(&self, t: &TypeTerm) -> String { + self.type_dict.type_term_to_str(&t) + } + pub fn add_editor_ctor(&mut self, tn: &str, mk_editor: Box Option>> + Send + Sync>) { + if let Some(tid) = self.type_dict.get_typeid(&tn.into()) { + self.editor_ctors.insert(tid, mk_editor); + } else { + println!("invalid type name"); + } + } + + pub fn make_editor(&self, type_term: TypeTerm) -> Option>> { + if let TypeTerm::Type{ id, args } = type_term.clone() { + let mk_editor = self.editor_ctors.get(&id)?; + mk_editor(self, type_term) + } else { + None + } + } + pub fn add_morphism( &mut self, morph_type: MorphismType, diff --git a/nested/src/core/mod.rs b/nested/src/core/mod.rs index 5197fed..4c0ba30 100644 --- a/nested/src/core/mod.rs +++ b/nested/src/core/mod.rs @@ -12,6 +12,6 @@ pub use { port::{ AnyInnerViewPort, AnyOuterViewPort, AnyViewPort, InnerViewPort, OuterViewPort, ViewPort, }, - type_term::{TypeDict, TypeID, TypeTerm}, + type_term::{TypeDict, TypeID, TypeTerm, TypeLadder}, view::View, }; diff --git a/nested/src/core/type_term.rs b/nested/src/core/type_term.rs index c691843..da064a8 100644 --- a/nested/src/core/type_term.rs +++ b/nested/src/core/type_term.rs @@ -3,6 +3,7 @@ use {crate::bimap::Bimap, std::collections::HashMap}; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> pub type TypeID = u64; +pub type TypeLadder = Vec; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> @@ -105,7 +106,7 @@ impl TypeTerm { pub fn to_str(&self, names: &HashMap) -> String { match self { TypeTerm::Type { id, args } => format!( - "( {} {})", + "« {} {}»", names[id], if args.len() > 0 { args.iter().fold(String::new(), |str, term| { @@ -141,6 +142,14 @@ impl TypeDict { self.type_id_counter += 1; } + pub fn get_typeid(&self, tn: &String) -> Option { + if let Some(id) = self.typenames.mλ.get(tn) { + Some(*id) + } else { + None + } + } + pub fn type_term_from_str(&self, typename: &str) -> Option { TypeTerm::from_str(typename, &self.typenames.mλ) } diff --git a/nested/src/core/view.rs b/nested/src/core/view.rs index 204c4b8..109999d 100644 --- a/nested/src/core/view.rs +++ b/nested/src/core/view.rs @@ -1,4 +1,4 @@ -/*\ + /*\ <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> View <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> diff --git a/nested/src/grid/flatten.rs b/nested/src/grid/flatten.rs index 9f1d52d..3fffc18 100644 --- a/nested/src/grid/flatten.rs +++ b/nested/src/grid/flatten.rs @@ -198,11 +198,11 @@ where let old_limit = self.limit; self.limit = Point2::new( (0..=top_range.end().x as usize) - .map(|x| col_widths[x]) + .map(|x| col_widths.get(x).unwrap_or(&0)) .sum::() - 1, (0..=top_range.end().y as usize) - .map(|y| row_heights[y]) + .map(|y| row_heights.get(y).unwrap_or(&0)) .sum::() - 1, ); diff --git a/nested/src/integer/editor.rs b/nested/src/integer/editor.rs index dd311c3..4f65b84 100644 --- a/nested/src/integer/editor.rs +++ b/nested/src/integer/editor.rs @@ -77,6 +77,8 @@ impl TerminalEditor for DigitEditor { } } +impl TerminalTreeEditor for DigitEditor {} + pub struct PosIntEditor { radix: u32, digits_editor: @@ -182,3 +184,6 @@ impl TerminalEditor for PosIntEditor { } } } + +impl TerminalTreeEditor for PosIntEditor {} + diff --git a/nested/src/lib.rs b/nested/src/lib.rs index 06a7f80..bda3e80 100644 --- a/nested/src/lib.rs +++ b/nested/src/lib.rs @@ -6,11 +6,13 @@ pub mod projection; pub mod grid; pub mod index; pub mod integer; +pub mod product; pub mod list; pub mod sequence; pub mod singleton; pub mod terminal; pub mod vec; +pub mod make_editor; pub mod tree_nav; diff --git a/nested/src/list/editor.rs b/nested/src/list/editor.rs index 40f551c..849f1a1 100644 --- a/nested/src/list/editor.rs +++ b/nested/src/list/editor.rs @@ -22,6 +22,7 @@ use { pub enum ListEditorStyle { HorizontalSexpr, VerticalSexpr, + Tuple(usize), Path, String, Clist, @@ -189,6 +190,7 @@ where return TreeNavResult::Continue; } + self.cursor.set(ListCursor::default()); TreeNavResult::Exit } } @@ -201,7 +203,7 @@ where } fn goto_home(&mut self) -> TreeNavResult { - let cur = self.cursor.get(); + let mut cur = self.cursor.get(); if self.data.len() == 0 && cur.idx.is_none() { self.cursor.set(ListCursor { mode: ListCursorMode::Insert, @@ -228,38 +230,38 @@ where } } 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(); + 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); + match cur_edit.goto_home() { + TreeNavResult::Exit => { + drop(cur_edit); - if let Some(i) = cur.idx { - self.up(); + if let Some(i) = cur.idx { + if i > 0 { + self.set_mode(ListCursorMode::Select); + self.pxev(); - if i > 0 { - self.set_mode(ListCursorMode::Select); - self.pxev(); + for _x in 1..depth { + self.dn(); + self.goto_end(); + } - for _x in 1..depth { self.dn(); - self.goto_end(); + self.set_leaf_mode(cur_mode); + //self.goto_home(); + return TreeNavResult::Continue; } - - self.set_leaf_mode(cur_mode); - self.dn(); - self.goto_home(); - return TreeNavResult::Continue; } } - - TreeNavResult::Exit - } - TreeNavResult::Continue => TreeNavResult::Continue, + TreeNavResult::Continue => { return TreeNavResult::Continue; } + }; } + + self.cursor.set(ListCursor::default()); + TreeNavResult::Exit } } } @@ -279,34 +281,42 @@ where TreeNavResult::Continue => {} } - return TreeNavResult::Continue; + TreeNavResult::Continue + } else { + TreeNavResult::Exit } + } else { + self.cursor.set(ListCursor { + mode: cur.mode, + idx: None, + }); + TreeNavResult::Exit } - - self.cursor.set(ListCursor { - mode: cur.mode, - idx: None, - }); - TreeNavResult::Exit } fn dn(&mut self) -> TreeNavResult { - let cur = self.cursor.get(); - 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.cur_dist.write().unwrap() += 1; + 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 } - TreeNavResult::Continue + ListCursorMode::Modify => self.get_item().unwrap().write().unwrap().dn(), } - ListCursorMode::Modify => self.get_item().unwrap().write().unwrap().dn(), } } @@ -397,7 +407,7 @@ where TreeNavResult::Exit => { drop(cur_edit); drop(ce); - self.up(); + //self.up(); if i + 1 < self.data.len() { self.set_mode(ListCursorMode::Select); @@ -405,14 +415,14 @@ where for _x in 1..depth { self.dn(); - self.goto_home(); } self.set_leaf_mode(cur_mode); self.dn(); - self.goto_home(); + TreeNavResult::Continue } else { + self.cursor.set(ListCursor::default()); TreeNavResult::Exit } } @@ -435,6 +445,7 @@ where 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(), @@ -474,10 +485,10 @@ where _ => { let new_edit = (self.make_item_editor)(); self.data.insert(idx, new_edit.clone()); - self.dn(); - self.goto_home(); + self.set_mode(ListCursorMode::Modify); + let mut ne = new_edit.write().unwrap(); - match new_edit.write().unwrap().handle_terminal_event(event) { + match ne.handle_terminal_event(event) { TerminalEditorResult::Exit => { self.cursor.set(ListCursor { mode: ListCursorMode::Insert, @@ -552,6 +563,12 @@ where } } +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, @@ -633,6 +650,13 @@ where .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) @@ -738,3 +762,4 @@ where self.goto(c); } } + diff --git a/nested/src/list/sexpr.rs b/nested/src/list/sexpr.rs index 70ffc3d..53c374f 100644 --- a/nested/src/list/sexpr.rs +++ b/nested/src/list/sexpr.rs @@ -224,6 +224,7 @@ impl VerticalSexprDecorator { 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 { diff --git a/nested/src/make_editor.rs b/nested/src/make_editor.rs new file mode 100644 index 0000000..975f741 --- /dev/null +++ b/nested/src/make_editor.rs @@ -0,0 +1,113 @@ + +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::editor::ProductEditor + }, + cgmath::{Point2, Vector2}, + std::{sync::{Arc, RwLock}, ops::{Deref, DerefMut}}, + termion::event::{Event, Key}, +}; + +pub fn make_editor(ctx: Arc>, t: &TypeLadder, depth: usize) -> Arc> { + let c = ctx.read().unwrap(); + if t[0] == c.type_term_from_str("( PosInt 16 BigEndian )").unwrap() { + Arc::new(RwLock::new(PosIntEditor::new(16))) as Arc> + + } else if t[0] == c.type_term_from_str("( PosInt 10 BigEndian )").unwrap() { + 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> + + } 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> + + } 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> + + } 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 + ))) 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> + + } else if t[0] == c.type_term_from_str("( RGB )").unwrap() { + Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone()) + .with_t("{ r: ") + .with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] ) + .with_t(", g: ") + .with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] ) + .with_t(", b: ") + .with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] ) + .with_t(" }") + )) as Arc> + + } else if t[0] == c.type_term_from_str("( Vec3i )").unwrap() { + Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone()) + .with_t("{ x: ") + .with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] ) + .with_t(", y: ") + .with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] ) + .with_t(", z: ") + .with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] ) + .with_t(" }") + )) 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> + + } else { // else: term + Arc::new(RwLock::new( + ProductEditor::new(depth, ctx.clone()) + .with_n( vec![ c.type_term_from_str("( List Char )").unwrap() ] ) + .with_n( vec![ c.type_term_from_str("( List Term )").unwrap() ] ) + )) as Arc> + } +} + + diff --git a/nested/src/product/editor.rs b/nested/src/product/editor.rs new file mode 100644 index 0000000..3a6a77e --- /dev/null +++ b/nested/src/product/editor.rs @@ -0,0 +1,456 @@ + +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}, + make_editor::make_editor + }, + cgmath::{Point2, Vector2}, + std::{sync::{Arc, RwLock}, ops::{Deref, DerefMut}}, + termion::event::{Event, Key}, +}; + +pub struct ProductEditor { + elements: VecBuffer, + n_indices: Vec, + + el_port: OuterViewPort>, + el_view_port: OuterViewPort>>, + + ctx: Arc>, + + cursor: Option, + depth: usize +} + +impl ProductEditor { + pub fn new(depth: usize, ctx: Arc>) -> Self { + let mut port = ViewPort::new(); + + let el_port = port.outer().to_sequence(); + let el_view_port = el_port.map({ + let ctx = ctx.clone(); + move |e: &ProductEditorElement| { e.get_view(ctx.clone()) } + }); + + ProductEditor { + elements: VecBuffer::new(port.inner()), + el_port, + el_view_port, + n_indices: Vec::new(), + + ctx, + + cursor: None, + depth + } + } + + pub fn with_t(mut self, t: &str) -> Self { + self.elements.push(ProductEditorElement::T(t.to_string())); + self + } + + pub fn with_n(mut self, n: TypeLadder) -> Self { + let elem_idx = self.elements.len(); + self.elements.push(ProductEditorElement::N{ + t: n, + editor: None, + select: false + }); + self.n_indices.push(elem_idx); + self + } + + fn get_editor_element(&self, idx: usize) -> Option { + if let Some(i) = self.n_indices.get(idx) { + Some(self.elements.get(*i)) + } else { + None + } + } + + fn get_editor_element_mut(&mut self, idx: usize) -> Option> { + if let Some(i) = self.n_indices.get(idx) { + Some(self.elements.get_mut(*i)) + } else { + None + } + } + + fn get_cur_element(&self) -> Option { + self.get_editor_element(self.cursor?) + } + + fn get_cur_element_mut(&mut self) -> Option> { + self.get_editor_element_mut(self.cursor?) + } + + fn get_editor(&self, idx: usize) -> Option>> { + if let Some(ProductEditorElement::N{ t: _, editor, select: _ }) = self.get_editor_element(idx) { + editor + } else { + None + } + } + + fn get_cur_editor(&self) -> Option>> { + self.get_editor(self.cursor?) + } + + fn set_leaf_mode(&mut self, mode: ListCursorMode) { + let mut c = self.get_cursor(); + c.leaf_mode = mode; + self.goto(c); + } +} + +impl TreeNav for ProductEditor { + fn get_cursor(&self) -> TreeCursor { + if let Some(i) = self.cursor { + if let Some(e) = self.get_editor(i) { + let mut c = e.read().unwrap().get_cursor(); + if c.tree_addr.len() == 0 { + c.leaf_mode = ListCursorMode::Select; + } + c.tree_addr.insert(0, i); + c + } else { + TreeCursor { + leaf_mode: ListCursorMode::Select, + tree_addr: vec![ i ] + } + } + } else { + TreeCursor::default() + } + } + + 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 Some(e) = editor { + e.write().unwrap().goto(TreeCursor::default()); + } + *select = false; + } + } + + if c.tree_addr.len() > 0 { + self.cursor = Some(c.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 Some(e) = editor { + e.write().unwrap().goto(c); + } + *select = true; + } + } + + TreeNavResult::Continue + } else { + self.cursor = None; + 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(e) = editor { + let mut ce = e.write().unwrap(); + + let cur_mode = ce.get_cursor().leaf_mode; + let depth = ce.get_cursor().tree_addr.len(); + + if depth > 0 { + return match ce.goto_home() { + TreeNavResult::Exit => { + drop(ce); + *select = false; + + match self.pxev() { + TreeNavResult::Exit => TreeNavResult::Exit, + TreeNavResult::Continue => { + for _x in 1..depth { + self.dn(); + self.goto_end(); + } + self.dn(); + self.set_leaf_mode(cur_mode); + + TreeNavResult::Continue + } + } + }, + TreeNavResult::Continue => TreeNavResult::Continue + }; + } + } + + *select = false; + 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; + } + return TreeNavResult::Continue; + } + } + } + self.cursor = None; + TreeNavResult::Exit + } + + 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(e) = editor { + let mut ce = e.write().unwrap(); + + let cur_mode = ce.get_cursor().leaf_mode; + let depth = ce.get_cursor().tree_addr.len(); + + if depth > 0 { + return match ce.goto_end() { + TreeNavResult::Exit => { + drop(ce); + *select = false; + + match self.nexd() { + TreeNavResult::Exit => TreeNavResult::Exit, + TreeNavResult::Continue => { + for _x in 1..depth { + self.dn(); + } + + self.dn(); + self.set_leaf_mode(cur_mode); + self.goto_end(); + + TreeNavResult::Continue + } + } + }, + TreeNavResult::Continue => TreeNavResult::Continue + }; + } + } + + *select = false; + 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; + } + return TreeNavResult::Continue; + } + } + } + self.cursor = None; + TreeNavResult::Exit + } + + 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(e) = editor { + let mut ce = e.write().unwrap(); + + let depth = ce.get_cursor().tree_addr.len(); + let cur_mode = ce.get_cursor().leaf_mode; + + if depth > 0 { + return match ce.pxev() { + TreeNavResult::Exit => { + drop(ce); + *select = false; + + 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; + } + + for _x in 1..depth { + self.dn(); + self.goto_end(); + } + + self.dn(); + self.set_leaf_mode(cur_mode); + self.goto_end(); + + TreeNavResult::Continue + } else { + TreeNavResult::Exit + } + } + TreeNavResult::Continue => TreeNavResult::Continue + }; + } + } + + *select = false; + 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; + } + return TreeNavResult::Continue; + } + } + } + + self.cursor = None; + TreeNavResult::Exit + } + + 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(e) = editor { + let mut ce = e.write().unwrap(); + + let depth = ce.get_cursor().tree_addr.len(); + let cur_mode = ce.get_cursor().leaf_mode; + + if depth > 0 { + return match ce.nexd() { + TreeNavResult::Exit => { + drop(ce); + *select = false; + + 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; + } + + for _x in 1..depth { + self.dn(); + } + + self.dn(); + self.set_leaf_mode(cur_mode); + + TreeNavResult::Continue + } else { + self.cursor = None; + TreeNavResult::Exit + } + } + TreeNavResult::Continue => TreeNavResult::Continue + }; + } + } + + *select = false; + 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; + } + + return TreeNavResult::Continue; + } + } + } + + self.cursor = None; + TreeNavResult::Exit + } + + fn up(&mut self) -> TreeNavResult { + if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() { + if let Some(e) = editor { + let mut ce = e.write().unwrap(); + if ce.get_cursor().tree_addr.len() > 0 { + ce.up(); + return TreeNavResult::Continue; + } + } + *select = false; + } + + self.cursor = None; + TreeNavResult::Exit + } + + 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(e) = editor { + e.write().unwrap().dn(); + } else { + let e = make_editor(self.ctx.clone(), t, self.depth+1); + e.write().unwrap().goto_home(); + *editor = Some(e); + } + } + } else { + self.cursor = Some(0); + if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() { + *select = true; + } + } + + TreeNavResult::Continue + } +} + +impl TerminalEditor for ProductEditor { + fn get_term_view(&self) -> OuterViewPort { + self.el_view_port.to_grid_horizontal().flatten() + } + + 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(e) = editor.clone() { + match e.clone().write().unwrap().handle_terminal_event(event) { + TerminalEditorResult::Exit => + match event { + TerminalEvent::Input(Event::Key(Key::Backspace)) => { + *editor = None; + TerminalEditorResult::Continue + } + _ => { + drop(e); + match self.nexd() { + TreeNavResult::Continue => TerminalEditorResult::Continue, + TreeNavResult::Exit => TerminalEditorResult::Exit + } + } + }, + TerminalEditorResult::Continue => + TerminalEditorResult::Continue + } + } 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); + x + } + } else { + TerminalEditorResult::Exit + } + } +} + +impl TerminalTreeEditor for ProductEditor {} + diff --git a/nested/src/product/element.rs b/nested/src/product/element.rs new file mode 100644 index 0000000..3387f86 --- /dev/null +++ b/nested/src/product/element.rs @@ -0,0 +1,74 @@ +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} + }, + cgmath::{Point2, Vector2}, + std::{sync::{Arc, RwLock}, ops::{Deref, DerefMut}}, + termion::event::{Event, Key}, +}; + + +#[derive(Clone)] +pub enum ProductEditorElement { + T( String ), + N { + t: TypeLadder, + editor: Option>>, + select: bool + } +} + +impl ProductEditorElement { + pub fn get_view(&self, ctx: Arc>) -> OuterViewPort { + match self { + ProductEditorElement::T(t) => + make_label(t.as_str()) + .map_item( + |i, x| + x.add_style_back(TerminalStyle::fg_color((0,120,200))) + ), + + ProductEditorElement::N {t: _, editor: Some(e), select} => + e.read().unwrap() + .get_term_view() + .map_item({ let select = *select; + 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() + } + ) + }), + + ProductEditorElement::N{t, editor: None, select} => + make_label(&ctx.read().unwrap().type_term_to_str(&t[0])) + .map_item({ let select = *select; + 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() + } + ) + }) + } + } +} + diff --git a/nested/src/product/mod.rs b/nested/src/product/mod.rs new file mode 100644 index 0000000..1e44f4b --- /dev/null +++ b/nested/src/product/mod.rs @@ -0,0 +1,4 @@ + +pub mod editor; +pub mod element; + diff --git a/nested/src/singleton/to_index.rs b/nested/src/singleton/to_index.rs index 85e919f..da39758 100644 --- a/nested/src/singleton/to_index.rs +++ b/nested/src/singleton/to_index.rs @@ -82,10 +82,10 @@ where { fn reset(&mut self, view: Option>) { self.src_view = view; - self.cast.notify(&IndexArea::Full); + self.cast.notify(&IndexArea::Set(vec![ () ])); } fn notify(&mut self, _: &()) { - self.cast.notify(&IndexArea::Full); + self.cast.notify(&IndexArea::Set(vec![ () ])); } } diff --git a/nested/src/string_editor.rs b/nested/src/string_editor.rs index 74f0599..a6e00e4 100644 --- a/nested/src/string_editor.rs +++ b/nested/src/string_editor.rs @@ -2,12 +2,12 @@ use { crate::{ core::{OuterViewPort, ViewPort}, list::{sexpr::ListDecoration, ListEditor}, - sequence::SequenceView, + sequence::{SequenceView, SequenceViewExt}, singleton::{SingletonBuffer, SingletonView}, terminal::{ TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView, }, - tree_nav::{TreeCursor, TreeNav, TreeNavResult}, + tree_nav::{TreeCursor, TreeNav, TreeNavResult, TerminalTreeEditor}, }, std::sync::Arc, std::sync::RwLock, @@ -62,6 +62,8 @@ impl TerminalEditor for CharEditor { } } +impl TerminalTreeEditor for CharEditor {} + //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> pub struct StringEditor { @@ -82,7 +84,18 @@ impl StringEditor { pub fn get_data_port(&self) -> OuterViewPort> { self.chars_editor .get_data_port() - .map(|char_editor| char_editor.read().unwrap().data.get().unwrap()) + .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() } } @@ -109,7 +122,7 @@ impl TreeNav for StringEditor { self.chars_editor.up() } fn dn(&mut self) -> TreeNavResult { - TreeNavResult::Exit + self.chars_editor.dn() } } @@ -133,3 +146,6 @@ impl TerminalEditor for StringEditor { } } } + +impl TerminalTreeEditor for StringEditor {} + diff --git a/nested/src/tree_nav.rs b/nested/src/tree_nav.rs index 757a1fb..800a82e 100644 --- a/nested/src/tree_nav.rs +++ b/nested/src/tree_nav.rs @@ -5,6 +5,7 @@ pub enum TreeNavResult { Continue, Exit, } + /* impl From for TerminalEditorResult { fn from(v: TreeNavResult) -> TerminalEditorResult { @@ -14,13 +15,23 @@ impl From for TerminalEditorResult { } } } -*/ + */ + #[derive(Clone, Eq, PartialEq)] pub struct TreeCursor { pub leaf_mode: ListCursorMode, pub tree_addr: Vec, } +impl TreeCursor { + pub fn home() -> Self { + TreeCursor { + leaf_mode: ListCursorMode::Select, + tree_addr: vec![0] + } + } +} + impl Default for TreeCursor { fn default() -> Self { TreeCursor { @@ -66,4 +77,5 @@ pub trait TreeNav { use crate::terminal::{TerminalEditor}; -pub trait TerminalTreeEditor = TerminalEditor + TreeNav; +pub trait TerminalTreeEditor : TerminalEditor + TreeNav + Send {} + diff --git a/nested/src/vec/mod.rs b/nested/src/vec/mod.rs index 3b081b5..2253a74 100644 --- a/nested/src/vec/mod.rs +++ b/nested/src/vec/mod.rs @@ -3,7 +3,7 @@ pub mod vec2bin; pub mod vec2json; pub mod vec2seq; -pub use buffer::VecBuffer; +pub use buffer::{VecBuffer, MutableVecAccess}; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>