lines example: split files

This commit is contained in:
Michael Sippel 2025-01-25 02:02:51 +01:00
parent a2242f0d65
commit bbcf97d00b
Signed by: senvas
GPG key ID: F96CF119C34B64A6
3 changed files with 520 additions and 421 deletions
examples/tty-06-lines/src

View file

@ -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()
}
}

View file

@ -0,0 +1,222 @@
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()
}
*/
}

View file

@ -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
*/