lib-nested/examples/tty-04-posint/src/main.rs

395 lines
15 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 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, ReprTree, ReprTreeExt, ReprLeaf},
edit_tree::{EditTree, TreeNav, TreeCursor}
},
nested_tty::{
DisplaySegment, TTYApplication,
TerminalCompositor, TerminalStyle, TerminalView,
TerminalAtom, TerminalEvent
},
r3vi::{
buffer::{singleton::*, vec::*},
view::{port::UpdateTask, singleton::*, list::*, sequence::*},
projection::*
},
std::sync::{Arc, RwLock},
};
fn rebuild_projections(
ctx: Arc<RwLock<Context>>,
repr_tree: Arc<RwLock<ReprTree>>,
morph_types: Vec< (laddertypes::TypeTerm, laddertypes::TypeTerm) >
) {
repr_tree.write().unwrap().detach(&ctx);
for (src_type, dst_type) in morph_types.iter() {
ctx.read().unwrap().morphisms.apply_morphism(
repr_tree.clone(),
&src_type,
&dst_type
);
}
}
fn setup_hex_master(ctx: &Arc<RwLock<Context>>, rt_int: &Arc<RwLock<ReprTree>>) {
rebuild_projections(
ctx.clone(),
rt_int.clone(),
vec![
// extract values from hex-editor
(
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char> ~ EditTree",
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char>"
),
// convert to little-endian
(
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char>",
" ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char>"
),
// convert digit representation from char to u64
(
" ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char>",
" ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ _2^64 ~ machine.UInt64>"
),
// convert radix to decimal
(
" ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ _2^64 ~ machine.UInt64>",
" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ _2^64 ~ machine.UInt64>"
),
// convert decimal digit representation back to char
(
" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ _2^64 ~ machine.UInt64>",
" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char>"
),
// convert to big-endian
(
" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char>",
" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char>"
),
// decimal editor
(
" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char>",
" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char ~ EditTree>"
),
(
" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char ~ EditTree>",
" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char ~ EditTree> ~ <Vec EditTree>"
),
(
" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char ~ EditTree> ~ <Vec EditTree>",
" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ EditTree"
),
].into_iter()
.map(|(s,d)| (Context::parse(&ctx, s), Context::parse(&ctx, d)))
.collect()
);
}
fn setup_dec_master(ctx: &Arc<RwLock<Context>>, rt_int: &Arc<RwLock<ReprTree>>) {
rebuild_projections(
ctx.clone(),
rt_int.clone(),
vec![
// extract values from decimal-editor
(
" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ EditTree",
" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char>"
),
// convert to little-endian
(
" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char>",
" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char>"
),
// convert digit representation to u64
(
" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char>",
" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ _2^64 ~ machine.UInt64>"
),
// convert radix to decimal
(
" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ _2^64 ~ machine.UInt64>",
" ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ _2^64 ~ machine.UInt64>"
),
// convert back digit representation char
(
" ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ _2^64 ~ machine.UInt64>",
" ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char>"
),
// convert back to big-endian
(
" ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char>",
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char>"
),
// hex editor
(
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char>",
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char ~ EditTree>"
),
(
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char ~ EditTree>",
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char ~ EditTree> ~ <Vec EditTree>"
),
(
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char ~ EditTree> ~ <Vec EditTree>",
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char> ~ EditTree"
),
].into_iter()
.map(|(s,d)| (Context::parse(&ctx, s), Context::parse(&ctx, d)))
.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);
/* Create a Representation-Tree of type ``
*/
let mut rt_int = ReprTree::new_arc( Context::parse(&ctx, "") );
/* Add a specific Representation-Path (big-endian hexadecimal)
*/
let mut digits_hex = VecBuffer::with_data(vec![ 'c', 'f', 'f' ]);
rt_int.insert_leaf(
Context::parse(&ctx, "<PosInt 16 BigEndian>~<Seq <Digit 16>>~<List <Digit 16>>~<List Char>~<Vec Char>"),
nested::repr_tree::ReprLeaf::from_vec_buffer( digits_hex.clone() )
);
let mut digits_dec = VecBuffer::with_data(vec!['3', '2', '1']);
rt_int.insert_leaf(
Context::parse(&ctx, "<PosInt 10 BigEndian>~<Seq <Digit 10>>~<List <Digit 10>>~<List Char>~<Vec Char>"),
nested::repr_tree::ReprLeaf::from_vec_buffer( digits_dec.clone() )
);
let mut digits_hex_editvec = VecBuffer::<Arc<RwLock<EditTree>>>::new();
rt_int.insert_leaf(
Context::parse(&ctx, "
<PosInt 16 BigEndian>
~ <Seq <Digit 16>>
~ <List <Digit 16>
~ Char
~ EditTree>
~ <Vec EditTree>
"),
nested::repr_tree::ReprLeaf::from_vec_buffer( digits_hex_editvec.clone() )
);
let mut digits_dec_editvec = VecBuffer::<Arc<RwLock<EditTree>>>::new();
rt_int.insert_leaf(
Context::parse(&ctx, "
<PosInt 10 BigEndian>
~ <Seq <Digit 10>>
~ <List <Digit 10>
~ Char
~ EditTree>
~ <Vec EditTree>
"),
nested::repr_tree::ReprLeaf::from_vec_buffer( digits_dec_editvec.clone() )
);
/* initially copy values from Vec to EditTree...
*/
rebuild_projections(
ctx.clone(),
rt_int.clone(),
// master representation
vec![
(
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char> ~ <Vec Char>",
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char>"
),
(
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char>",
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char ~ EditTree>"
),
(
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char> ~ <List EditTree>",
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char> ~ <List EditTree> ~ <Vec EditTree>"
),
(
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char> ~ <List EditTree> ~ <Vec EditTree>",
" ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char> ~ EditTree"
),
].into_iter()
.map(|(s,d)| (Context::parse(&ctx, s), Context::parse(&ctx, d)))
.collect()
);
setup_hex_master(&ctx, &rt_int);
let edittree_hex_be_list = ctx.read().unwrap()
.setup_edittree(
rt_int.descend(Context::parse(&ctx,"
<PosInt 16 BigEndian>
~ <Seq <Digit 16>>
~ <List <Digit 16>>
~ <List Char>
")).expect("descend"),
SingletonBuffer::new(0).get_port()
).unwrap().get();
let edittree_dec_be_list = ctx.read().unwrap()
.setup_edittree(
rt_int.descend(Context::parse(&ctx,"
<PosInt 10 BigEndian>
~ <Seq <Digit 10>>
~ <List <Digit 10>>
~ <List Char>
")).expect("descend"),
SingletonBuffer::new(0).get_port()
).unwrap().get();
let hex_digits_view = rt_int.descend(Context::parse(&ctx, "
<PosInt 16 LittleEndian>
~ <Seq <Digit 16> >
~ <List <Digit 16>
~ _2^64
~ machine.UInt64 >
")).expect("descend")
.view_list::<u64>()
.map(|v| TerminalAtom::from(char::from_digit(*v as u32, 16)))
.to_sequence()
.to_grid_horizontal()
;
let dec_digits_view = rt_int.descend(Context::parse(&ctx, "
<PosInt 10 LittleEndian>
~ <Seq <Digit 10>>
~ <List <Digit 10>
~ _2^64
~ machine.UInt64 >
")).expect("descend")
.view_list::<u64>()
.map(|v| TerminalAtom::from(char::from_digit(*v as u32, 10)))
.to_sequence()
.to_grid_horizontal()
;
/* list of both editors
*/
let mut list_editor = nested::editors::list::ListEditor::new(ctx.clone(), Context::parse(&ctx, "<Seq Char>"));
list_editor.data.push( edittree_hex_be_list.clone() );
list_editor.data.push( edittree_dec_be_list.clone() );
let mut edittree = list_editor.into_node(SingletonBuffer::new(0).get_port());
/* cursors are a bit screwed initially so fix them up
* TODO: how to fix this generally?
*/
edittree_hex_be_list.write().unwrap().goto(TreeCursor::none());
edittree_dec_be_list.write().unwrap().goto(TreeCursor::none());
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 rt_int = rt_int.clone();
let last_idx = RwLock::new(1);
move |ev| {
let cur = edittree.read().unwrap().get_cursor();
if cur.tree_addr.len() > 0 {
match cur.tree_addr[0] {
0 => {
let mut li = last_idx.write().unwrap();
if *li != 0 {
setup_hex_master(&ctx, &rt_int);
*li = 0;
}
}
1 => {
let mut li = last_idx.write().unwrap();
if *li != 1 {
setup_dec_master(&ctx, &rt_int);
*li = 1;
}
}
_=>{}
}
}
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()
.offset(Vector2::new(1,y+1)));
}
show_edit_tree(&ctx, &mut comp, &rt_int.descend(Context::parse(&ctx, "<PosInt 16 BigEndian> ~ <Seq~List <Digit 16>~Char>")).expect(""), 1);
show_edit_tree(&ctx, &mut comp, &rt_int.descend(Context::parse(&ctx, "<PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char>")).expect(""), 4);
/* project the seq of u64 representations to a view
*/
comp.push(nested_tty::make_label("dec: ").offset(Vector2::new(3,7)));
comp.push(dec_digits_view.offset(Vector2::new(8,7)).map_item(|_,a| {
a.add_style_back(TerminalStyle::fg_color((30,90,200)))
}));
comp.push(nested_tty::make_label("hex: ").offset(Vector2::new(3,8)));
comp.push(hex_digits_view.offset(Vector2::new(8,8)).map_item(|_,a| {
a.add_style_back(TerminalStyle::fg_color((200, 200, 30)))
}));
}
/* write the changes in the view of `term_port` to the terminal
*/
app.show().await.expect("output error!");
}