Compare commits
6 commits
02b8574038
...
c4226281e1
Author | SHA1 | Date | |
---|---|---|---|
c4226281e1 | |||
dad789227c | |||
2c2268c918 | |||
fe4b571b8c | |||
e09f3e5656 | |||
b2083aec4c |
12 changed files with 905 additions and 91 deletions
|
@ -10,5 +10,6 @@ members = [
|
|||
"examples/tty-02-digit",
|
||||
"examples/tty-03-string",
|
||||
"examples/tty-04-posint",
|
||||
"examples/tty-05-dictionary",
|
||||
"examples/tty-06-lines",
|
||||
]
|
||||
|
||||
|
|
19
examples/tty-05-dictionary/Cargo.toml
Normal file
19
examples/tty-05-dictionary/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "tty-05-dictionary"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
laddertypes = { path = "../../../lib-laddertypes" }
|
||||
r3vi = { path = "../../../lib-r3vi" }
|
||||
nested = { path = "../../lib-nested-core" }
|
||||
nested-tty = { path = "../../lib-nested-tty" }
|
||||
termion = "*"
|
||||
cgmath = "*"
|
||||
|
||||
[dependencies.async-std]
|
||||
version = "1.9.0"
|
||||
features = ["unstable", "attributes"]
|
||||
|
299
examples/tty-05-dictionary/src/main.rs
Normal file
299
examples/tty-05-dictionary/src/main.rs
Normal file
|
@ -0,0 +1,299 @@
|
|||
extern crate cgmath;
|
||||
extern crate nested;
|
||||
extern crate nested_tty;
|
||||
extern crate r3vi;
|
||||
extern crate termion;
|
||||
|
||||
use {
|
||||
cgmath::Vector2,
|
||||
nested::{
|
||||
editors::{
|
||||
ObjCommander
|
||||
},
|
||||
repr_tree::{Context, ReprTree, ReprTreeExt, ReprLeaf},
|
||||
edit_tree::{EditTree, TreeNav, TreeCursor}
|
||||
},
|
||||
laddertypes::{
|
||||
bimap::Bimap,
|
||||
sugar::SugaredTypeTerm
|
||||
},
|
||||
nested_tty::{
|
||||
DisplaySegment, TTYApplication,
|
||||
TerminalCompositor, TerminalStyle, TerminalView,
|
||||
TerminalAtom, TerminalEvent
|
||||
},
|
||||
r3vi::{
|
||||
buffer::{singleton::*, vec::*},
|
||||
view::{port::UpdateTask, singleton::*, list::*, sequence::*},
|
||||
projection::*
|
||||
},
|
||||
std::sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
#[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_tty::setup_edittree_hook(&ctx);
|
||||
|
||||
let dict = Arc::new(RwLock::new(Bimap::<String, u64>::new()));
|
||||
dict.write().unwrap().insert( "Nop".into(), 0 );
|
||||
dict.write().unwrap().insert( "Jmp".into(), 1 );
|
||||
dict.write().unwrap().insert( "Call".into(), 2 );
|
||||
dict.write().unwrap().insert( "Branch".into(), 3 );
|
||||
dict.write().unwrap().insert( "Ret".into(), 4 );
|
||||
dict.write().unwrap().insert( "Lit".into(), 5 );
|
||||
dict.write().unwrap().insert( "Pick".into(), 6 );
|
||||
dict.write().unwrap().insert( "Roll".into(), 7 );
|
||||
dict.write().unwrap().insert( "Dup".into(), 8 );
|
||||
dict.write().unwrap().insert( "Drop".into(), 9 );
|
||||
dict.write().unwrap().insert( "Swap".into(), 10 );
|
||||
dict.write().unwrap().insert( "Rot".into(), 11 );
|
||||
dict.write().unwrap().insert( "Fetch".into(), 13 );
|
||||
dict.write().unwrap().insert( "Store".into(), 14 );
|
||||
dict.write().unwrap().insert( "Accept".into(), 15 );
|
||||
dict.write().unwrap().insert( "Emit".into(), 16 );
|
||||
dict.write().unwrap().insert( "IntAdd".into(), 17 );
|
||||
dict.write().unwrap().insert( "IntSub".into(), 18 );
|
||||
dict.write().unwrap().insert( "IntMul".into(), 19 );
|
||||
dict.write().unwrap().insert( "IntDiv".into(), 20 );
|
||||
dict.write().unwrap().insert( "IntRem".into(), 21 );
|
||||
dict.write().unwrap().insert( "FltAdd".into(), 22 );
|
||||
dict.write().unwrap().insert( "FltSub".into(), 23 );
|
||||
dict.write().unwrap().insert( "FltMul".into(), 24 );
|
||||
dict.write().unwrap().insert( "FltDiv".into(), 25 );
|
||||
dict.write().unwrap().insert( "FltRem".into(), 26 );
|
||||
dict.write().unwrap().insert( "BitNeg".into(), 28 );
|
||||
dict.write().unwrap().insert( "BitAnd".into(), 29 );
|
||||
dict.write().unwrap().insert( "BitOr".into(), 30 );
|
||||
dict.write().unwrap().insert( "BitXor".into(), 31 );
|
||||
dict.write().unwrap().insert( "BitShl".into(), 32 );
|
||||
dict.write().unwrap().insert( "BitShr".into(), 33 );
|
||||
|
||||
let symbol_morph_str_to_u64 = nested::repr_tree::GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq~List~Vec Char>"),
|
||||
Context::parse(&ctx, "Instruction ~ Opcode ~ ℕ ~ machine.UInt64"),
|
||||
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
let dict = dict.clone();
|
||||
|
||||
move |rt, σ| {
|
||||
let str_view = rt
|
||||
.descend(Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq~List~Vec Char>")).unwrap()
|
||||
.vec_buffer::<char>()
|
||||
.get_port();
|
||||
|
||||
let u64_view = str_view
|
||||
.to_singleton()
|
||||
.map({
|
||||
let old_value = Arc::new(RwLock::new(0));
|
||||
let dict = dict.clone();
|
||||
move |chars| {
|
||||
let str_val = chars.iter().collect::<String>();
|
||||
let dict = &dict.read().unwrap().mλ;
|
||||
|
||||
let mut old_value = old_value.write().unwrap();
|
||||
if let Some( new_value ) = dict.get( &str_val ) {
|
||||
*old_value = new_value.clone();
|
||||
new_value.clone()
|
||||
} else {
|
||||
old_value.clone()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
rt.attach_leaf_to(
|
||||
Context::parse(&ctx, "Opcode ~ ℕ ~ machine.UInt64"),
|
||||
u64_view
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let symbol_morph_u64_to_str = nested::repr_tree::GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "Instruction ~ Opcode ~ ℕ ~ machine.UInt64"),
|
||||
Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq Char>"),
|
||||
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
let dict = dict.clone();
|
||||
|
||||
move |rt, σ| {
|
||||
let u64_view = rt
|
||||
.descend(Context::parse(&ctx, "Instruction ~ Opcode ~ ℕ ~ machine.UInt64")).unwrap()
|
||||
.view_u64();
|
||||
|
||||
let str_view =
|
||||
u64_view
|
||||
.map({
|
||||
let dict = dict.clone();
|
||||
let old_value = Arc::new(RwLock::new( VecBuffer::<char>::new() ));
|
||||
move |idx| {
|
||||
let dict = &dict.read().unwrap().my;
|
||||
let mut old_value = old_value.write().unwrap();
|
||||
if let Some( new_value ) = dict.get( &idx ) {
|
||||
*old_value = VecBuffer::<char>::with_data(
|
||||
new_value.chars().collect::<Vec<char>>()
|
||||
);
|
||||
}
|
||||
|
||||
old_value.get_port().to_sequence()
|
||||
}
|
||||
})
|
||||
.to_sequence()
|
||||
.flatten();
|
||||
|
||||
rt.attach_leaf_to(
|
||||
Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq Char>"),
|
||||
str_view
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
ctx.write().unwrap().morphisms.add_morphism( symbol_morph_u64_to_str );
|
||||
ctx.write().unwrap().morphisms.add_morphism( symbol_morph_str_to_u64 );
|
||||
|
||||
let mut symbol_rt = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, "
|
||||
Instruction ~ Mnemonic ~ <Seq~List~Vec Char>
|
||||
"),
|
||||
"Call"
|
||||
);
|
||||
|
||||
// this is required to initialize the <Vec EditTree> representation,
|
||||
// and to take the value from <Vec Char>
|
||||
ctx.read().unwrap().build_repr_tree(
|
||||
&symbol_rt,
|
||||
Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq~List~Vec Char>"),
|
||||
vec![
|
||||
Context::parse(&ctx, "Instruction ~ Opcode ~ ℕ ~ <PosInt 10 BigEndian> ~ EditTree"),
|
||||
Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq~List Char> ~ EditTree"),
|
||||
]);
|
||||
|
||||
symbol_rt.write().unwrap().detach( &ctx );
|
||||
|
||||
fn set_master(
|
||||
ctx: &Arc<RwLock<Context>>,
|
||||
rt: &Arc<RwLock<ReprTree>>,
|
||||
mut leaves: Vec< laddertypes::TypeTerm >,
|
||||
master_idx: usize
|
||||
) {
|
||||
eprintln!("set master to {}", master_idx);
|
||||
if master_idx < leaves.len() {
|
||||
let master = leaves.remove( master_idx );
|
||||
rt.write().unwrap().detach( &ctx );
|
||||
ctx.read().unwrap().build_repr_tree(
|
||||
rt,
|
||||
master,
|
||||
leaves
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let editor_types = vec![
|
||||
Context::parse(&ctx,
|
||||
"Instruction ~ Mnemonic ~ <Seq~List Char> ~ EditTree"),
|
||||
Context::parse(&ctx,
|
||||
"Instruction ~ Opcode ~ ℕ ~ <PosInt 10 BigEndian> ~ EditTree"),
|
||||
Context::parse(&ctx,
|
||||
"Instruction ~ Opcode ~ ℕ ~ <PosInt 16 BigEndian> ~ EditTree"),
|
||||
];
|
||||
|
||||
set_master(&ctx, &symbol_rt, editor_types.clone(), 0);
|
||||
let mut list_editor = nested::editors::list::ListEditor::new(ctx.clone(), Context::parse(&ctx, "<Seq Char>"));
|
||||
|
||||
// add all desired editors to the list
|
||||
for leaf in editor_types.iter() {
|
||||
let et =
|
||||
symbol_rt
|
||||
.descend(leaf.clone()).unwrap()
|
||||
.edittree(&ctx).get();
|
||||
et.write().unwrap().goto(TreeCursor::none());
|
||||
list_editor.data.push(et);
|
||||
}
|
||||
|
||||
let mut edittree = list_editor.into_node(SingletonBuffer::new(0).get_port());
|
||||
edittree.goto(TreeCursor{
|
||||
leaf_mode: nested::editors::list::ListCursorMode::Insert,
|
||||
tree_addr: vec![0, 0]
|
||||
});
|
||||
let edittree = Arc::new(RwLock::new(edittree));
|
||||
|
||||
/* setup terminal
|
||||
*/
|
||||
let app = TTYApplication::new({
|
||||
/* event handler
|
||||
*/
|
||||
let ctx = ctx.clone();
|
||||
let symbol_rt = symbol_rt.clone();
|
||||
let last_idx = RwLock::new(0);
|
||||
let editor_types = editor_types.clone();
|
||||
move |ev| {
|
||||
let cur = edittree.read().unwrap().get_cursor();
|
||||
if cur.tree_addr.len() > 0 {
|
||||
let mut li = last_idx.write().unwrap();
|
||||
let ci = cur.tree_addr[0];
|
||||
|
||||
if *li != ci {
|
||||
eprintln!("----------------------------------");
|
||||
set_master(
|
||||
&ctx,
|
||||
&symbol_rt,
|
||||
editor_types.clone(),
|
||||
ci as usize
|
||||
);
|
||||
*li = ci;
|
||||
}
|
||||
}
|
||||
|
||||
edittree.write().unwrap().send_cmd_obj(ev.to_repr_tree(&ctx));
|
||||
}
|
||||
});
|
||||
|
||||
/* Setup the compositor to serve as root-view
|
||||
* by routing it to the `app.port` Viewport,
|
||||
* so it will be displayed on TTY-output.
|
||||
*/
|
||||
let compositor = TerminalCompositor::new(app.port.inner());
|
||||
|
||||
/* Now add some views to our compositor
|
||||
*/
|
||||
{
|
||||
let mut comp = compositor.write().unwrap();
|
||||
|
||||
fn show_edit_tree(
|
||||
ctx: &Arc<RwLock<Context>>,
|
||||
comp: &mut TerminalCompositor,
|
||||
rt: &Arc<RwLock<ReprTree>>,
|
||||
y: i16
|
||||
) {
|
||||
let rt_edittree = rt.descend(Context::parse(&ctx, "EditTree")).expect("descend");
|
||||
let halo_type = rt_edittree.read().unwrap().get_halo_type().clone();
|
||||
let edittree = rt_edittree.read().unwrap().get_view::<dyn r3vi::view::singleton::SingletonView<Item = Arc<RwLock<EditTree>>>>().unwrap().get().read().unwrap().clone();
|
||||
|
||||
comp.push( nested_tty::make_label( &ctx.read().unwrap().type_term_to_str(&halo_type) )
|
||||
.map_item(|_pt, atom| atom.add_style_front(TerminalStyle::fg_color((90,90,90))))
|
||||
.offset(Vector2::new(1,y)));
|
||||
|
||||
comp.push( edittree.display_view()
|
||||
.map_item(|_pt, atom|
|
||||
atom.add_style_front(TerminalStyle::bg_color((80,80,80)))
|
||||
)
|
||||
.offset(Vector2::new(1,y+1)));
|
||||
}
|
||||
|
||||
show_edit_tree( &ctx, &mut comp, &symbol_rt.descend(Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq~List Char>")).unwrap(), 1 );
|
||||
show_edit_tree( &ctx, &mut comp, &symbol_rt.descend(Context::parse(&ctx, "Instruction ~ Opcode ~ ℕ ~ <PosInt 10 BigEndian>")).unwrap(), 3 );
|
||||
show_edit_tree( &ctx, &mut comp, &symbol_rt.descend(Context::parse(&ctx, "Instruction ~ Opcode ~ ℕ ~ <PosInt 16 BigEndian>")).unwrap(), 5 );
|
||||
}
|
||||
|
||||
/* write the changes in the view of `term_port` to the terminal
|
||||
*/
|
||||
app.show().await.expect("output error!");
|
||||
}
|
19
examples/tty-06-lines/Cargo.toml
Normal file
19
examples/tty-06-lines/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "tty-06-lines"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
laddertypes = { path = "../../../lib-laddertypes" }
|
||||
r3vi = { path = "../../../lib-r3vi" }
|
||||
nested = { path = "../../lib-nested-core" }
|
||||
nested-tty = { path = "../../lib-nested-tty" }
|
||||
iterate-text = "0.0.1"
|
||||
termion = "*"
|
||||
cgmath = "*"
|
||||
|
||||
[dependencies.async-std]
|
||||
version = "1.9.0"
|
||||
features = ["unstable", "attributes"]
|
8
examples/tty-06-lines/README.md
Normal file
8
examples/tty-06-lines/README.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
# tty-03-string
|
||||
|
||||
Similarly to `tty-02-digit`, a editor is created
|
||||
but of type <List Char>.
|
||||
The contents of the editor can be retrieved by
|
||||
a morphism from the `EditTree` node.
|
||||
To demonstrate that, the values are are mapped
|
||||
to the TTY-display in different form.
|
418
examples/tty-06-lines/src/main.rs
Normal file
418
examples/tty-06-lines/src/main.rs
Normal file
|
@ -0,0 +1,418 @@
|
|||
extern crate cgmath;
|
||||
extern crate nested;
|
||||
extern crate nested_tty;
|
||||
extern crate r3vi;
|
||||
extern crate termion;
|
||||
|
||||
use {
|
||||
cgmath::{Vector2, Point2},
|
||||
nested::{
|
||||
editors::{ObjCommander, char::CharEditor, list::{ListEditor, ListSegment, ListSegmentSequence}},
|
||||
repr_tree::{Context, ReprLeaf, ReprTree, ReprTreeExt, GenericReprTreeMorphism},
|
||||
edit_tree::{EditTree, TreeNav, TreeCursor}
|
||||
},
|
||||
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
|
||||
},
|
||||
std::sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
struct LineDiagnostic {
|
||||
range: (u32, u32),
|
||||
msg: String
|
||||
}
|
||||
|
||||
struct LineView {
|
||||
line_num: Arc< dyn SingletonView<Item = u64> >,
|
||||
segments: Arc< dyn SequenceView<Item = ListSegment> >,
|
||||
diagnostics: Arc< dyn SequenceView<Item = LineDiagnostic> >,
|
||||
|
||||
diag_buf: VecBuffer< LineDiagnostic >,
|
||||
|
||||
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
|
||||
out_port: OuterViewPort<dyn TerminalView>,
|
||||
proj_helper: ProjectionHelper<usize, Self>
|
||||
}
|
||||
|
||||
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 -1-n_digits , 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 LineView {
|
||||
pub fn new(
|
||||
n: u64,
|
||||
le: &ListEditor,
|
||||
) -> Arc<RwLock<Self>> {
|
||||
let line_num_buf = SingletonBuffer::new(n);
|
||||
let diag_buf = VecBuffer::new();
|
||||
let seg_seq = ListSegmentSequence::new(le.get_cursor_port(), le.get_data_port())
|
||||
.read().unwrap().get_view();
|
||||
|
||||
let out_port = ViewPort::new();
|
||||
let mut proj_helper = ProjectionHelper::new(out_port.update_hooks.clone());
|
||||
|
||||
let lv = Arc::new(RwLock::new(LineView{
|
||||
line_num: proj_helper.new_singleton_arg(0, line_num_buf.get_port(),
|
||||
|s: &mut LineView, _msg|{
|
||||
s.cast.write().unwrap()
|
||||
.notify(&IndexArea::Range(
|
||||
(Point2::new(-100, 0) ..= Point2::new(0, 0))
|
||||
));
|
||||
}),
|
||||
segments: proj_helper.new_sequence_arg(1, seg_seq,
|
||||
|s: &mut LineView, idx| {
|
||||
s.cast.write().unwrap()
|
||||
.notify(&IndexArea::Range(
|
||||
(Point2::new(0, *idx as i16 - 1) ..= Point2::new(100, *idx as i16))
|
||||
));
|
||||
}),
|
||||
diagnostics: proj_helper.new_sequence_arg(2, diag_buf.get_port().to_sequence(),
|
||||
|s: &mut LineView, idx| {
|
||||
s.cast.write().unwrap()
|
||||
.notify(&IndexArea::Range(
|
||||
(Point2::new(-100, 1+*idx as i16) ..= Point2::new(100, 1+*idx as i16))
|
||||
));
|
||||
}),
|
||||
|
||||
diag_buf,
|
||||
|
||||
cast: out_port.inner().get_broadcast(),
|
||||
proj_helper,
|
||||
out_port: out_port.outer()
|
||||
}));
|
||||
|
||||
lv.write().unwrap().proj_helper.set_proj(&lv);
|
||||
out_port.inner().set_view(Some(lv.clone()));
|
||||
|
||||
lv
|
||||
}
|
||||
|
||||
pub fn get_port(&self) -> OuterViewPort<dyn TerminalView> {
|
||||
self.out_port.clone()
|
||||
}
|
||||
}
|
||||
|
||||
struct LinesEditor {
|
||||
ctx: Arc<RwLock<Context>>,
|
||||
edit: Arc<RwLock<EditTree>>
|
||||
}
|
||||
|
||||
impl LinesEditor {
|
||||
pub fn new(ctx: Arc<RwLock<Context>>) -> Self {
|
||||
let typ = Context::parse(&ctx, "<List Char>");
|
||||
let depth_port = SingletonBuffer::<usize>::new(0).get_port();
|
||||
|
||||
let list_edit = ListEditor::new(ctx.clone(), typ);
|
||||
|
||||
let line_to_edittree = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "Line ~ <Seq~List Char>"),
|
||||
Context::parse(&ctx, "Line ~ EditTree"),
|
||||
|rt, σ| {
|
||||
eprintln!("LINE EDITOR CONSTRUCT");
|
||||
}
|
||||
);
|
||||
ctx.write().unwrap().morphisms.add_morphism( line_to_edittree );
|
||||
|
||||
let lines_segments = nested::editors::list::ListSegmentSequence::new(
|
||||
list_edit.get_cursor_port(),
|
||||
list_edit.get_data_port()
|
||||
).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_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: Arc::new(RwLock::new(list_edit)),
|
||||
ctx
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_line(&mut self, line_value: &str) {
|
||||
let n = self.edit.write().unwrap()
|
||||
.get_edit::< ListEditor >().unwrap()
|
||||
.read().unwrap()
|
||||
.data.len() as u64;
|
||||
|
||||
let line =
|
||||
self.make_line(line_value)
|
||||
.descend(Context::parse(&self.ctx, "EditTree")).unwrap()
|
||||
.edittree(&self.ctx).get();
|
||||
|
||||
let le = line.read().unwrap().get_edit::<ListEditor>().unwrap();
|
||||
le.write().unwrap().goto(TreeCursor::none());
|
||||
|
||||
let lvport = LineView::new( n, &*le.read().unwrap() ).read().unwrap().get_port();
|
||||
line.write().unwrap().disp.view
|
||||
.insert_leaf(
|
||||
Context::parse(&self.ctx, "TerminalView"),
|
||||
ReprLeaf::from_view( lvport )
|
||||
);
|
||||
|
||||
self.edit.write().unwrap()
|
||||
.get_edit::< ListEditor >().unwrap()
|
||||
.write().unwrap()
|
||||
.data
|
||||
.push(line);
|
||||
}
|
||||
|
||||
pub fn make_line(&self, line_value: &str) -> Arc<RwLock<ReprTree>> {
|
||||
let ctx = &self.ctx;
|
||||
let mut rt_line = ReprTree::from_str(
|
||||
Context::parse(&ctx, "<List Char>~<Vec Char>"),
|
||||
line_value
|
||||
);
|
||||
|
||||
ctx.read().unwrap().apply_morphism(
|
||||
&rt_line,
|
||||
&laddertypes::MorphismType {
|
||||
src_type: Context::parse(&ctx, "<List~Vec Char>"),
|
||||
dst_type: Context::parse(&ctx, "<List Char> ~ EditTree")
|
||||
}
|
||||
);
|
||||
|
||||
// .. avoid cycle of projections..
|
||||
rt_line.write().unwrap().detach(&ctx);
|
||||
|
||||
ctx.read().unwrap().apply_morphism(
|
||||
&rt_line,
|
||||
&laddertypes::MorphismType {
|
||||
src_type: Context::parse(&ctx, "<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) {
|
||||
/*
|
||||
let mut line = self.edit.write().unwrap()
|
||||
.get_edit::< ListEditor >().expect("cant get list edit")
|
||||
.write().unwrap()
|
||||
.data
|
||||
.get(line_num)
|
||||
.get_edit::< LineEditor >().expect("cant get line edit");
|
||||
|
||||
line.write().unwrap().diag_buf.push(diag);
|
||||
*/
|
||||
}
|
||||
/*
|
||||
pub fn get_lines(&self) -> Vec<String> {
|
||||
// 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_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 iter_lines = iterate_text::file::lines::IterateFileLines::new(path.clone());
|
||||
for line in iter_lines {
|
||||
let mut sanitized_line = String::new();
|
||||
for c in line.chars() {
|
||||
if c == '\t' {
|
||||
for _ in 0..4 { sanitized_line.push(' '); }
|
||||
} else if c != '\n' {
|
||||
sanitized_line.push(c);
|
||||
}
|
||||
}
|
||||
lines_edit.add_line(&sanitized_line);
|
||||
}
|
||||
|
||||
lines_edit.edit.write().unwrap().goto(TreeCursor::home());
|
||||
lines_edit.add_diagnostic( 5, LineDiagnostic{ range: (0, 10), msg: "test diagnostic".into() } );
|
||||
|
||||
/* setup terminal
|
||||
*/
|
||||
let app = TTYApplication::new({
|
||||
let edittree = lines_edit.edit.clone();
|
||||
|
||||
/* event handler
|
||||
*/
|
||||
let ctx = ctx.clone();
|
||||
move |ev| {
|
||||
edittree.write().unwrap().send_cmd_obj(ev.to_repr_tree(&ctx));
|
||||
}
|
||||
});
|
||||
|
||||
/* Setup the compositor to serve as root-view
|
||||
* by routing it to the `app.port` Viewport,
|
||||
* so it will be displayed on TTY-output.
|
||||
*/
|
||||
let compositor = TerminalCompositor::new(app.port.inner());
|
||||
|
||||
/* Now add some views to our compositor
|
||||
*/
|
||||
{
|
||||
let mut comp = compositor.write().unwrap();
|
||||
let edit = lines_edit.edit.read().unwrap();
|
||||
comp.push(edit.get_cursor_widget());
|
||||
comp.push(edit.display_view().offset(Vector2::new(0, 1)));
|
||||
}
|
||||
|
||||
/* write the changes in the view of `term_port` to the terminal
|
||||
*/
|
||||
app.show().await.expect("output error!");
|
||||
}
|
88
lib-nested-core/src/editors/char/ctx.rs
Normal file
88
lib-nested-core/src/editors/char/ctx.rs
Normal file
|
@ -0,0 +1,88 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{
|
||||
OuterViewPort,
|
||||
singleton::*,
|
||||
port::UpdateTask
|
||||
},
|
||||
buffer::singleton::*
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
repr_tree::{Context, ReprTree, ReprLeaf, ReprTreeExt, GenericReprTreeMorphism},
|
||||
edit_tree::{EditTree, TreeNavResult},
|
||||
editors::{
|
||||
char::CharEditor,
|
||||
ObjCommander
|
||||
},
|
||||
},
|
||||
std::sync::Arc,
|
||||
std::sync::RwLock
|
||||
};
|
||||
|
||||
pub fn init_ctx( ctx: Arc<RwLock<Context>> ) {
|
||||
|
||||
let char_morph_to_edittree = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "Char"),
|
||||
Context::parse(&ctx, "Char~EditTree"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |rt, σ| {
|
||||
{
|
||||
let mut b = rt.write().unwrap().singleton_buffer::<char>();
|
||||
if let Some(buf) = b {
|
||||
// buffer already exists
|
||||
} else {
|
||||
// create char buffer
|
||||
rt.write().unwrap().insert_leaf(
|
||||
vec![].into_iter(),
|
||||
ReprLeaf::from_singleton_buffer(SingletonBuffer::new('\0'))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let char_buf = rt.singleton_buffer::<char>();
|
||||
let mut edittree = CharEditor::new_edit_tree(
|
||||
ctx.clone(),
|
||||
char_buf,
|
||||
SingletonBuffer::<usize>::new(0).get_port()
|
||||
);
|
||||
|
||||
rt.insert_leaf(
|
||||
Context::parse(&ctx, "EditTree"),
|
||||
ReprLeaf::from_singleton_buffer(
|
||||
SingletonBuffer::new(
|
||||
Arc::new(RwLock::new(edittree))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
ctx.read().unwrap().setup_edittree(rt);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let char_morph_from_edittree = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "Char~EditTree"),
|
||||
Context::parse(&ctx, "Char"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |rt, σ|
|
||||
{
|
||||
let mut b = rt
|
||||
.descend(Context::parse(&ctx, "EditTree")).unwrap()
|
||||
.view_singleton::<Arc<RwLock<EditTree>>>();
|
||||
|
||||
rt.attach_leaf_to(
|
||||
Context::parse(&ctx, "Char"),
|
||||
b.map(|x|
|
||||
x.read().unwrap()
|
||||
.get_edit::<CharEditor>().unwrap()
|
||||
.read().unwrap()
|
||||
.get())
|
||||
);
|
||||
}
|
||||
});
|
||||
ctx.write().unwrap().morphisms.add_morphism( char_morph_to_edittree );
|
||||
ctx.write().unwrap().morphisms.add_morphism( char_morph_from_edittree );
|
||||
}
|
|
@ -17,72 +17,8 @@ use {
|
|||
std::sync::RwLock
|
||||
};
|
||||
|
||||
pub fn init_ctx( ctx: Arc<RwLock<Context>> ) {
|
||||
|
||||
let char_morph_to_edittree = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "Char"),
|
||||
Context::parse(&ctx, "Char~EditTree"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |rt, σ| {
|
||||
{
|
||||
let mut b = rt.write().unwrap().singleton_buffer::<char>();
|
||||
if let Some(buf) = b {
|
||||
// buffer already exists
|
||||
} else {
|
||||
// create char buffer
|
||||
rt.write().unwrap().insert_leaf(
|
||||
vec![].into_iter(),
|
||||
ReprLeaf::from_singleton_buffer(SingletonBuffer::new('\0'))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let char_buf = rt.singleton_buffer::<char>();
|
||||
let mut edittree = CharEditor::new_edit_tree(
|
||||
ctx.clone(),
|
||||
char_buf,
|
||||
SingletonBuffer::<usize>::new(0).get_port()
|
||||
);
|
||||
|
||||
rt.insert_leaf(
|
||||
Context::parse(&ctx, "EditTree"),
|
||||
ReprLeaf::from_singleton_buffer(
|
||||
SingletonBuffer::new(
|
||||
Arc::new(RwLock::new(edittree))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
ctx.read().unwrap().setup_edittree(rt);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let char_morph_from_edittree = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "Char~EditTree"),
|
||||
Context::parse(&ctx, "Char"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |rt, σ|
|
||||
{
|
||||
let mut b = rt
|
||||
.descend(Context::parse(&ctx, "EditTree")).unwrap()
|
||||
.view_singleton::<Arc<RwLock<EditTree>>>();
|
||||
|
||||
rt.attach_leaf_to(
|
||||
Context::parse(&ctx, "Char"),
|
||||
b.map(|x|
|
||||
x.read().unwrap()
|
||||
.get_edit::<CharEditor>().unwrap()
|
||||
.read().unwrap()
|
||||
.get())
|
||||
);
|
||||
}
|
||||
});
|
||||
ctx.write().unwrap().morphisms.add_morphism( char_morph_to_edittree );
|
||||
ctx.write().unwrap().morphisms.add_morphism( char_morph_from_edittree );
|
||||
}
|
||||
pub mod ctx;
|
||||
pub use crate::editors::char::ctx::init_ctx;
|
||||
|
||||
pub struct CharEditor {
|
||||
ctx: Arc<RwLock<Context>>,
|
||||
|
@ -146,4 +82,3 @@ impl CharEditor {
|
|||
.set_editor( editor.clone() )
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ mod tests;
|
|||
pub use {
|
||||
context::{Context},
|
||||
leaf::ReprLeaf,
|
||||
node::ReprTree,
|
||||
node::{ReprTree, ReprTreeArc},
|
||||
morphism::{GenericReprTreeMorphism}
|
||||
};
|
||||
|
||||
|
@ -42,7 +42,7 @@ pub trait ReprTreeExt {
|
|||
fn insert_leaf(&mut self, type_ladder: impl Into<TypeTerm>, leaf: ReprLeaf);
|
||||
fn insert_branch(&mut self, repr: Arc<RwLock<ReprTree>>);
|
||||
fn create_branch(&mut self, rung: impl Into<TypeTerm>);
|
||||
fn descend(&self, target_type: impl Into<TypeTerm>) -> Option<Arc<RwLock<ReprTree>>>;
|
||||
fn descend(&self, target_type: impl Into<TypeTerm>) -> Option< ReprTreeArc >;
|
||||
|
||||
fn attach_leaf_to<V: View + ?Sized + 'static>(&self, t: impl Into<TypeTerm>, v: OuterViewPort<V>) where V::Msg: Clone;
|
||||
fn get_port<V: View + ?Sized + 'static>(&self) -> Option<OuterViewPort<V>> where V::Msg: Clone;
|
||||
|
@ -100,7 +100,7 @@ impl ReprTreeExt for Arc<RwLock<ReprTree>> {
|
|||
self.write().unwrap().attach_leaf_to::<V>(type_ladder.into().get_lnf_vec().into_iter(), v)
|
||||
}
|
||||
|
||||
fn descend(&self, target_type: impl Into<TypeTerm>) -> Option<Arc<RwLock<ReprTree>>> {
|
||||
fn descend(&self, target_type: impl Into<TypeTerm>) -> Option< ReprTreeArc > {
|
||||
ReprTree::descend( self, target_type )
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,12 @@ use {
|
|||
pub struct ReprTree {
|
||||
halo: TypeTerm,
|
||||
type_tag: TypeTerm,
|
||||
branches: HashMap<TypeTerm, Arc<RwLock<ReprTree>>>,
|
||||
branches: HashMap<TypeTerm, ReprTreeArc>,
|
||||
leaf: Option< ReprLeaf >
|
||||
}
|
||||
|
||||
pub type ReprTreeArc = Arc<RwLock<ReprTree>>;
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl std::fmt::Debug for ReprTree {
|
||||
|
@ -50,20 +52,24 @@ impl std::fmt::Debug for ReprTree {
|
|||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl ReprTree {
|
||||
pub fn new(type_tag: impl Into<TypeTerm>) -> Self {
|
||||
let type_tag = type_tag.into();
|
||||
pub fn new(typ: impl Into<TypeTerm>) -> Self {
|
||||
let mut lnf = typ.into().get_lnf_vec();
|
||||
let head_type = lnf.remove(0);
|
||||
|
||||
let mut branches = HashMap::new();
|
||||
if lnf.len() > 0 {
|
||||
branches.insert( lnf[0].clone(), ReprTree::new_arc(TypeTerm::Ladder(lnf)) );
|
||||
}
|
||||
|
||||
assert!(type_tag.is_flat());
|
||||
|
||||
ReprTree {
|
||||
halo: TypeTerm::unit(),
|
||||
type_tag: type_tag.clone(),
|
||||
branches: HashMap::new(),
|
||||
type_tag: head_type,
|
||||
branches,
|
||||
leaf: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_arc(type_tag: impl Into<TypeTerm>) -> Arc<RwLock<Self>> {
|
||||
pub fn new_arc(type_tag: impl Into<TypeTerm>) -> ReprTreeArc {
|
||||
Arc::new(RwLock::new(Self::new(type_tag)))
|
||||
}
|
||||
|
||||
|
@ -102,7 +108,7 @@ impl ReprTree {
|
|||
leaf_types
|
||||
}
|
||||
|
||||
pub fn insert_branch(&mut self, repr: Arc<RwLock<ReprTree>>) {
|
||||
pub fn insert_branch(&mut self, repr: ReprTreeArc) {
|
||||
let branch_type = repr.read().unwrap().get_type().clone();
|
||||
|
||||
assert!(branch_type.is_flat());
|
||||
|
@ -115,14 +121,14 @@ impl ReprTree {
|
|||
self.branches.insert(branch_type, repr.clone());
|
||||
}
|
||||
|
||||
pub fn from_char(ctx: &Arc<RwLock<Context>>, c: char ) -> Arc<RwLock<Self>> {
|
||||
pub fn from_char(ctx: &Arc<RwLock<Context>>, c: char ) -> ReprTreeArc {
|
||||
ReprTree::from_singleton_buffer(
|
||||
Context::parse(ctx, "Char"),
|
||||
SingletonBuffer::new(c)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn from_view<V>( type_tag: impl Into<TypeTerm>, view: OuterViewPort<V> ) -> Arc<RwLock<Self>>
|
||||
pub fn from_view<V>( type_tag: impl Into<TypeTerm>, view: OuterViewPort<V> ) -> ReprTreeArc
|
||||
where V: View + ?Sized + 'static,
|
||||
V::Msg: Clone
|
||||
{
|
||||
|
@ -131,7 +137,7 @@ impl ReprTree {
|
|||
Arc::new(RwLock::new(rt))
|
||||
}
|
||||
|
||||
pub fn from_singleton_buffer<T>( type_tag: impl Into<TypeTerm>, buf: SingletonBuffer<T> ) -> Arc<RwLock<Self>>
|
||||
pub fn from_singleton_buffer<T>( type_tag: impl Into<TypeTerm>, buf: SingletonBuffer<T> ) -> ReprTreeArc
|
||||
where T: Clone + Send + Sync + 'static
|
||||
{
|
||||
let mut rt = ReprTree::new(type_tag);
|
||||
|
@ -142,7 +148,7 @@ impl ReprTree {
|
|||
pub fn from_str(
|
||||
type_tag: impl Into<TypeTerm>,
|
||||
val: &str
|
||||
) -> Arc<RwLock<Self>> {
|
||||
) -> ReprTreeArc {
|
||||
let mut lnf = type_tag.into().get_lnf_vec();
|
||||
|
||||
let mut rt = ReprTree::from_vec_buffer(
|
||||
|
@ -159,7 +165,7 @@ impl ReprTree {
|
|||
rt
|
||||
}
|
||||
|
||||
pub fn from_vec_buffer<T>( type_tag: impl Into<TypeTerm>, buf: VecBuffer<T> ) -> Arc<RwLock<Self>>
|
||||
pub fn from_vec_buffer<T>( type_tag: impl Into<TypeTerm>, buf: VecBuffer<T> ) -> ReprTreeArc
|
||||
where T: Clone + Send + Sync + 'static
|
||||
{
|
||||
let mut rt = ReprTree::new(type_tag);
|
||||
|
@ -336,13 +342,13 @@ impl ReprTree {
|
|||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub fn descend_one(&self, dst_type: impl Into<TypeTerm>) -> Option<Arc<RwLock<ReprTree>>> {
|
||||
pub fn descend_one(&self, dst_type: impl Into<TypeTerm>) -> Option< ReprTreeArc > {
|
||||
let dst_type = dst_type.into();
|
||||
assert!( dst_type.is_flat() );
|
||||
self.branches.get(&dst_type).cloned()
|
||||
}
|
||||
|
||||
pub fn descend_ladder(rt: &Arc<RwLock<Self>>, mut repr_ladder: impl Iterator<Item = TypeTerm>) -> Option<Arc<RwLock<ReprTree>>> {
|
||||
pub fn descend_ladder(rt: &Arc<RwLock<Self>>, mut repr_ladder: impl Iterator<Item = TypeTerm>) -> Option< ReprTreeArc > {
|
||||
if let Some(first) = repr_ladder.next() {
|
||||
let rt = rt.read().unwrap();
|
||||
repr_ladder.fold(
|
||||
|
@ -353,7 +359,7 @@ impl ReprTree {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn descend(rt: &Arc<RwLock<Self>>, dst_type: impl Into<TypeTerm>) -> Option<Arc<RwLock<ReprTree>>> {
|
||||
pub fn descend(rt: &Arc<RwLock<Self>>, dst_type: impl Into<TypeTerm>) -> Option< ReprTreeArc > {
|
||||
let mut lnf = dst_type.into().get_lnf_vec();
|
||||
if lnf.len() > 0 {
|
||||
if lnf[0] == rt.get_type() {
|
||||
|
|
|
@ -1,5 +1,27 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{
|
||||
OuterViewPort
|
||||
},
|
||||
buffer::vec::*,
|
||||
projection::decorate_sequence::Separate
|
||||
},
|
||||
nested::{
|
||||
edit_tree::{
|
||||
TreeNav
|
||||
},
|
||||
editors::list::{
|
||||
ListCursorMode
|
||||
}
|
||||
},
|
||||
crate::{TerminalView, make_label, TerminalProjections}
|
||||
};
|
||||
|
||||
impl TreeNav {
|
||||
pub trait TreeNavExt {
|
||||
fn get_cursor_widget(&self) -> OuterViewPort<dyn TerminalView>;
|
||||
}
|
||||
|
||||
impl<T: TreeNav> TreeNavExt for T {
|
||||
fn get_cursor_widget(&self) -> OuterViewPort<dyn TerminalView> {
|
||||
VecBuffer::with_data(
|
||||
vec![
|
||||
|
@ -30,4 +52,3 @@ impl TreeNav {
|
|||
.flatten()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
pub mod color;
|
||||
pub mod keymap;
|
||||
|
||||
pub mod cursor_widget;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue