diff --git a/Cargo.toml b/Cargo.toml index c3f2dbd..fe2b93b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,5 @@ members = [ "examples/tty-04-posint", "examples/tty-05-dictionary", "examples/tty-06-lines", + "examples/tty-07-color", ] diff --git a/examples/tty-04-posint/src/main.rs b/examples/tty-04-posint/src/main.rs index 5f9e032..1a125b9 100644 --- a/examples/tty-04-posint/src/main.rs +++ b/examples/tty-04-posint/src/main.rs @@ -39,8 +39,8 @@ async fn main() { */ let ctx = Arc::new(RwLock::new(Context::new())); nested::editors::char::init_ctx( ctx.clone() ); - nested::editors::digit::init_ctx( ctx.clone() ); - nested::editors::integer::init_ctx( ctx.clone() ); + //nested::editors::digit::init_ctx( ctx.clone() ); + //nested::editors::integer::init_ctx( ctx.clone() ); nested::editors::list::init_ctx( ctx.clone() ); nested_tty::setup_edittree_hook(&ctx); @@ -49,23 +49,28 @@ async fn main() { */ let int_builder = ReprTreeBuilder::new( ctx.clone() ) .require(Context::parse(&ctx, - "ℕ ~ <PosInt 16 BigEndian> ~ EditTree")) + //"ℕ ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16>> ~ + "<List <Digit 16>> ~ <List Char> ~ EditTree")) + /* .require(Context::parse(&ctx, "ℕ ~ <PosInt 10 BigEndian> ~ EditTree")) .require(Context::parse(&ctx, "ℕ ~ <PosInt 8 BigEndian> ~ EditTree")) .require(Context::parse(&ctx, "ℕ ~ <PosInt 2 BigEndian> ~ EditTree")) + */ ; let mut rt_int = nested::repr_tree::ReprTree::from_str("3"); rt_int.write().unwrap().set_halo( /* HALO TYPE (append to top of type ladder) */ - Context::parse(&ctx, " + Context::parse(&ctx, /*" ℕ ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16>> + */ + " <List <Digit 16>> ~ <List Char> ") ); @@ -102,7 +107,7 @@ async fn main() { let first_idx : usize = 0; int_builder.update( &rt_int, int_builder.required_leaves[first_idx].clone() ); - edittree.goto(TreeCursor{ + edittree.goto(TreeCursor { leaf_mode: nested::editors::list::ListCursorMode::Insert, tree_addr: vec![first_idx as isize, 0] }); @@ -155,7 +160,6 @@ async fn main() { let halo_type = rt_edittree.read().unwrap().get_halo_type().clone(); let edittree = rt_edittree.edittree( &ctx ); - let box_port = ViewPort::new(); let ascii_box = nested_tty::widgets::ascii_box::AsciiBox::new( Vector2::new(30, 1), diff --git a/examples/tty-06-lines/src/line.rs b/examples/tty-06-lines/src/line.rs new file mode 100644 index 0000000..0fe9a70 --- /dev/null +++ b/examples/tty-06-lines/src/line.rs @@ -0,0 +1,257 @@ +use { + cgmath::{Point2}, + nested::{ + editors::{ + char::CharEditor, + list::{ListEditor, ListSegment, ListSegments}, + }, + repr_tree::{ + Context, + ReprTreeExt, + }, + }, + nested_tty::{TerminalAtom, TerminalStyle, TerminalView}, + r3vi::{ + buffer::{singleton::*, vec::*}, + projection::projection_helper::ProjectionHelper, + view::{ + grid::*, index::*, list::*, sequence::*, singleton::*, Observer, + ObserverBroadcast, OuterViewPort, View, ViewPort, + }, + }, + std::sync::{Arc, RwLock}, +}; + +#[derive(Clone)] +pub struct LineDiagnostic { + pub range: (u32, u32), + pub msg: String, +} + +pub struct LineEditor { + pub num_buf: SingletonBuffer<u64>, + pub diag_buf: VecBuffer<LineDiagnostic>, + chars_edit: Arc<RwLock<ListEditor>>, + out_port: ViewPort<dyn TerminalView>, + seg_count: usize, + view: Arc<RwLock<LineView>>, + cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>, +} + +pub struct LineView { + line_num: Arc<dyn SingletonView<Item = u64>>, + segments: Arc<dyn ListView<ListSegment>>, + diagnostics: Arc<dyn SequenceView<Item = LineDiagnostic>>, + proj_helper: ProjectionHelper<usize, LineEditor>, +} + +impl View for LineView { + type Msg = IndexArea<Point2<i16>>; +} + +impl IndexView<Point2<i16>> for LineView { + type Item = TerminalAtom; + + fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> { + let xoff = 6; + + let mut pos = pos.clone(); + pos.x -= xoff; + if pos.y == 0 { + // main line + if pos.x >= 0 { + match self.segments.get(&(pos.x as usize)) { + Some(ListSegment::InsertCursor) => Some(TerminalAtom::new( + '|', + TerminalStyle::fg_color((220, 80, 40)), + )), + Some(ListSegment::Item { editor, cur_dist }) => { + if let Some(e) = editor.get_edit::<CharEditor>() { + let c = e.read().unwrap().get(); + let mut style = TerminalStyle::default(); + let i = if cur_dist >= 0 { + pos.x as u32 + } else { + pos.x as u32 - 1 + }; + for d in self.diagnostics.iter() { + if d.range.0 <= i && d.range.1 > i { + style = TerminalStyle::bg_color((110, 80, 30)) + } + } + Some(TerminalAtom::new(c, style)) + } else { + Some(TerminalAtom::from('?')) + } + } + None => None, + } + } else if pos.x <= -2 { + // line number + let mut n = self.line_num.get(); + let digit_idx = -(pos.x + 2); + for _ in 0..digit_idx { + n /= 10; + } + Some(TerminalAtom::new( + char::from_digit((n % 10) as u32, 10).unwrap_or('?'), + TerminalStyle::fg_color((120, 120, 120)), + )) + } else { + None + } + } else if pos.y > 0 { + // optional diagnostic message + let diag_idx = pos.y as usize - 1; + if let Some(diag) = self.diagnostics.get(&diag_idx) { + if let Some(c) = diag.msg.chars().nth(pos.x as usize) { + Some(TerminalAtom::new( + c, + TerminalStyle::bg_color((20, 20, 0)) + .add(TerminalStyle::fg_color((220, 40, 40))), + )) + } else { + None + } + } else { + None + } + } else { + None + } + } + + fn area(&self) -> IndexArea<Point2<i16>> { + let xoff = 6; + let mut n = self.line_num.get(); + let mut n_digits = 0 as i16; + while n > 0 { + n_digits += 1; + n /= 10; + } + let diag_len = self + .diagnostics + .iter() + .map(|d| d.msg.chars().count() as i16) + .max() + .unwrap_or(0); + IndexArea::Range( + Point2::new(xoff - n_digits - 1, 0) + ..=Point2::new( + xoff + i16::max( + self.segments.len().unwrap_or(i16::MAX as usize) as i16, + diag_len, + ), + self.diagnostics.len().unwrap_or(i16::MAX as usize) as i16, + ), + ) + } +} + +impl LineEditor { + pub fn new( + ctx: &Arc<RwLock<Context>>, + n: u64, + chars_edit: Arc<RwLock<ListEditor>>, + ) -> Arc<RwLock<Self>> { + let num_buf = SingletonBuffer::new(n); + let diag_buf = VecBuffer::new(); + let chars_segs = ListSegments::new( + chars_edit.read().unwrap().get_cursor_port(), + chars_edit.read().unwrap().get_edittree_list(), + ); + let chars_segs_view = chars_segs.read().unwrap().get_view(); + + let out_port = ViewPort::new(); + + let mut proj_helper = ProjectionHelper::new(out_port.update_hooks.clone()); + let line_view = Arc::new(RwLock::new(LineView { + line_num: proj_helper.new_singleton_arg( + 0, + num_buf.get_port(), + |e: &mut LineEditor, _msg| { + e.cast.write().unwrap().notify(&IndexArea::Range( + (Point2::new(-100, 0)..=Point2::new(6, 0)), + )); + }, + ), + segments: proj_helper.new_list_arg(1, chars_segs_view, |e: &mut LineEditor, diff| { + let xoff = 6; + let mut l = &mut e.seg_count; + /* + eprintln!("line: (l={}) (diff={})", l, match diff { + ListDiff::Clear => format!("clear"), + ListDiff::Remove(idx) => format!("remove {}", idx), + ListDiff::Insert{idx,val} =>format!("insert {}", idx), + ListDiff::Update{idx, val}=>format!("update {}", idx) + }); + */ + match diff { + ListDiff::Clear => { + e.cast.write().unwrap().notify(&IndexArea::Range( + (Point2::new(xoff + 0 as i16, 0)..=Point2::new(xoff + *l as i16, 0)), + )); + *l = 0; + } + ListDiff::Remove(idx) => { + *l -= 1; + e.cast.write().unwrap().notify(&IndexArea::Range( + (Point2::new(xoff + *idx as i16, 0) + ..=Point2::new(xoff + *l as i16 + 1, 0)), + )); + } + ListDiff::Insert { idx, val } => { + *l += 1; + e.cast.write().unwrap().notify(&IndexArea::Range( + (Point2::new(xoff + *idx as i16, 0)..=Point2::new(xoff + *l as i16, 0)), + )); + } + ListDiff::Update { idx, val } => { + e.cast.write().unwrap().notify(&IndexArea::Range( + (Point2::new(xoff + *idx as i16, 0) + ..=Point2::new(xoff + *idx as i16, 0)), + )); + } + } + }), + diagnostics: proj_helper.new_sequence_arg( + 2, + diag_buf.get_port().to_sequence(), + |e: &mut LineEditor, idx| { + e.cast.write().unwrap().notify(&IndexArea::Range( + (Point2::new(-100, 1 + *idx as i16)..=Point2::new(100, 1 + *idx as i16)), + )); + }, + ), + + proj_helper, + })); + + out_port.set_view(Some(line_view.clone() as Arc<dyn TerminalView>)); + + let line_edit = Arc::new(RwLock::new(LineEditor { + num_buf, + diag_buf, + chars_edit, + cast: out_port.inner().get_broadcast(), + view: line_view.clone(), + seg_count: 0, + out_port, + })); + + line_view.write().unwrap().proj_helper.set_proj(&line_edit); + line_edit + } + + pub fn set_linum(&mut self, n: u64) { + self.num_buf.set(n); + } + + pub fn add_diag(&mut self, diag: LineDiagnostic) { + self.diag_buf.push(diag); + } + + pub fn get_port(&self) -> OuterViewPort<dyn TerminalView> { + self.out_port.outer() + } +} diff --git a/examples/tty-06-lines/src/lines.rs b/examples/tty-06-lines/src/lines.rs new file mode 100644 index 0000000..7419c4e --- /dev/null +++ b/examples/tty-06-lines/src/lines.rs @@ -0,0 +1,225 @@ +use { + crate::line::{LineDiagnostic, LineEditor}, + nested::{ + edit_tree::{EditTree}, + editors::list::{ListEditor}, + repr_tree::{ + Context, GenericReprTreeMorphism, ReprLeaf, ReprTree, ReprTreeArc, ReprTreeBuilder, + ReprTreeExt + }, + }, + nested_tty::{ + DisplaySegment, TerminalProjections, TerminalStyle, + }, + r3vi::{ + buffer::{singleton::*}, + }, + std::sync::{Arc, RwLock}, +}; + +pub struct LinesEditor { + ctx: Arc<RwLock<Context>>, + pub edit: EditTree, +} + +impl LinesEditor { + pub fn new(ctx: Arc<RwLock<Context>>) -> Self { + let typ = Context::parse(&ctx, "Line"); + let depth_port = SingletonBuffer::<usize>::new(0).get_port(); + + let list_edit = ListEditor::new(ctx.clone(), typ, ReprTreeBuilder::new(ctx.clone())); + + let morph_new_line = GenericReprTreeMorphism::new( + Context::parse(&ctx, "Line ~ Void"), + Context::parse(&ctx, "Line ~ <List Char> ~ <Vec Char>"), + { + let ctx = ctx.clone(); + move |line_rt, σ| { + let mut l = ReprTree::from_str(""); + l.write() + .unwrap() + .set_halo(Context::parse(&ctx, "<List Char>")); + l = ReprTree::rise(l); + line_rt.insert_branch(l); + line_rt + .write() + .unwrap() + .branches + .remove(&Context::parse(&ctx, "Void")); + eprintln!("make line: {}", line_rt.read().unwrap().fmt(&ctx, 0)); + } + }, + ); + ctx.write().unwrap().morphisms.add_morphism(morph_new_line); + + let line_to_edittree = GenericReprTreeMorphism::new( + Context::parse(&ctx, "Line ~ <List Char> ~ EditTree"), + Context::parse(&ctx, "Line ~ EditTree"), + { + let ctx = ctx.clone(); + move |line_rt, σ| { + let chars_edittree = line_rt + .descend(Context::parse(&ctx, "<List Char>")) + .expect("cant descend") + .edittree(&ctx) + .get(); + + let line = + LineEditor::new(&ctx, 0, chars_edittree.get_edit::<ListEditor>().unwrap()); + let line_port = line.read().unwrap().get_port(); + + let depth = SingletonBuffer::new(0).get_port(); + let mut line_edittree = EditTree::new(ctx.clone(), depth) + .set_nav(chars_edittree.ctrl.tree_nav.get().unwrap()) + .set_cmd(chars_edittree.ctrl.cmd.get().unwrap()) + .set_editor(line.clone()); + + line_edittree.disp.view.insert_leaf( + Context::parse(&ctx, "TerminalView"), + ReprLeaf::from_view(line_port), + ); + line_rt.insert_leaf( + Context::parse(&ctx, "EditTree"), + ReprLeaf::from_singleton_buffer(SingletonBuffer::new(line_edittree)), + ); + } + }, + ); + + ctx.write() + .unwrap() + .morphisms + .add_morphism(line_to_edittree); + + let lines_segments = nested::editors::list::ListSegments::new( + list_edit.get_cursor_port(), + list_edit.get_edittree_list(), + ) + .read() + .unwrap() + .get_view(); + let lines_view = lines_segments + .map({ + let ctx = ctx.clone(); + move |segment| match segment { + nested::editors::list::ListSegment::InsertCursor => { + nested_tty::make_label("..... |").with_fg_color((220, 80, 40)) + } + nested::editors::list::ListSegment::Item { editor, cur_dist } => { + if *cur_dist == 0 { + editor.display_view().map_item(|x, a| { + a.add_style_back(TerminalStyle::bg_color((50, 50, 50))) + }) + } else { + editor.display_view() + } + } + } + }) + .to_sequence() + .to_grid_vertical() + .flatten(); + + let mut list_edit = list_edit.into_node(depth_port); + { + nested_tty::editors::list::PTYListController::for_node(&mut list_edit, Some('\n'), None); + } + list_edit + .disp + .view + .write() + .unwrap() + .insert_branch(ReprTree::from_view( + Context::parse(&ctx, "TerminalView"), + lines_view, + )); + + LinesEditor { + // lines, + edit: list_edit, + ctx, + } + } + + pub fn add_line(&mut self, line_value: &str) -> ReprTreeArc { + let n = self + .edit + .get_edit::<ListEditor>() + .unwrap() + .read() + .unwrap() + .data + .len() as u64; + + let line_rt = self.make_line(line_value); + self.edit + .get_edit::<ListEditor>() + .unwrap() + .write() + .unwrap() + .insert(line_rt.clone()); + + line_rt + } + + pub fn make_line(&self, line_value: &str) -> ReprTreeArc { + let ctx = &self.ctx; + let rt_line = ReprTree::from_str(line_value); + rt_line + .write() + .unwrap() + .set_halo(Context::parse(&ctx, "Line ~ <List Char>")); + + let line_builder = ReprTreeBuilder::new(ctx.clone()) + .require(Context::parse(&ctx, "Line ~ <List Char> ~ <Vec Char>")) + .require(Context::parse(&ctx, "Line ~ EditTree")); + + line_builder + .build_from(rt_line) + .expect("cant build line reprtree") + } + + pub fn add_diagnostic(&mut self, line_num: usize, diag: LineDiagnostic) { + let line = self + .edit + .get_edit::<ListEditor>() + .expect("cant get list edit") + .read() + .unwrap() + .data + .get(line_num) + .edittree(&self.ctx) + .get() + .get_edit::<LineEditor>() + .expect("cant get line edit"); + + line.write().unwrap().diag_buf.push(diag); + } + /* + pub fn get_lines(&self) -> Vec<String> { + /* 1. get [[Char]] Repr + 2. call flatten + 3. read out as <Vec Char> repr + */ + + // TODO + let lines = self.edit.read().unwrap().get_edit::< ListEditor >().expect("cant get list edit") + .read().unwrap().data + .clone().into_inner() + .read().unwrap() + .iter() + .map(|line_edittree_arc| { + let line_edittree = line_edittree_arc.read().unwrap(); + line_edittree. + }) + } + + pub fn get(&self) -> String { + self.get_lines().iter() + .map(|l| + l.chars().chain(std::iter::once('\n')) + ).flatten() + .collect() + } + */ +} diff --git a/examples/tty-06-lines/src/main.rs b/examples/tty-06-lines/src/main.rs index 74683d7..e9da856 100644 --- a/examples/tty-06-lines/src/main.rs +++ b/examples/tty-06-lines/src/main.rs @@ -4,462 +4,82 @@ extern crate nested_tty; extern crate r3vi; extern crate termion; +mod line; +mod lines; + use { - cgmath::{Vector2, Point2}, + cgmath::{Vector2}, nested::{ - editors::{ObjCommander, char::CharEditor, list::{ListEditor, ListSegment, ListSegments}}, - repr_tree::{Context, ReprLeaf, ReprTreeBuilder, ReprTree, ReprTreeExt, ReprTreeArc, GenericReprTreeMorphism}, - edit_tree::{EditTree, TreeNav, TreeCursor} + edit_tree::{TreeCursor, TreeNav}, + editors::ObjCommander, + repr_tree::{Context, ReprTreeExt}, }, nested_tty::{ - DisplaySegment, TTYApplication, - TerminalCompositor, TerminalStyle, TerminalView, - TerminalAtom, TerminalEvent, - edit_tree::cursor_widget::TreeNavExt, - TerminalProjections - }, - r3vi::{ - buffer::{singleton::*, vec::*}, - view::{ - ObserverBroadcast, Observer, ObserverExt, View, ViewPort, OuterViewPort, - port::UpdateTask, list::*, sequence::*, singleton::*, index::*, grid::* - }, - projection::projection_helper::ProjectionHelper + edit_tree::cursor_widget::TreeNavExt, DisplaySegment, TTYApplication, + TerminalCompositor, }, std::sync::{Arc, RwLock}, }; -#[derive(Clone)] -struct LineDiagnostic { - range: (u32, u32), - msg: String -} - -struct LineEditor { - num_buf: SingletonBuffer< u64 >, - diag_buf: VecBuffer< LineDiagnostic >, - chars_edit: Arc<RwLock<ListEditor>>, - out_port: ViewPort< dyn TerminalView >, - seg_count: usize, - view: Arc<RwLock< LineView >>, - cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>, -} - -struct LineView { - line_num: Arc< dyn SingletonView<Item = u64> >, - segments: Arc< dyn ListView<ListSegment> >, - diagnostics: Arc< dyn SequenceView<Item = LineDiagnostic> >, - proj_helper: ProjectionHelper<usize, LineEditor> -} - -impl View for LineView { - type Msg = IndexArea<Point2<i16>>; -} - -impl IndexView<Point2<i16>> for LineView { - type Item = TerminalAtom; - - fn get(&self, pos: &Point2<i16>) -> Option< TerminalAtom > { - let xoff = 6; - - let mut pos = pos.clone(); - pos.x -= xoff; - if pos.y == 0 { - // main line - if pos.x >= 0 { - match self.segments.get(&(pos.x as usize)) { - Some(ListSegment::InsertCursor) => { - Some(TerminalAtom::new('|', TerminalStyle::fg_color((220, 80, 40)))) - } - Some(ListSegment::Item { editor, cur_dist }) => { - if let Some(e) = editor.get_edit::<CharEditor>() { - let c = e.read().unwrap().get(); - let mut style = TerminalStyle::default(); - let i = if cur_dist >= 0 { pos.x as u32 } else { pos.x as u32 - 1 }; - for d in self.diagnostics.iter() { - if d.range.0 <= i && d.range.1 > i { - style = TerminalStyle::bg_color((110, 80, 30)) - } - } - Some(TerminalAtom::new(c, style)) - } else { - Some(TerminalAtom::from('?')) - } - } - None => None - } - } else if pos.x <= -2 { - // line number - let mut n = self.line_num.get(); - let digit_idx = -(pos.x+2); - for _ in 0..digit_idx { n /= 10; } - Some( - TerminalAtom::new( - char::from_digit((n % 10) as u32, 10).unwrap_or('?'), - TerminalStyle::fg_color((120,120,120)) - ) - ) - } else { - None - } - } else if pos.y > 0 { - // optional diagnostic message - let diag_idx = pos.y as usize - 1; - if let Some(diag) = self.diagnostics.get(&diag_idx) { - if let Some(c) = diag.msg.chars().nth( pos.x as usize ) { - Some(TerminalAtom::new(c, - TerminalStyle::bg_color((20,20,0)) - .add(TerminalStyle::fg_color((220, 40, 40))) - )) - } else { - None - } - } else { - None - } - } else { - None - } - } - - fn area(&self) -> IndexArea<Point2<i16>> { - let xoff = 6; - let mut n = self.line_num.get(); - let mut n_digits = 0 as i16; - while n > 0 { n_digits += 1; n /= 10; } - let diag_len = self.diagnostics.iter().map(|d| d.msg.chars().count() as i16).max().unwrap_or(0); - IndexArea::Range( - Point2::new( xoff - n_digits - 1 , 0) ..= - Point2::new( - xoff + i16::max( - self.segments.len().unwrap_or(i16::MAX as usize) as i16, - diag_len - ), - self.diagnostics.len().unwrap_or(i16::MAX as usize) as i16, - ) - ) - } -} - -impl LineEditor { - pub fn new( - ctx: &Arc<RwLock<Context>>, - n: u64, - chars_edit: Arc<RwLock<ListEditor>> - ) -> Arc<RwLock<Self>> { - let num_buf = SingletonBuffer::new(n); - let diag_buf = VecBuffer::new(); - let chars_segs = ListSegments::new( - chars_edit.read().unwrap().get_cursor_port(), - chars_edit.read().unwrap().get_edittree_list() - ); - let chars_segs_view = chars_segs.read().unwrap().get_view(); - - let out_port = ViewPort::new(); - - let mut proj_helper = ProjectionHelper::new(out_port.update_hooks.clone()); - let line_view = Arc::new(RwLock::new(LineView { - line_num: proj_helper.new_singleton_arg(0, num_buf.get_port(), - |e: &mut LineEditor, _msg|{ - e.cast.write().unwrap() - .notify(&IndexArea::Range( - (Point2::new(-100, 0) ..= Point2::new(6, 0)) - )); - }), - segments: proj_helper.new_list_arg(1, chars_segs_view, - |e: &mut LineEditor, diff| { - let xoff = 6; - let mut l = &mut e.seg_count; - /* - eprintln!("line: (l={}) (diff={})", l, match diff { - ListDiff::Clear => format!("clear"), - ListDiff::Remove(idx) => format!("remove {}", idx), - ListDiff::Insert{idx,val} =>format!("insert {}", idx), - ListDiff::Update{idx, val}=>format!("update {}", idx) - }); - */ - match diff { - ListDiff::Clear => { - e.cast.write().unwrap() - .notify(&IndexArea::Range( - (Point2::new(xoff+0 as i16, 0) ..= Point2::new(xoff+*l as i16, 0)) - )); - *l = 0; - } - ListDiff::Remove(idx) => { - *l -= 1; - e.cast.write().unwrap() - .notify(&IndexArea::Range( - (Point2::new(xoff+*idx as i16, 0) ..= Point2::new(xoff+*l as i16+1, 0)) - )); - } - ListDiff::Insert{ idx, val } => { - *l += 1; - e.cast.write().unwrap() - .notify(&IndexArea::Range( - (Point2::new(xoff+*idx as i16, 0) ..= Point2::new(xoff+*l as i16, 0)) - )); - } - ListDiff::Update{ idx, val } => { - e.cast.write().unwrap() - .notify(&IndexArea::Range( - (Point2::new(xoff+*idx as i16, 0) ..= Point2::new(xoff+*idx as i16, 0)) - )); - } - } - }), - diagnostics: proj_helper.new_sequence_arg(2, diag_buf.get_port().to_sequence(), - |e: &mut LineEditor, idx| { - e.cast.write().unwrap() - .notify(&IndexArea::Range( - (Point2::new(-100, 1+*idx as i16) ..= Point2::new(100, 1+*idx as i16)) - )); - }), - - proj_helper, - })); - - out_port.set_view(Some(line_view.clone() as Arc<dyn TerminalView>)); - - let line_edit = Arc::new(RwLock::new(LineEditor { - num_buf, - diag_buf, - chars_edit, - cast: out_port.inner().get_broadcast(), - view: line_view.clone(), - seg_count: 0, - out_port, - })); - - line_view.write().unwrap().proj_helper.set_proj(&line_edit); - line_edit - } - - pub fn set_linum(&mut self, n: u64) { - self.num_buf.set(n); - } - - pub fn add_diag(&mut self, diag: LineDiagnostic) { - self.diag_buf.push(diag); - } - - pub fn get_port(&self) -> OuterViewPort<dyn TerminalView> { - self.out_port.outer() - } -} - -struct LinesEditor { - ctx: Arc<RwLock<Context>>, - edit: EditTree -} - -impl LinesEditor { - pub fn new(ctx: Arc<RwLock<Context>>) -> Self { - let typ = Context::parse(&ctx, "Line"); - let depth_port = SingletonBuffer::<usize>::new(0).get_port(); - - let list_edit = ListEditor::new(ctx.clone(), typ, ReprTreeBuilder::new(ctx.clone())); - - let morph_new_line = GenericReprTreeMorphism::new( - Context::parse(&ctx, "Line ~ Void"), - Context::parse(&ctx, "Line ~ <List Char> ~ <Vec Char>"), - { - let ctx = ctx.clone(); - move |line_rt, σ| { - let mut l = ReprTree::from_str(""); - l.write().unwrap().set_halo(Context::parse(&ctx, "<List Char>")); - l = ReprTree::rise(l); - line_rt.insert_branch(l); - line_rt.write().unwrap().branches.remove(&Context::parse(&ctx, "Void")); - eprintln!("make line: {}", line_rt.read().unwrap().fmt(&ctx, 0)); - } - }); - ctx.write().unwrap().morphisms.add_morphism( morph_new_line ); - - let line_to_edittree = GenericReprTreeMorphism::new( - Context::parse(&ctx, "Line ~ <List Char> ~ EditTree"), - Context::parse(&ctx, "Line ~ EditTree"), - { - let ctx = ctx.clone(); - move |line_rt, σ| { - let chars_edittree = line_rt - .descend(Context::parse(&ctx, "<List Char>")).expect("cant descend") - .edittree(&ctx).get(); - - let line = LineEditor::new(&ctx, 0, - chars_edittree.get_edit::<ListEditor>().unwrap()); - let line_port = line.read().unwrap().get_port(); - - let depth = SingletonBuffer::new(0).get_port(); - let mut line_edittree = EditTree::new(ctx.clone(), depth) - .set_nav( chars_edittree.ctrl.tree_nav.get().unwrap() ) - .set_cmd( chars_edittree.ctrl.cmd.get().unwrap() ) - .set_editor( line.clone() ); - - line_edittree.disp.view - .insert_leaf( - Context::parse(&ctx, "TerminalView"), - ReprLeaf::from_view( line_port ) - ); - line_rt.insert_leaf( - Context::parse(&ctx, "EditTree"), - ReprLeaf::from_singleton_buffer(SingletonBuffer::new( line_edittree )) - ); - } - } - ); - ctx.write().unwrap().morphisms.add_morphism( line_to_edittree ); - - let lines_segments = nested::editors::list::ListSegments::new( - list_edit.get_cursor_port(), - list_edit.get_edittree_list() - ).read().unwrap().get_view(); - let lines_view = lines_segments - .map({ - let ctx = ctx.clone(); - move |segment| match segment { - nested::editors::list::ListSegment::InsertCursor => { - nested_tty::make_label("..... |") - .with_fg_color((220, 80, 40)) - }, - nested::editors::list::ListSegment::Item { editor, cur_dist } => { - if *cur_dist == 0 { - editor.display_view() - .map_item(|x,a| a - .add_style_back(TerminalStyle::bg_color((50, 50, 50))) - ) - } else { - editor.display_view() - } - } - } - }) - .to_sequence() - .to_grid_vertical() - .flatten(); - - let mut list_edit = list_edit.into_node( depth_port ); - nested_tty::editors::list::PTYListController::for_node( &mut list_edit, Some('\n'), None ); - list_edit.disp.view.write().unwrap() - .insert_branch(ReprTree::from_view( - Context::parse(&ctx, "TerminalView"), - lines_view - )); - - LinesEditor { - // lines, - edit: list_edit, - ctx - } - } - - pub fn add_line(&mut self, line_value: &str) -> ReprTreeArc { - let n = self.edit.get_edit::< ListEditor >().unwrap() - .read().unwrap() - .data.len() as u64; - - let mut line_rt = self.make_line(line_value); - self.edit.get_edit::< ListEditor >().unwrap() - .write().unwrap() - .insert( line_rt.clone() ); - - line_rt - } - - pub fn make_line(&self, line_value: &str) -> ReprTreeArc { - let ctx = &self.ctx; - let mut rt_line = ReprTree::from_str(line_value); - rt_line.write().unwrap().set_halo(Context::parse(&ctx, "Line ~ <List Char>")); - - let line_builder = ReprTreeBuilder::new(ctx.clone()) - .require(Context::parse(&ctx, "Line ~ <List Char> ~ <Vec Char>")) - .require(Context::parse(&ctx, "Line ~ EditTree")); - - line_builder.build_from(rt_line).expect("cant build line reprtree") - } - - pub fn add_diagnostic(&mut self, line_num: usize, diag: LineDiagnostic) { - let mut line = self.edit - .get_edit::< ListEditor >().expect("cant get list edit") - .read().unwrap() - .data - .get(line_num) - .edittree(&self.ctx) - .get() - .get_edit::< LineEditor >().expect("cant get line edit"); - - line.write().unwrap().diag_buf.push(diag); - } -/* - pub fn get_lines(&self) -> Vec<String> { - /* 1. get [[Char]] Repr - 2. call flatten - 3. read out as <Vec Char> repr - */ - - // TODO - let lines = self.edit.read().unwrap().get_edit::< ListEditor >().expect("cant get list edit") - .read().unwrap().data - .clone().into_inner() - .read().unwrap() - .iter() - .map(|line_edittree_arc| { - let line_edittree = line_edittree_arc.read().unwrap(); - line_edittree. - }) - } - - pub fn get(&self) -> String { - self.get_lines().iter() - .map(|l| - l.chars().chain(std::iter::once('\n')) - ).flatten() - .collect() - } -*/ -} - #[async_std::main] async fn main() { /* setup context */ let ctx = Arc::new(RwLock::new(Context::new())); - nested::editors::char::init_ctx( ctx.clone() ); - nested::editors::digit::init_ctx( ctx.clone() ); - nested::editors::integer::init_ctx( ctx.clone() ); - nested::editors::list::init_ctx( ctx.clone() ); + nested::editors::char::init_ctx(ctx.clone()); + nested::editors::digit::init_ctx(ctx.clone()); + nested::editors::integer::init_ctx(ctx.clone()); + nested::editors::list::init_ctx(ctx.clone()); nested_tty::setup_edittree_hook(&ctx); let args: Vec<String> = std::env::args().collect(); let path = String::from(args.get(1).expect("no filename given")); - let mut lines_edit = LinesEditor::new(ctx.clone()); + let mut lines_edit = lines::LinesEditor::new(ctx.clone()); let iter_lines = iterate_text::file::lines::IterateFileLines::new(path.clone()); - for (i,line) in iter_lines.enumerate() { + for (i, line) in iter_lines.enumerate() { let mut sanitized_line = String::new(); for c in line.chars() { if c == '\t' { - for _ in 0..4 { sanitized_line.push(' '); } + for _ in 0..4 { + sanitized_line.push(' '); + } } else if c != '\n' { sanitized_line.push(c); } } let line = lines_edit.add_line(&sanitized_line); - line.edittree(&ctx).get() - .get_edit::<LineEditor>().unwrap() - .write().unwrap() - .num_buf.set(i as u64); + line.edittree(&ctx) + .get() + .get_edit::<line::LineEditor>() + .unwrap() + .write() + .unwrap() + .num_buf + .set(i as u64); } lines_edit.edit.goto(TreeCursor::home()); - lines_edit.add_diagnostic( 5, LineDiagnostic{ range: (5, 10), msg: "test diagnostic".into() } ); - lines_edit.add_diagnostic( 8, LineDiagnostic{ range: (6, 14), msg: "another test diagnostic".into() } ); + lines_edit.add_diagnostic( + 5, + line::LineDiagnostic { + range: (5, 10), + msg: "test diagnostic".into(), + }, + ); + lines_edit.add_diagnostic( + 8, + line::LineDiagnostic { + range: (6, 14), + msg: "another test diagnostic".into(), + }, + ); lines_edit.edit.goto(TreeCursor::home()); - let mut edit = lines_edit.edit.clone(); + let edit = lines_edit.edit.clone(); /* setup terminal */ diff --git a/examples/tty-07-color/Cargo.toml b/examples/tty-07-color/Cargo.toml index 53db651..d5299b8 100644 --- a/examples/tty-07-color/Cargo.toml +++ b/examples/tty-07-color/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "tty-06-color" +name = "tty-07-color" version = "0.1.0" edition = "2021" @@ -16,4 +16,3 @@ cgmath = "*" [dependencies.async-std] version = "1.9.0" features = ["unstable", "attributes"] - diff --git a/examples/tty-07-color/src/main.rs b/examples/tty-07-color/src/main.rs index e02ae87..afe5403 100644 --- a/examples/tty-07-color/src/main.rs +++ b/examples/tty-07-color/src/main.rs @@ -10,7 +10,7 @@ use { editors::{ ObjCommander }, - repr_tree::{Context, ReprTree, ReprTreeExt, ReprLeaf}, + repr_tree::{Context, ReprTree, ReprTreeBuilder, ReprTreeExt, ReprTreeArc, ReprLeaf}, edit_tree::{EditTree, TreeNav, TreeCursor} }, nested_tty::{ @@ -46,139 +46,57 @@ async fn main() { Context::parse(&ctx, "<Vec EditTree>") ); - let mut red = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, " - ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ <Vec Char> - "), - "221" - ); - ctx.read().unwrap().apply_morphism( &red, - &laddertypes::MorphismType { - src_type: Context::parse(&ctx, "ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10> ~ Char > ~ <Vec Char>"), - dst_type: Context::parse(&ctx, "ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > ~ EditTree") - }); - let red_edit = ctx.read().unwrap().setup_edittree( - red.descend(Context::parse(&ctx, " - ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16>~Char> - ")).unwrap(), - SingletonBuffer::new(0).get_port() - ).unwrap(); + let channel_builder = ReprTreeBuilder::new(ctx.clone()) + .require(Context::parse(&ctx, " + ℕ ~ <PosInt 10 BigEndian> ~ EditTree + ")) + .require(Context::parse(&ctx, " + ℕ ~ <PosInt 16 BigEndian> ~ EditTree + ")); - let mut green = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, " - ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ <Vec Char> - "), - "220" - ); - ctx.read().unwrap().apply_morphism( &green, - &laddertypes::MorphismType { - src_type: Context::parse(&ctx, "ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10> ~ Char > ~ <Vec Char>"), - dst_type: Context::parse(&ctx, "ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > ~ EditTree") - }); - let green_edit = ctx.read().unwrap().setup_edittree(green.descend(Context::parse(&ctx, " - ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16>~Char> - ")).unwrap(), - SingletonBuffer::new(0).get_port() - ).unwrap(); + let mut red = nested::repr_tree::ReprTree::from_str("221"); + red.write().unwrap().set_halo(Context::parse(&ctx, " + ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char> + ")); + red = channel_builder.build_from(red).expect(""); - - let mut blue = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, " - ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ <Vec Char> - "), - "5" - ); - ctx.read().unwrap().apply_morphism( &blue, - &laddertypes::MorphismType { - src_type: Context::parse(&ctx, "ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10> ~ Char > ~ <Vec Char>"), - dst_type: Context::parse(&ctx, "ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > ~ EditTree") - }); - let blue_edit = ctx.read().unwrap().setup_edittree( - blue.descend(Context::parse(&ctx, " - ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16>~Char> - ")).unwrap(), - SingletonBuffer::new(0).get_port() - ).unwrap(); + let mut green = nested::repr_tree::ReprTree::from_str("220"); + green.write().unwrap().set_halo(Context::parse(&ctx, " + ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char> + ")); + green = channel_builder.build_from(green).expect(""); + let mut blue = nested::repr_tree::ReprTree::from_str("150"); + blue.write().unwrap().set_halo(Context::parse(&ctx, " + ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char> + ")); + blue = channel_builder.build_from(blue).expect(""); + + let mut color_builder = ReprTreeBuilder::new(ctx.clone()) + .require(Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian>> ~ EditTree")) + .require(Context::parse(&ctx, "<List ℕ ~ <PosInt 10 BigEndian>> ~ EditTree")) + ; - eprintln!("======\n M A K E L I S T E D I T O R\n======\n"); - let mut color = nested::repr_tree::ReprTree::new_arc( Context::parse(&ctx, "<List ℕ>") ); - color.insert_leaf( Context::parse(&ctx, " - <List ℕ - ~ <PosInt 16 BigEndian> - ~ <Seq <Digit 16>> - ~ <List <Digit 16> - ~ Char > - > - ~ <List EditTree> - ~ <Vec EditTree> + < List ℕ ~ ReprTree > + ~ < Vec ReprTree > "), - - ReprLeaf::from_vec_buffer(VecBuffer::< - Arc<RwLock< EditTree >> - >::with_data(vec![ - red_edit.get(), - green_edit.get(), - blue_edit.get() - ])) + ReprLeaf::from_vec_buffer(VecBuffer::<ReprTreeArc>::with_data( + vec![ red, green, blue ]) + ) + ); +/* + color.attach_leaf_to( + Context::parse(&ctx, "< List ℕ ~ <PosInt 10 BigEndian> ~ EditTre >"), + color.descend(Context::parse(&ctx, "<List ℕ ~ ReprTree> ~ <Vec ReprTree>")) + .expect("descend") + . ); - ctx.read().unwrap().apply_morphism( - &color, - &laddertypes::MorphismType { - src_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > ~ EditTree > ~ <Vec EditTree>"), - dst_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > > ~ EditTree") - }); - let edit = ctx.read().unwrap().setup_edittree( - color.descend(Context::parse(&ctx, " - <List ℕ - ~ < PosInt 16 BigEndian > - ~ < Seq~List <Digit 16> - ~ Char > - > - ")).unwrap(), - SingletonBuffer::new(0).get_port() - ).unwrap(); - - - -eprintln!(" edittree => list list char "); - ctx.read().unwrap().apply_morphism( - &color, - &laddertypes::MorphismType { - src_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > > ~ EditTree"), - dst_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > >") - }); - -eprintln!("list char ==> list u64"); - ctx.read().unwrap().apply_morphism( - &color, - &laddertypes::MorphismType { - src_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char>>"), - dst_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ ℤ_2^64 ~ machine.UInt64>>") - }); -return; - - ctx.read().unwrap().apply_morphism( - &color, - &laddertypes::MorphismType { - src_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ ℤ_2^64 ~ machine.UInt64 > >"), - dst_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10> ~ Char > >") - }); - /* - let edit2 = ctx.read().unwrap().setup_edittree( - color.descend(Context::parse(&ctx, " - <List ℕ - ~ < PosInt 10 BigEndian > - ~ < Seq~List <Digit 10> - ~ Char > - > - ")).unwrap(), - SingletonBuffer::new(0).get_port() - ).unwrap(); */ - return; /* setup terminal @@ -187,12 +105,12 @@ return; /* event handler */ let ctx = ctx.clone(); - let edit = edit.get().clone(); + //let edit = edit.get().clone(); + + // edit.write().unwrap().goto(TreeCursor::home()); - edit.write().unwrap().goto(TreeCursor::home()); - move |ev| { - edit.write().unwrap().send_cmd_obj( ev.to_repr_tree(&ctx) ); + // edit.write().unwrap().send_cmd_obj( ev.to_repr_tree(&ctx) ); } }); @@ -213,7 +131,7 @@ return; let halo_type = rt_edittree.read().unwrap().get_halo_type().clone(); let edittree = rt_edittree.read().unwrap().get_view::<dyn r3vi::view::singleton::SingletonView<Item = Arc<RwLock<EditTree>>>>().unwrap().get().read().unwrap().clone(); - comp.push( nested_tty::make_label( &ctx.read().unwrap().type_term_to_str(&halo_type) ) + comp.push( nested_tty::make_label( &ctx.read().unwrap().type_term_to_str(&halo_type) ) .map_item(|_pt, atom| atom.add_style_front(TerminalStyle::fg_color((90,90,90)))) .offset(Vector2::new(1,y))); @@ -221,12 +139,11 @@ return; .offset(Vector2::new(1,y+1))); } - show_edit_tree( &ctx, &mut comp, &color.descend(Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16>~Char>>")).unwrap(), 1 ); - show_edit_tree( &ctx, &mut comp, &color.descend(Context::parse(&ctx, "<List ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char>>")).unwrap(), 3 ); + // show_edit_tree( &ctx, &mut comp, &color.descend(Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16>~Char>>")).unwrap(), 1 ); + // show_edit_tree( &ctx, &mut comp, &color.descend(Context::parse(&ctx, "<List ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char>>")).unwrap(), 3 ); } /* write the changes in the view of `term_port` to the terminal */ app.show().await.expect("output error!"); } - diff --git a/lib-nested-core/src/editors/list/ctx.rs b/lib-nested-core/src/editors/list/ctx.rs index 1d00b34..58ee1d5 100644 --- a/lib-nested-core/src/editors/list/ctx.rs +++ b/lib-nested-core/src/editors/list/ctx.rs @@ -261,7 +261,7 @@ pub fn init_ctx(ctx: Arc<RwLock<Context>>) { ctx.write().unwrap().add_varname("Item"); let list_morph_editsetup1 = GenericReprTreeMorphism::new( - Context::parse(&ctx, "<List Item>~<List ReprTree>~<Vec ReprTree>"), + Context::parse(&ctx, "<List~Vec Item~ReprTree>"), Context::parse(&ctx, "<List Item>~EditTree"), { let ctx = ctx.clone(); diff --git a/lib-nested-core/src/repr_tree/builder.rs b/lib-nested-core/src/repr_tree/builder.rs index 47002f6..ea8c541 100644 --- a/lib-nested-core/src/repr_tree/builder.rs +++ b/lib-nested-core/src/repr_tree/builder.rs @@ -1,23 +1,11 @@ use { - r3vi::{ - view::{ - ViewPort, OuterViewPort, - AnyViewPort, AnyInnerViewPort, AnyOuterViewPort, - port::UpdateTask, - View, Observer, - singleton::*, - sequence::*, - list::* - }, - buffer::{singleton::*, vec::*} - }, - laddertypes::{TypeTerm, TypeID, sugar::*}, - std::{ - collections::HashMap, - sync::{Arc, RwLock}, - any::Any - }, - super::{Context, ReprLeaf, ReprTree, ReprTreeExt, context::{TYPEID_list, TYPEID_vec, TYPEID_char, TYPEID_u64, TYPEID_edittree}} + super::{context::{TYPEID_char, TYPEID_edittree, TYPEID_list, TYPEID_u64, TYPEID_vec}, Context, ReprLeaf, ReprTree, ReprTreeExt}, laddertypes::{steiner_tree, sugar::*, unparser::UnparseLadderType as _, TypeID, TypeTerm}, r3vi::{ + buffer::{singleton::*, vec::*}, view::{ + list::*, port::UpdateTask, sequence::*, singleton::*, AnyInnerViewPort, AnyOuterViewPort, AnyViewPort, Observer, OuterViewPort, View, ViewPort + } + }, std::{ + any::Any, collections::HashMap, sync::{Arc, RwLock} + } }; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> @@ -65,8 +53,8 @@ impl ReprTreeBuilder { let morphism_base = &self.ctx.read().unwrap().morphisms; - let mt = master_leaf_type.into(); - //eprintln!("REBUILD repr tree from {}", self.ctx.read().unwrap().type_term_to_str(&mt)); + let mt = master_leaf_type.into().normalize().param_normalize(); + eprintln!("REBUILD repr tree from {}", self.ctx.read().unwrap().type_term_to_str(&mt)); let mut leaves = self.required_leaves.clone(); leaves.retain(|t| t != &mt); @@ -77,18 +65,32 @@ impl ReprTreeBuilder { if let Some( steiner_tree ) = st_problem.solve( &morphism_base ) { eprintln!("--> from {}", self.ctx.read().unwrap().type_term_to_str(&mt)); - for morphism_type in steiner_tree.into_edges() { + + let edges = steiner_tree.into_edges(); + eprintln!("steiner tree has {} edges", edges.len()); + for morphism_type in edges { eprintln!("--> morph to {}", self.ctx.read().unwrap().type_term_to_str(&morphism_type.dst_type)); - if let Some(( morphism, mut τ, σ )) = - morphism_base.find_morphism_with_subtyping( &morphism_type ) + let mut dict = self.ctx.read().unwrap().type_dict.clone(); + + if let Some(morph_inst) = + morphism_base.find_morphism( &morphism_type, &mut dict ) { - let mut rt = rt.descend_create( τ ).expect("descend src repr"); - (morphism.setup_projection)( &mut rt, &σ ); + eprintln!("setup morph"); + + let halo = laddertypes::common_halo( + &morphism_type.src_type, + &morphism_type.dst_type + ).unwrap_or(TypeTerm::unit()); + eprintln!("halo = {}", dict.read().unwrap().unparse(&halo)); + + let mut rt = rt.descend_create( halo ).expect("descend src repr"); + eprintln!("{}", rt.read().unwrap().fmt(&self.ctx, 0)); + (morph_inst.m.setup_projection)( &mut rt, &morph_inst.σ ); } else { eprintln!("failed to get morphism"); - //return Err(ReprTreeError::MissingMorphism); + return Err(ReprTreeError::MissingMorphism); } } diff --git a/lib-nested-core/src/repr_tree/context.rs b/lib-nested-core/src/repr_tree/context.rs index 8254090..8fdea0a 100644 --- a/lib-nested-core/src/repr_tree/context.rs +++ b/lib-nested-core/src/repr_tree/context.rs @@ -53,22 +53,28 @@ pub struct Context { impl Context { pub fn with_parent(parent: Option<Arc<RwLock<Context>>>) -> Self { - Context { - type_dict: match parent.as_ref() { - Some(p) => p.read().unwrap().type_dict.clone(), - None => { - let mut dict = BimapTypeDict::new(); - assert_eq!(TYPEID_reprtree, dict.add_typename("ReprTree".into())); - assert_eq!(TYPEID_edittree, dict.add_typename("EditTree".into())); - assert_eq!(TYPEID_char, dict.add_typename("Char".into())); - assert_eq!(TYPEID_u64, dict.add_typename("machine.UInt64".into())); - assert_eq!(TYPEID_list, dict.add_typename("List".into())); - assert_eq!(TYPEID_vec, dict.add_typename("Vec".into())); - Arc::new(RwLock::new(dict)) - } - }, - morphisms: MorphismBase::new(TYPEID_list), + let mut dict = match parent.as_ref() { + Some(p) => p.read().unwrap().type_dict.clone(), + None => { + let mut dict = BimapTypeDict::new(); + assert_eq!(TYPEID_reprtree, dict.add_typename("ReprTree".into())); + assert_eq!(TYPEID_edittree, dict.add_typename("EditTree".into())); + assert_eq!(TYPEID_char, dict.add_typename("Char".into())); + assert_eq!(TYPEID_u64, dict.add_typename("machine.UInt64".into())); + assert_eq!(TYPEID_list, dict.add_typename("List".into())); + assert_eq!(TYPEID_vec, dict.add_typename("Vec".into())); + + Arc::new(RwLock::new(dict)) + } + }; + + Context { + type_dict: dict.clone(), + morphisms: MorphismBase::new(vec![ + dict.parse("List").expect(""), + //dict.parse("Vec").expect("") + ]), nodes: HashMap::new(), list_types: match parent.as_ref() { Some(p) => p.read().unwrap().list_types.clone(), @@ -104,22 +110,9 @@ impl Context { pub fn apply_morphism(&self, rt: &Arc<RwLock<ReprTree>>, ty: &MorphismType) { if let Some(path) = self.morphisms.find_morphism_path(ty.clone().normalize()) { - let mut path = path.into_iter(); - if let Some(mut src_type) = path.next() { - for dst_type in path { - if let Some((m, mut τ, σ)) = - self.morphisms - .find_morphism_with_subtyping(&laddertypes::MorphismType { - src_type: src_type.clone(), - dst_type: dst_type.clone(), - }) - { - let mut rt = rt.descend(τ).expect("descend src repr"); - (m.setup_projection)(&mut rt, &σ); - } - - src_type = dst_type; - } + for morph_inst in path { + let mut rt = rt.descend(morph_inst.halo).expect("descend src repr"); + (morph_inst.m.setup_projection)(&mut rt, &morph_inst.σ); } } else { eprintln!("no path found"); diff --git a/lib-nested-core/src/repr_tree/morphism.rs b/lib-nested-core/src/repr_tree/morphism.rs index c5e5e8a..d841d94 100644 --- a/lib-nested-core/src/repr_tree/morphism.rs +++ b/lib-nested-core/src/repr_tree/morphism.rs @@ -27,13 +27,19 @@ pub struct GenericReprTreeMorphism { > } +impl PartialEq for GenericReprTreeMorphism { + fn eq(&self, other: &Self) -> bool { + self.morph_type == other.morph_type + } +} + impl Morphism for GenericReprTreeMorphism { fn get_type(&self) -> MorphismType { self.morph_type.clone() } - fn list_map_morphism(&self, list_typeid: TypeID) -> Option< GenericReprTreeMorphism > { - self.into_list_map_dyn(list_typeid) + fn map_morphism(&self, seq_type: TypeTerm) -> Option< GenericReprTreeMorphism > { + self.into_list_map_dyn(seq_type) } } @@ -54,7 +60,7 @@ impl GenericReprTreeMorphism { } } - pub fn into_list_map< SrcItem, DstItem >(&self, list_typeid: TypeID) + pub fn into_list_map< SrcItem, DstItem >(&self, seq_type: TypeTerm) -> GenericReprTreeMorphism where SrcItem: Clone + Send + Sync + 'static, @@ -62,11 +68,11 @@ impl GenericReprTreeMorphism { { let mut lst_map_type = MorphismType { src_type: TypeTerm::App(vec![ - TypeTerm::TypeID(list_typeid), + seq_type.clone(), self.morph_type.src_type.clone() ]), dst_type: TypeTerm::App(vec![ - TypeTerm::TypeID(list_typeid), + seq_type.clone(), self.morph_type.dst_type.clone() ]) }.normalize(); @@ -86,14 +92,13 @@ impl GenericReprTreeMorphism { "lst map type ::\n {:?}\n===> {:?}\n\n", lst_map_type.src_type, lst_map_type.dst_type ); - let mut item_ladder = item_morph.morph_type.src_type.clone().get_lnf_vec(); let top_type = item_ladder.remove( item_ladder.len() - 1 ); if let Ok(item_sigma) = laddertypes::unify( &top_type, &TypeTerm::App(vec![ - TypeTerm::TypeID( list_typeid ), + seq_type.clone(), TypeTerm::TypeID( TypeID::Var( 200 ) ) ]) ) { @@ -113,7 +118,7 @@ impl GenericReprTreeMorphism { top_type.clone(), r3vi::buffer::singleton::SingletonBuffer::new(x.clone()) ); - + // TODO: required? for t in item_ladder.iter().rev() { @@ -139,43 +144,43 @@ impl GenericReprTreeMorphism { } } - pub fn into_list_map_dyn(&self, typeid_list: TypeID) + pub fn into_list_map_dyn(&self, seq_type: TypeTerm) -> Option< GenericReprTreeMorphism > - { + { let src_item_type_lnf = self.morph_type.src_type.clone().get_lnf_vec(); let dst_item_type_lnf = self.morph_type.dst_type.clone().get_lnf_vec(); - eprintln!("into list map dyn"); + eprintln!("into list map dyn:\n src {:?}\n dst {:?}", src_item_type_lnf, dst_item_type_lnf); if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) && dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) { - Some( self.into_list_map::< char, char >(TYPEID_list) ) + Some( self.into_list_map::< char, char >( seq_type ) ) } else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_u64)) && dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_u64)) { - Some( self.into_list_map::< u64, u64 >(TYPEID_list) ) + Some( self.into_list_map::< u64, u64 >( seq_type ) ) } else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) && dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_u64)) { - Some( self.into_list_map::< char, u64 >(TYPEID_list) ) + Some( self.into_list_map::< char, u64 >( seq_type ) ) } else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_u64)) && dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) { - Some( self.into_list_map::< u64, char >(TYPEID_list) ) + Some( self.into_list_map::< u64, char >( seq_type ) ) } else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) && dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_edittree)) { - Some( self.into_list_map::< char, Arc<RwLock<crate::edit_tree::EditTree>> >(TYPEID_list) ) + Some( self.into_list_map::< char, Arc<RwLock<crate::edit_tree::EditTree>> >(seq_type) ) } else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_edittree)) && dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) { - Some( self.into_list_map::< Arc<RwLock<crate::edit_tree::EditTree>>, char >(TYPEID_list) ) + Some( self.into_list_map::< Arc<RwLock<crate::edit_tree::EditTree>>, char >(seq_type) ) } /* else if src_item_type_lnf.last() == Some(&TypeTerm::App(vec![ TypeTerm::TypeID(typeid_list), TypeTerm::TypeID(typeid_char) ])) && @@ -208,4 +213,3 @@ impl GenericReprTreeMorphism { } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> - diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..8bfb27f --- /dev/null +++ b/todo.md @@ -0,0 +1,27 @@ +# Workbench +* TreeType trait +* TypedCursor widget + +# Layouting +* Columns, word-oriented line breaks + +# Navigation +* save Cursor Gravity mode in editor +* find intuitive scheme to switch gravity mode + +# Editing +* Char Editor: escape chars \n \t etc. +* Range Seletcion +* Drag/Move + +# Refactor +* Proper Variable Scoping in Type Terms +* cleaner type substitutions +* TreeNavCmd via ObjCommander → remove tree_nav in NestedNode +* lib crates: add prelude +* rename + OuterViewPort -> OutPort + InnerViewPort -> InPort + AnyOuterViewPort -> AnyOutPort + AnyInnerViewPort -> AnyInPort +