diff --git a/examples/tty-06-lines/src/main.rs b/examples/tty-06-lines/src/main.rs index 357f593..74683d7 100644 --- a/examples/tty-06-lines/src/main.rs +++ b/examples/tty-06-lines/src/main.rs @@ -7,8 +7,8 @@ extern crate termion; use { cgmath::{Vector2, Point2}, nested::{ - editors::{ObjCommander, char::CharEditor, list::{ListEditor, ListSegment, ListSegmentSequence}}, - repr_tree::{Context, ReprLeaf, ReprTree, ReprTreeExt, GenericReprTreeMorphism}, + editors::{ObjCommander, char::CharEditor, list::{ListEditor, ListSegment, ListSegments}}, + repr_tree::{Context, ReprLeaf, ReprTreeBuilder, ReprTree, ReprTreeExt, ReprTreeArc, GenericReprTreeMorphism}, edit_tree::{EditTree, TreeNav, TreeCursor} }, nested_tty::{ @@ -20,7 +20,10 @@ use { }, r3vi::{ buffer::{singleton::*, vec::*}, - view::{ObserverBroadcast, Observer, ObserverExt, View, ViewPort, OuterViewPort, port::UpdateTask, list::*, sequence::*, singleton::*, index::*, grid::*}, + view::{ + ObserverBroadcast, Observer, ObserverExt, View, ViewPort, OuterViewPort, + port::UpdateTask, list::*, sequence::*, singleton::*, index::*, grid::* + }, projection::projection_helper::ProjectionHelper }, std::sync::{Arc, RwLock}, @@ -37,13 +40,14 @@ struct LineEditor { diag_buf: VecBuffer< LineDiagnostic >, chars_edit: Arc>, out_port: ViewPort< dyn TerminalView >, + seg_count: usize, view: Arc>, cast: Arc>>, } struct LineView { line_num: Arc< dyn SingletonView >, - segments: Arc< dyn SequenceView >, + segments: Arc< dyn ListView >, diagnostics: Arc< dyn SequenceView >, proj_helper: ProjectionHelper } @@ -141,15 +145,15 @@ impl LineEditor { pub fn new( ctx: &Arc>, n: u64, + chars_edit: Arc> ) -> Arc> { let num_buf = SingletonBuffer::new(n); let diag_buf = VecBuffer::new(); - let chars_edit = ListEditor::new( - ctx.clone(), - Context::parse(&ctx, "") + let chars_segs = ListSegments::new( + chars_edit.read().unwrap().get_cursor_port(), + chars_edit.read().unwrap().get_edittree_list() ); - let chars_seg_seq = ListSegmentSequence::new(chars_edit.get_cursor_port(), chars_edit.get_edittree_seq() ) - .read().unwrap().get_view(); + let chars_segs_view = chars_segs.read().unwrap().get_view(); let out_port = ViewPort::new(); @@ -159,15 +163,50 @@ impl LineEditor { |e: &mut LineEditor, _msg|{ e.cast.write().unwrap() .notify(&IndexArea::Range( - (Point2::new(-100, 0) ..= Point2::new(0, 0)) + (Point2::new(-100, 0) ..= Point2::new(6, 0)) )); }), - segments: proj_helper.new_sequence_arg(1, chars_seg_seq, - |e: &mut LineEditor, idx| { - e.cast.write().unwrap() - .notify(&IndexArea::Range( - (Point2::new(*idx as i16, 0) ..= Point2::new(*idx as i16, 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| { @@ -180,12 +219,15 @@ impl LineEditor { proj_helper, })); + out_port.set_view(Some(line_view.clone() as Arc)); + let line_edit = Arc::new(RwLock::new(LineEditor { num_buf, diag_buf, - chars_edit: Arc::new(RwLock::new(chars_edit)), + chars_edit, cast: out_port.inner().get_broadcast(), view: line_view.clone(), + seg_count: 0, out_port, })); @@ -208,33 +250,69 @@ impl LineEditor { struct LinesEditor { ctx: Arc>, - edit: Arc> + edit: EditTree } impl LinesEditor { pub fn new(ctx: Arc>) -> Self { - let typ = Context::parse(&ctx, ""); + let typ = Context::parse(&ctx, "Line"); let depth_port = SingletonBuffer::::new(0).get_port(); - let list_edit = ListEditor::new(ctx.clone(), typ); + 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 ~ ~ "), + { + let ctx = ctx.clone(); + move |line_rt, σ| { + let mut l = ReprTree::from_str(""); + l.write().unwrap().set_halo(Context::parse(&ctx, "")); + 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 ~ "), + Context::parse(&ctx, "Line ~ ~ EditTree"), Context::parse(&ctx, "Line ~ EditTree"), - |rt, σ| { - eprintln!("LINE EDITOR CONSTRUCT"); -/* - rt.insert_branch( - Context::parse(&ctx, "EditTree"), + { + let ctx = ctx.clone(); + move |line_rt, σ| { + let chars_edittree = line_rt + .descend(Context::parse(&ctx, "")).expect("cant descend") + .edittree(&ctx).get(); - )*/ + let line = LineEditor::new(&ctx, 0, + chars_edittree.get_edit::().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::ListSegmentSequence::new( + let lines_segments = nested::editors::list::ListSegments::new( list_edit.get_cursor_port(), - list_edit.get_edittree_seq() + list_edit.get_edittree_list() ).read().unwrap().get_view(); let lines_view = lines_segments .map({ @@ -256,6 +334,7 @@ impl LinesEditor { } } }) + .to_sequence() .to_grid_vertical() .flatten(); @@ -269,102 +348,55 @@ impl LinesEditor { LinesEditor { // lines, - edit: Arc::new(RwLock::new(list_edit)), + edit: list_edit, ctx } } - pub fn add_line(&mut self, line_value: &str) { - let n = self.edit.write().unwrap() - .get_edit::< ListEditor >().unwrap() + 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 depth = SingletonBuffer::new(0).get_port(); - - let chars_rt = self.make_line(line_value); - let chars_edittree = chars_rt - .edittree(&self.ctx).get() - .read().unwrap().clone(); - - let line = LineEditor::new(&self.ctx, n); - line.write().unwrap().chars_edit = chars_edittree.get_edit::().unwrap(); - let line_port = line.read().unwrap().get_port(); - - let mut line_edittree = EditTree::new(self.ctx.clone(), depth) - .set_nav( line.read().unwrap().chars_edit.clone() ) - .set_cmd( line.read().unwrap().chars_edit.clone() ) - .set_editor( line.clone() ); - - line_edittree.disp.view - .insert_leaf( - Context::parse(&self.ctx, "TerminalView"), - ReprLeaf::from_view( line_port ) - ); - - let mut le_rt = ReprTree::from_singleton_buffer( - Context::parse(&self.ctx, "EditTree"), - SingletonBuffer::new( Arc::new(RwLock::new(line_edittree)) ) - ); - le_rt.write().unwrap().set_halo(Context::parse(&self.ctx, "Line")); - le_rt = ReprTree::rise(le_rt); - - self.edit.write().unwrap() - .get_edit::< ListEditor >().unwrap() + let mut line_rt = self.make_line(line_value); + self.edit.get_edit::< ListEditor >().unwrap() .write().unwrap() - .data - .push( le_rt ); + .insert( line_rt.clone() ); + + line_rt } - pub fn make_line(&self, line_value: &str) -> Arc> { + 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, "~")); + rt_line.write().unwrap().set_halo(Context::parse(&ctx, "Line ~ ")); - // create Editor & transfer data to Editor - ctx.read().unwrap().apply_morphism( - &rt_line, - &laddertypes::MorphismType { - src_type: Context::parse(&ctx, ""), - dst_type: Context::parse(&ctx, " ~ EditTree") - } - ); + let line_builder = ReprTreeBuilder::new(ctx.clone()) + .require(Context::parse(&ctx, "Line ~ ~ ")) + .require(Context::parse(&ctx, "Line ~ EditTree")); - // .. avoid cycle of projections.. - rt_line.write().unwrap().detach(&ctx); - - ctx.read().unwrap().apply_morphism( - &rt_line, - &laddertypes::MorphismType { - src_type: Context::parse(&ctx, "~EditTree"), - dst_type: Context::parse(&ctx, "") - } - ); - ctx.read().unwrap().apply_morphism( - &rt_line, - &laddertypes::MorphismType { - src_type: Context::parse(&ctx, ""), - dst_type: Context::parse(&ctx, "~") - } - ); - - rt_line + 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.write().unwrap() + let mut line = self.edit .get_edit::< ListEditor >().expect("cant get list edit") - .write().unwrap() + .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 { + /* 1. get [[Char]] Repr + 2. call flatten + 3. read out as repr + */ + // TODO let lines = self.edit.read().unwrap().get_edit::< ListEditor >().expect("cant get list edit") .read().unwrap().data @@ -387,7 +419,6 @@ impl LinesEditor { */ } - #[async_std::main] async fn main() { /* setup context @@ -401,10 +432,11 @@ async fn main() { let args: Vec = std::env::args().collect(); let path = String::from(args.get(1).expect("no filename given")); + let mut lines_edit = LinesEditor::new(ctx.clone()); let iter_lines = iterate_text::file::lines::IterateFileLines::new(path.clone()); - for line in iter_lines { + for (i,line) in iter_lines.enumerate() { let mut sanitized_line = String::new(); for c in line.chars() { if c == '\t' { @@ -413,22 +445,35 @@ async fn main() { sanitized_line.push(c); } } - lines_edit.add_line(&sanitized_line); + let line = lines_edit.add_line(&sanitized_line); + + line.edittree(&ctx).get() + .get_edit::().unwrap() + .write().unwrap() + .num_buf.set(i as u64); } - lines_edit.edit.write().unwrap().goto(TreeCursor::home()); - lines_edit.add_diagnostic( 5, LineDiagnostic{ range: (0, 10), msg: "test diagnostic".into() } ); + 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.edit.goto(TreeCursor::home()); + + let mut edit = lines_edit.edit.clone(); /* setup terminal */ let app = TTYApplication::new({ - let edittree = lines_edit.edit.clone(); + let edittree = edit.clone(); /* event handler */ let ctx = ctx.clone(); move |ev| { - edittree.write().unwrap().send_cmd_obj(ev.to_repr_tree(&ctx)); + let ev_rt = ev.to_repr_tree(&ctx); + let mut et = edittree.clone(); + eprintln!("main loop: input {}", ev_rt.read().unwrap().fmt(&ctx, 0)); + et.send_cmd_obj(ev_rt); } }); @@ -442,7 +487,6 @@ async fn main() { */ { let mut comp = compositor.write().unwrap(); - let edit = lines_edit.edit.read().unwrap(); comp.push(edit.get_cursor_widget()); comp.push(edit.display_view().offset(Vector2::new(0, 1))); }