Compare commits
3 commits
a2242f0d65
...
48fc91b586
Author | SHA1 | Date | |
---|---|---|---|
48fc91b586 | |||
894e19b84b | |||
bbcf97d00b |
12 changed files with 685 additions and 636 deletions
|
@ -12,4 +12,5 @@ members = [
|
||||||
"examples/tty-04-posint",
|
"examples/tty-04-posint",
|
||||||
"examples/tty-05-dictionary",
|
"examples/tty-05-dictionary",
|
||||||
"examples/tty-06-lines",
|
"examples/tty-06-lines",
|
||||||
|
"examples/tty-07-color",
|
||||||
]
|
]
|
||||||
|
|
|
@ -39,8 +39,8 @@ async fn main() {
|
||||||
*/
|
*/
|
||||||
let ctx = Arc::new(RwLock::new(Context::new()));
|
let ctx = Arc::new(RwLock::new(Context::new()));
|
||||||
nested::editors::char::init_ctx( ctx.clone() );
|
nested::editors::char::init_ctx( ctx.clone() );
|
||||||
nested::editors::digit::init_ctx( ctx.clone() );
|
//nested::editors::digit::init_ctx( ctx.clone() );
|
||||||
nested::editors::integer::init_ctx( ctx.clone() );
|
//nested::editors::integer::init_ctx( ctx.clone() );
|
||||||
nested::editors::list::init_ctx( ctx.clone() );
|
nested::editors::list::init_ctx( ctx.clone() );
|
||||||
nested_tty::setup_edittree_hook(&ctx);
|
nested_tty::setup_edittree_hook(&ctx);
|
||||||
|
|
||||||
|
@ -49,23 +49,28 @@ async fn main() {
|
||||||
*/
|
*/
|
||||||
let int_builder = ReprTreeBuilder::new( ctx.clone() )
|
let int_builder = ReprTreeBuilder::new( ctx.clone() )
|
||||||
.require(Context::parse(&ctx,
|
.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,
|
.require(Context::parse(&ctx,
|
||||||
"ℕ ~ <PosInt 10 BigEndian> ~ EditTree"))
|
"ℕ ~ <PosInt 10 BigEndian> ~ EditTree"))
|
||||||
.require(Context::parse(&ctx,
|
.require(Context::parse(&ctx,
|
||||||
"ℕ ~ <PosInt 8 BigEndian> ~ EditTree"))
|
"ℕ ~ <PosInt 8 BigEndian> ~ EditTree"))
|
||||||
.require(Context::parse(&ctx,
|
.require(Context::parse(&ctx,
|
||||||
"ℕ ~ <PosInt 2 BigEndian> ~ EditTree"))
|
"ℕ ~ <PosInt 2 BigEndian> ~ EditTree"))
|
||||||
|
*/
|
||||||
;
|
;
|
||||||
|
|
||||||
let mut rt_int = nested::repr_tree::ReprTree::from_str("3");
|
let mut rt_int = nested::repr_tree::ReprTree::from_str("3");
|
||||||
rt_int.write().unwrap().set_halo(
|
rt_int.write().unwrap().set_halo(
|
||||||
/* HALO TYPE (append to top of type ladder) */
|
/* HALO TYPE (append to top of type ladder) */
|
||||||
Context::parse(&ctx, "
|
Context::parse(&ctx, /*"
|
||||||
ℕ
|
ℕ
|
||||||
~ <PosInt 16 BigEndian>
|
~ <PosInt 16 BigEndian>
|
||||||
~ <Seq <Digit 16>>
|
~ <Seq <Digit 16>>
|
||||||
~ <List <Digit 16>>
|
~ <List <Digit 16>>
|
||||||
|
*/
|
||||||
|
" <List <Digit 16>>
|
||||||
~ <List Char>
|
~ <List Char>
|
||||||
")
|
")
|
||||||
);
|
);
|
||||||
|
@ -102,7 +107,7 @@ async fn main() {
|
||||||
let first_idx : usize = 0;
|
let first_idx : usize = 0;
|
||||||
int_builder.update( &rt_int, int_builder.required_leaves[first_idx].clone() );
|
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,
|
leaf_mode: nested::editors::list::ListCursorMode::Insert,
|
||||||
tree_addr: vec![first_idx as isize, 0]
|
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 halo_type = rt_edittree.read().unwrap().get_halo_type().clone();
|
||||||
let edittree = rt_edittree.edittree( &ctx );
|
let edittree = rt_edittree.edittree( &ctx );
|
||||||
|
|
||||||
|
|
||||||
let box_port = ViewPort::new();
|
let box_port = ViewPort::new();
|
||||||
let ascii_box = nested_tty::widgets::ascii_box::AsciiBox::new(
|
let ascii_box = nested_tty::widgets::ascii_box::AsciiBox::new(
|
||||||
Vector2::new(30, 1),
|
Vector2::new(30, 1),
|
||||||
|
|
257
examples/tty-06-lines/src/line.rs
Normal file
257
examples/tty-06-lines/src/line.rs
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
225
examples/tty-06-lines/src/lines.rs
Normal file
225
examples/tty-06-lines/src/lines.rs
Normal file
|
@ -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()
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
|
@ -4,462 +4,82 @@ extern crate nested_tty;
|
||||||
extern crate r3vi;
|
extern crate r3vi;
|
||||||
extern crate termion;
|
extern crate termion;
|
||||||
|
|
||||||
|
mod line;
|
||||||
|
mod lines;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
cgmath::{Vector2, Point2},
|
cgmath::{Vector2},
|
||||||
nested::{
|
nested::{
|
||||||
editors::{ObjCommander, char::CharEditor, list::{ListEditor, ListSegment, ListSegments}},
|
edit_tree::{TreeCursor, TreeNav},
|
||||||
repr_tree::{Context, ReprLeaf, ReprTreeBuilder, ReprTree, ReprTreeExt, ReprTreeArc, GenericReprTreeMorphism},
|
editors::ObjCommander,
|
||||||
edit_tree::{EditTree, TreeNav, TreeCursor}
|
repr_tree::{Context, ReprTreeExt},
|
||||||
},
|
},
|
||||||
nested_tty::{
|
nested_tty::{
|
||||||
DisplaySegment, TTYApplication,
|
edit_tree::cursor_widget::TreeNavExt, DisplaySegment, TTYApplication,
|
||||||
TerminalCompositor, TerminalStyle, TerminalView,
|
TerminalCompositor,
|
||||||
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
|
|
||||||
},
|
},
|
||||||
std::sync::{Arc, RwLock},
|
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_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
/* setup context
|
/* setup context
|
||||||
*/
|
*/
|
||||||
let ctx = Arc::new(RwLock::new(Context::new()));
|
let ctx = Arc::new(RwLock::new(Context::new()));
|
||||||
nested::editors::char::init_ctx( ctx.clone() );
|
nested::editors::char::init_ctx(ctx.clone());
|
||||||
nested::editors::digit::init_ctx( ctx.clone() );
|
nested::editors::digit::init_ctx(ctx.clone());
|
||||||
nested::editors::integer::init_ctx( ctx.clone() );
|
nested::editors::integer::init_ctx(ctx.clone());
|
||||||
nested::editors::list::init_ctx( ctx.clone() );
|
nested::editors::list::init_ctx(ctx.clone());
|
||||||
nested_tty::setup_edittree_hook(&ctx);
|
nested_tty::setup_edittree_hook(&ctx);
|
||||||
|
|
||||||
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 = lines::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 (i,line) in iter_lines.enumerate() {
|
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' {
|
||||||
for _ in 0..4 { sanitized_line.push(' '); }
|
for _ in 0..4 {
|
||||||
|
sanitized_line.push(' ');
|
||||||
|
}
|
||||||
} else if c != '\n' {
|
} else if c != '\n' {
|
||||||
sanitized_line.push(c);
|
sanitized_line.push(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let line = lines_edit.add_line(&sanitized_line);
|
let line = lines_edit.add_line(&sanitized_line);
|
||||||
|
|
||||||
line.edittree(&ctx).get()
|
line.edittree(&ctx)
|
||||||
.get_edit::<LineEditor>().unwrap()
|
.get()
|
||||||
.write().unwrap()
|
.get_edit::<line::LineEditor>()
|
||||||
.num_buf.set(i as u64);
|
.unwrap()
|
||||||
|
.write()
|
||||||
|
.unwrap()
|
||||||
|
.num_buf
|
||||||
|
.set(i as u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
lines_edit.edit.goto(TreeCursor::home());
|
lines_edit.edit.goto(TreeCursor::home());
|
||||||
lines_edit.add_diagnostic( 5, LineDiagnostic{ range: (5, 10), msg: "test diagnostic".into() } );
|
lines_edit.add_diagnostic(
|
||||||
lines_edit.add_diagnostic( 8, LineDiagnostic{ range: (6, 14), msg: "another test diagnostic".into() } );
|
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());
|
lines_edit.edit.goto(TreeCursor::home());
|
||||||
|
|
||||||
let mut edit = lines_edit.edit.clone();
|
let edit = lines_edit.edit.clone();
|
||||||
|
|
||||||
/* setup terminal
|
/* setup terminal
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "tty-06-color"
|
name = "tty-07-color"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
@ -16,4 +16,3 @@ cgmath = "*"
|
||||||
[dependencies.async-std]
|
[dependencies.async-std]
|
||||||
version = "1.9.0"
|
version = "1.9.0"
|
||||||
features = ["unstable", "attributes"]
|
features = ["unstable", "attributes"]
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ use {
|
||||||
editors::{
|
editors::{
|
||||||
ObjCommander
|
ObjCommander
|
||||||
},
|
},
|
||||||
repr_tree::{Context, ReprTree, ReprTreeExt, ReprLeaf},
|
repr_tree::{Context, ReprTree, ReprTreeBuilder, ReprTreeExt, ReprTreeArc, ReprLeaf},
|
||||||
edit_tree::{EditTree, TreeNav, TreeCursor}
|
edit_tree::{EditTree, TreeNav, TreeCursor}
|
||||||
},
|
},
|
||||||
nested_tty::{
|
nested_tty::{
|
||||||
|
@ -46,139 +46,57 @@ async fn main() {
|
||||||
Context::parse(&ctx, "<Vec EditTree>")
|
Context::parse(&ctx, "<Vec EditTree>")
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut red = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, "
|
let channel_builder = ReprTreeBuilder::new(ctx.clone())
|
||||||
ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ <Vec Char>
|
.require(Context::parse(&ctx, "
|
||||||
"),
|
ℕ ~ <PosInt 10 BigEndian> ~ EditTree
|
||||||
"221"
|
"))
|
||||||
);
|
.require(Context::parse(&ctx, "
|
||||||
ctx.read().unwrap().apply_morphism( &red,
|
ℕ ~ <PosInt 16 BigEndian> ~ EditTree
|
||||||
&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 mut green = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, "
|
let mut red = nested::repr_tree::ReprTree::from_str("221");
|
||||||
ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ <Vec Char>
|
red.write().unwrap().set_halo(Context::parse(&ctx, "
|
||||||
"),
|
ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char>
|
||||||
"220"
|
"));
|
||||||
);
|
red = channel_builder.build_from(red).expect("");
|
||||||
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 green = nested::repr_tree::ReprTree::from_str("220");
|
||||||
let mut blue = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, "
|
green.write().unwrap().set_halo(Context::parse(&ctx, "
|
||||||
ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ <Vec Char>
|
ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char>
|
||||||
"),
|
"));
|
||||||
"5"
|
green = channel_builder.build_from(green).expect("");
|
||||||
);
|
|
||||||
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 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(
|
let mut color = nested::repr_tree::ReprTree::new_arc(
|
||||||
Context::parse(&ctx, "<List ℕ>")
|
Context::parse(&ctx, "<List ℕ>")
|
||||||
);
|
);
|
||||||
|
|
||||||
color.insert_leaf(
|
color.insert_leaf(
|
||||||
Context::parse(&ctx, "
|
Context::parse(&ctx, "
|
||||||
<List ℕ
|
< List ℕ ~ ReprTree >
|
||||||
~ <PosInt 16 BigEndian>
|
~ < Vec ReprTree >
|
||||||
~ <Seq <Digit 16>>
|
|
||||||
~ <List <Digit 16>
|
|
||||||
~ Char >
|
|
||||||
>
|
|
||||||
~ <List EditTree>
|
|
||||||
~ <Vec EditTree>
|
|
||||||
"),
|
"),
|
||||||
|
ReprLeaf::from_vec_buffer(VecBuffer::<ReprTreeArc>::with_data(
|
||||||
ReprLeaf::from_vec_buffer(VecBuffer::<
|
vec![ red, green, blue ])
|
||||||
Arc<RwLock< EditTree >>
|
)
|
||||||
>::with_data(vec![
|
);
|
||||||
red_edit.get(),
|
/*
|
||||||
green_edit.get(),
|
color.attach_leaf_to(
|
||||||
blue_edit.get()
|
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;
|
return;
|
||||||
|
|
||||||
/* setup terminal
|
/* setup terminal
|
||||||
|
@ -187,12 +105,12 @@ return;
|
||||||
/* event handler
|
/* event handler
|
||||||
*/
|
*/
|
||||||
let ctx = ctx.clone();
|
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| {
|
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 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();
|
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))))
|
.map_item(|_pt, atom| atom.add_style_front(TerminalStyle::fg_color((90,90,90))))
|
||||||
.offset(Vector2::new(1,y)));
|
.offset(Vector2::new(1,y)));
|
||||||
|
|
||||||
|
@ -221,12 +139,11 @@ return;
|
||||||
.offset(Vector2::new(1,y+1)));
|
.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 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 10 BigEndian> ~ <Seq~List <Digit 10>~Char>>")).unwrap(), 3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write the changes in the view of `term_port` to the terminal
|
/* write the changes in the view of `term_port` to the terminal
|
||||||
*/
|
*/
|
||||||
app.show().await.expect("output error!");
|
app.show().await.expect("output error!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -261,7 +261,7 @@ pub fn init_ctx(ctx: Arc<RwLock<Context>>) {
|
||||||
ctx.write().unwrap().add_varname("Item");
|
ctx.write().unwrap().add_varname("Item");
|
||||||
|
|
||||||
let list_morph_editsetup1 = GenericReprTreeMorphism::new(
|
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"),
|
Context::parse(&ctx, "<List Item>~EditTree"),
|
||||||
{
|
{
|
||||||
let ctx = ctx.clone();
|
let ctx = ctx.clone();
|
||||||
|
|
|
@ -1,23 +1,11 @@
|
||||||
use {
|
use {
|
||||||
r3vi::{
|
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::{
|
||||||
view::{
|
buffer::{singleton::*, vec::*}, view::{
|
||||||
ViewPort, OuterViewPort,
|
list::*, port::UpdateTask, sequence::*, singleton::*, AnyInnerViewPort, AnyOuterViewPort, AnyViewPort, Observer, OuterViewPort, View, ViewPort
|
||||||
AnyViewPort, AnyInnerViewPort, AnyOuterViewPort,
|
}
|
||||||
port::UpdateTask,
|
}, std::{
|
||||||
View, Observer,
|
any::Any, collections::HashMap, sync::{Arc, RwLock}
|
||||||
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}}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
@ -65,8 +53,8 @@ impl ReprTreeBuilder {
|
||||||
|
|
||||||
let morphism_base = &self.ctx.read().unwrap().morphisms;
|
let morphism_base = &self.ctx.read().unwrap().morphisms;
|
||||||
|
|
||||||
let mt = master_leaf_type.into();
|
let mt = master_leaf_type.into().normalize().param_normalize();
|
||||||
//eprintln!("REBUILD repr tree from {}", self.ctx.read().unwrap().type_term_to_str(&mt));
|
eprintln!("REBUILD repr tree from {}", self.ctx.read().unwrap().type_term_to_str(&mt));
|
||||||
let mut leaves = self.required_leaves.clone();
|
let mut leaves = self.required_leaves.clone();
|
||||||
leaves.retain(|t| t != &mt);
|
leaves.retain(|t| t != &mt);
|
||||||
|
|
||||||
|
@ -77,18 +65,32 @@ impl ReprTreeBuilder {
|
||||||
|
|
||||||
if let Some( steiner_tree ) = st_problem.solve( &morphism_base ) {
|
if let Some( steiner_tree ) = st_problem.solve( &morphism_base ) {
|
||||||
eprintln!("--> from {}", self.ctx.read().unwrap().type_term_to_str(&mt));
|
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 {}",
|
eprintln!("--> morph to {}",
|
||||||
self.ctx.read().unwrap().type_term_to_str(&morphism_type.dst_type));
|
self.ctx.read().unwrap().type_term_to_str(&morphism_type.dst_type));
|
||||||
|
|
||||||
if let Some(( morphism, mut τ, σ )) =
|
let mut dict = self.ctx.read().unwrap().type_dict.clone();
|
||||||
morphism_base.find_morphism_with_subtyping( &morphism_type )
|
|
||||||
|
if let Some(morph_inst) =
|
||||||
|
morphism_base.find_morphism( &morphism_type, &mut dict )
|
||||||
{
|
{
|
||||||
let mut rt = rt.descend_create( τ ).expect("descend src repr");
|
eprintln!("setup morph");
|
||||||
(morphism.setup_projection)( &mut rt, &σ );
|
|
||||||
|
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 {
|
} else {
|
||||||
eprintln!("failed to get morphism");
|
eprintln!("failed to get morphism");
|
||||||
//return Err(ReprTreeError::MissingMorphism);
|
return Err(ReprTreeError::MissingMorphism);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,22 +53,28 @@ pub struct Context {
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub fn with_parent(parent: Option<Arc<RwLock<Context>>>) -> Self {
|
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))
|
let mut dict = match parent.as_ref() {
|
||||||
}
|
Some(p) => p.read().unwrap().type_dict.clone(),
|
||||||
},
|
None => {
|
||||||
morphisms: MorphismBase::new(TYPEID_list),
|
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(),
|
nodes: HashMap::new(),
|
||||||
list_types: match parent.as_ref() {
|
list_types: match parent.as_ref() {
|
||||||
Some(p) => p.read().unwrap().list_types.clone(),
|
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) {
|
pub fn apply_morphism(&self, rt: &Arc<RwLock<ReprTree>>, ty: &MorphismType) {
|
||||||
if let Some(path) = self.morphisms.find_morphism_path(ty.clone().normalize()) {
|
if let Some(path) = self.morphisms.find_morphism_path(ty.clone().normalize()) {
|
||||||
let mut path = path.into_iter();
|
for morph_inst in path {
|
||||||
if let Some(mut src_type) = path.next() {
|
let mut rt = rt.descend(morph_inst.halo).expect("descend src repr");
|
||||||
for dst_type in path {
|
(morph_inst.m.setup_projection)(&mut rt, &morph_inst.σ);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eprintln!("no path found");
|
eprintln!("no path found");
|
||||||
|
|
|
@ -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 {
|
impl Morphism for GenericReprTreeMorphism {
|
||||||
fn get_type(&self) -> MorphismType {
|
fn get_type(&self) -> MorphismType {
|
||||||
self.morph_type.clone()
|
self.morph_type.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_map_morphism(&self, list_typeid: TypeID) -> Option< GenericReprTreeMorphism > {
|
fn map_morphism(&self, seq_type: TypeTerm) -> Option< GenericReprTreeMorphism > {
|
||||||
self.into_list_map_dyn(list_typeid)
|
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
|
-> GenericReprTreeMorphism
|
||||||
where
|
where
|
||||||
SrcItem: Clone + Send + Sync + 'static,
|
SrcItem: Clone + Send + Sync + 'static,
|
||||||
|
@ -62,11 +68,11 @@ impl GenericReprTreeMorphism {
|
||||||
{
|
{
|
||||||
let mut lst_map_type = MorphismType {
|
let mut lst_map_type = MorphismType {
|
||||||
src_type: TypeTerm::App(vec![
|
src_type: TypeTerm::App(vec![
|
||||||
TypeTerm::TypeID(list_typeid),
|
seq_type.clone(),
|
||||||
self.morph_type.src_type.clone()
|
self.morph_type.src_type.clone()
|
||||||
]),
|
]),
|
||||||
dst_type: TypeTerm::App(vec![
|
dst_type: TypeTerm::App(vec![
|
||||||
TypeTerm::TypeID(list_typeid),
|
seq_type.clone(),
|
||||||
self.morph_type.dst_type.clone()
|
self.morph_type.dst_type.clone()
|
||||||
])
|
])
|
||||||
}.normalize();
|
}.normalize();
|
||||||
|
@ -86,14 +92,13 @@ impl GenericReprTreeMorphism {
|
||||||
"lst map type ::\n {:?}\n===> {:?}\n\n", lst_map_type.src_type, lst_map_type.dst_type
|
"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 mut item_ladder = item_morph.morph_type.src_type.clone().get_lnf_vec();
|
||||||
let top_type = item_ladder.remove( item_ladder.len() - 1 );
|
let top_type = item_ladder.remove( item_ladder.len() - 1 );
|
||||||
|
|
||||||
if let Ok(item_sigma) = laddertypes::unify(
|
if let Ok(item_sigma) = laddertypes::unify(
|
||||||
&top_type,
|
&top_type,
|
||||||
&TypeTerm::App(vec![
|
&TypeTerm::App(vec![
|
||||||
TypeTerm::TypeID( list_typeid ),
|
seq_type.clone(),
|
||||||
TypeTerm::TypeID( TypeID::Var( 200 ) )
|
TypeTerm::TypeID( TypeID::Var( 200 ) )
|
||||||
])
|
])
|
||||||
) {
|
) {
|
||||||
|
@ -113,7 +118,7 @@ impl GenericReprTreeMorphism {
|
||||||
top_type.clone(),
|
top_type.clone(),
|
||||||
r3vi::buffer::singleton::SingletonBuffer::new(x.clone())
|
r3vi::buffer::singleton::SingletonBuffer::new(x.clone())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// TODO: required?
|
// TODO: required?
|
||||||
for t in item_ladder.iter().rev() {
|
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 >
|
-> Option< GenericReprTreeMorphism >
|
||||||
{
|
{
|
||||||
let src_item_type_lnf = self.morph_type.src_type.clone().get_lnf_vec();
|
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();
|
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)) &&
|
if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) &&
|
||||||
dst_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)) &&
|
else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_u64)) &&
|
||||||
dst_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)) &&
|
else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) &&
|
||||||
dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_u64))
|
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)) &&
|
else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_u64)) &&
|
||||||
dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char))
|
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)) &&
|
else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) &&
|
||||||
dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_edittree))
|
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)) &&
|
else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_edittree)) &&
|
||||||
dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char))
|
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) ])) &&
|
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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
|
27
todo.md
Normal file
27
todo.md
Normal file
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue