lines example wip

This commit is contained in:
Michael Sippel 2025-01-22 23:37:16 +01:00
parent 16a0381ada
commit a2242f0d65
Signed by: senvas
GPG key ID: F96CF119C34B64A6

View file

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