188 lines
6.3 KiB
Rust
188 lines
6.3 KiB
Rust
//! In the following example, a <List Char> editor
|
||
//! as before is used, but its data is morphed into
|
||
//! representing a positional integer which is then
|
||
//! projected into different radices and displayed
|
||
//! in different views on screen
|
||
|
||
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, ReprTreeBuilder, ReprTree, ReprTreeExt, ReprLeaf},
|
||
edit_tree::{EditTree, TreeNav, TreeCursor}
|
||
},
|
||
nested_tty::{
|
||
DisplaySegment, TTYApplication,
|
||
TerminalCompositor, TerminalStyle, TerminalView,
|
||
TerminalAtom, TerminalEvent,
|
||
edit_tree::cursor_widget::TreeNavExt
|
||
},
|
||
r3vi::{
|
||
buffer::{singleton::*, vec::*},
|
||
view::{port::UpdateTask, ViewPort, 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);
|
||
|
||
/* Create a Representation-Tree of type `ℕ`
|
||
* with a specific representation-path (big-endian hexadecimal string)
|
||
*/
|
||
let int_builder = ReprTreeBuilder::new( ctx.clone() )
|
||
.require(Context::parse(&ctx,
|
||
//"ℕ ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16>> ~
|
||
"<List <Digit 16>> ~ <List Char> ~ EditTree"))
|
||
/*
|
||
.require(Context::parse(&ctx,
|
||
"ℕ ~ <PosInt 10 BigEndian> ~ EditTree"))
|
||
.require(Context::parse(&ctx,
|
||
"ℕ ~ <PosInt 8 BigEndian> ~ EditTree"))
|
||
.require(Context::parse(&ctx,
|
||
"ℕ ~ <PosInt 2 BigEndian> ~ EditTree"))
|
||
*/
|
||
;
|
||
|
||
let mut rt_int = nested::repr_tree::ReprTree::from_str("3");
|
||
rt_int.write().unwrap().set_halo(
|
||
/* HALO TYPE (append to top of type ladder) */
|
||
Context::parse(&ctx, /*"
|
||
ℕ
|
||
~ <PosInt 16 BigEndian>
|
||
~ <Seq <Digit 16>>
|
||
~ <List <Digit 16>>
|
||
*/
|
||
" <List <Digit 16>>
|
||
~ <List Char>
|
||
")
|
||
);
|
||
rt_int = int_builder.build_from( rt_int )
|
||
.expect("cant build initial repr tree");
|
||
|
||
eprintln!("rt_int = \n{}\n", rt_int.read().unwrap().fmt(&ctx, 0));
|
||
|
||
/* list of editors
|
||
*/
|
||
let mut list_editor = nested::editors::list::ListEditor::new(
|
||
ctx.clone(),
|
||
Context::parse(&ctx, "EditTree"),
|
||
ReprTreeBuilder::new(ctx.clone())
|
||
);
|
||
|
||
// add all desired editors to the list
|
||
for edit_leaf in int_builder.required_leaves.iter() {
|
||
let leaf_rt = rt_int.descend(edit_leaf.clone()).unwrap();
|
||
list_editor.data.push(leaf_rt);
|
||
}
|
||
|
||
let mut edittree = list_editor.into_node(SingletonBuffer::new(0).get_port());
|
||
nested_tty::editors::list::PTYListController::for_node(&mut edittree, None, None);
|
||
|
||
/* cursors are a bit screwed initially so fix them up
|
||
* TODO: how to fix this generally?
|
||
*/
|
||
for edit_leaf in int_builder.required_leaves.iter() {
|
||
let leaf_rt = rt_int.descend(edit_leaf.clone()).unwrap();
|
||
leaf_rt.edittree(&ctx).get_mut().goto(TreeCursor::none());
|
||
}
|
||
|
||
let first_idx : usize = 0;
|
||
int_builder.update( &rt_int, int_builder.required_leaves[first_idx].clone() );
|
||
|
||
edittree.goto(TreeCursor {
|
||
leaf_mode: nested::editors::list::ListCursorMode::Insert,
|
||
tree_addr: vec![first_idx as isize, 0]
|
||
});
|
||
let edittree = Arc::new(RwLock::new(edittree));
|
||
|
||
|
||
/* setup terminal
|
||
*/
|
||
let app = TTYApplication::new({
|
||
/* event handler
|
||
*/
|
||
let ctx = ctx.clone();
|
||
let rt_int = rt_int.clone();
|
||
let last_idx = RwLock::new(first_idx);
|
||
let int_builder = int_builder.clone();
|
||
let edittree = edittree.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 as usize {
|
||
int_builder.update( &rt_int, int_builder.required_leaves[ci as usize].clone() );
|
||
*li = ci as usize;
|
||
}
|
||
}
|
||
|
||
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 et = edittree.read().unwrap();
|
||
comp.push(et.get_cursor_widget());
|
||
|
||
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.edittree( &ctx );
|
||
|
||
let box_port = ViewPort::new();
|
||
let ascii_box = nested_tty::widgets::ascii_box::AsciiBox::new(
|
||
Vector2::new(30, 1),
|
||
edittree.get().display_view(),
|
||
box_port.inner()
|
||
);
|
||
|
||
comp.push(
|
||
box_port.outer()
|
||
.offset(Vector2::new(1,y)));
|
||
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)));
|
||
}
|
||
|
||
let mut y = 2;
|
||
for t in int_builder.required_leaves.iter() {
|
||
show_edit_tree(&ctx, &mut comp, &rt_int.descend(t.clone()).expect(""), y);
|
||
y += 4;
|
||
}
|
||
}
|
||
|
||
/* write the changes in the view of `term_port` to the terminal
|
||
*/
|
||
app.show().await.expect("output error!");
|
||
}
|