Compare commits
76 commits
Author | SHA1 | Date | |
---|---|---|---|
32b2cb5d1f | |||
41c02465be | |||
dad789227c | |||
2c2268c918 | |||
fe4b571b8c | |||
e09f3e5656 | |||
b2083aec4c | |||
50fe43df97 | |||
af34fc9976 | |||
689ac95486 | |||
9b5dfc9cca | |||
9f53b65074 | |||
4b7d929abc | |||
38c772389f | |||
0a6405b08e | |||
7f18fd7755 | |||
6ed456e3ff | |||
aed4cad1e4 | |||
b3d0e4f03c | |||
fb796cda04 | |||
e7331b36ae | |||
0bcfd7a65a | |||
7762fa4b12 | |||
786866746c | |||
8d637a6f32 | |||
6e2b82585e | |||
ffeb4b8e73 | |||
508e716a6a | |||
4c0e9da2d3 | |||
830ce613ea | |||
a3c701ce88 | |||
6e8bb0aeb5 | |||
e86070da50 | |||
bb846afc7c | |||
ab51ea5d3d | |||
cdf03c9aae | |||
d02f33ee17 | |||
fdecc29e80 | |||
40a5da4512 | |||
91e56d876d | |||
edf088b853 | |||
473dd5f4dc | |||
33e97ed5e3 | |||
ecaa74ccfd | |||
658f5c1000 | |||
03dc9f1133 | |||
d7d0a46c7b | |||
77d9e64531 | |||
73d457ba24 | |||
647a5d77b6 | |||
e46c143dec | |||
0ac4a34743 | |||
863fe95848 | |||
fdf2d60b35 | |||
8471c7a90f | |||
caa0c9a5c0 | |||
668b0b8b96 | |||
47a35f22b7 | |||
97a5b580df | |||
193b8c8cac | |||
834bb49b5e | |||
be3eefc3a5 | |||
bee1b43ddc | |||
6a3afde29c | |||
39fbae7740 | |||
d15077aca0 | |||
25d8acdb72 | |||
85b614a9bb | |||
f151f9c5d2 | |||
57cb1ee3ff | |||
9b9ea77cb0 | |||
f3ad5c78d7 | |||
b1c17da75f | |||
ea38b0f9b0 | |||
f8e872acda | |||
4bf03c356d |
115 changed files with 5868 additions and 2508 deletions
19
Cargo.toml
19
Cargo.toml
|
@ -1,10 +1,15 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"nested",
|
||||
# "terminal/display_server",
|
||||
# "terminal/ansi_parser",
|
||||
# "math/str2int",
|
||||
# "math/int2str",
|
||||
# "math/radix_transform",
|
||||
# "math/fib"
|
||||
"lib-nested-core",
|
||||
"lib-nested-tty",
|
||||
|
||||
"srv-tty-output",
|
||||
"srv-pty-capture",
|
||||
|
||||
"examples/tty-01-hello",
|
||||
"examples/tty-02-digit",
|
||||
"examples/tty-03-string",
|
||||
"examples/tty-04-posint",
|
||||
"examples/tty-05-dictionary",
|
||||
"examples/tty-06-lines",
|
||||
]
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
[package]
|
||||
name = "radix_transform"
|
||||
name = "tty-01-hello"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
nested = { path = "../../nested" }
|
||||
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"]
|
||||
|
8
examples/tty-01-hello/README.md
Normal file
8
examples/tty-01-hello/README.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
# tty-01-hello
|
||||
|
||||
This example shows how to:
|
||||
- initialize the TTY backend (`lib-nestetd-tty`),
|
||||
- create a simple 'Hello World' output,
|
||||
- create color gradients on the outputted text
|
||||
utilizing basic projection functionality from `lib-r3vi`,
|
||||
- perform basic layouting & compositing.
|
60
examples/tty-01-hello/src/main.rs
Normal file
60
examples/tty-01-hello/src/main.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
//! This example shows how to:
|
||||
//! - initialize the TTY backend (`lib-nestetd-tty`),
|
||||
//! - create a simple 'Hello World' output,
|
||||
//! - create color gradients on the outputted text
|
||||
//! utilizing basic projection functionality from `lib-r3vi`,
|
||||
//! - perform basic layouting & compositing.
|
||||
|
||||
extern crate cgmath;
|
||||
extern crate nested;
|
||||
extern crate nested_tty;
|
||||
extern crate r3vi;
|
||||
extern crate termion;
|
||||
|
||||
use {
|
||||
cgmath::Vector2,
|
||||
nested::repr_tree::Context,
|
||||
nested_tty::{Terminal, TerminalCompositor, TTYApplication, TerminalEvent, TerminalStyle, TerminalView},
|
||||
r3vi::view::{port::UpdateTask, ViewPort},
|
||||
std::sync::{Arc, RwLock},
|
||||
termion::event::{Event, Key},
|
||||
};
|
||||
|
||||
#[async_std::main]
|
||||
async fn main() {
|
||||
/* Initialize our terminal.
|
||||
*/
|
||||
let tty_app = TTYApplication::new(|event| { /* handle event */ });
|
||||
|
||||
/* Setup our "root" view of the application.
|
||||
* This will be the compositor, which is able to
|
||||
* mix multiple `TerminalView`-Views together.
|
||||
* Its output is routed to the `app.port` Viewport,
|
||||
* so it will be displayed on TTY-output.
|
||||
*/
|
||||
let compositor = TerminalCompositor::new(tty_app.port.inner());
|
||||
|
||||
/* Add the label 'test' at position (7, 2)
|
||||
*/
|
||||
compositor
|
||||
.write()
|
||||
.unwrap()
|
||||
.push(nested_tty::make_label("test").offset(Vector2::new(7, 2)));
|
||||
|
||||
/* Add a 'Hello World' label at position (5, 3)
|
||||
* and set a coloring determined by formula from
|
||||
* the position of each character.
|
||||
*/
|
||||
compositor.write().unwrap().push(
|
||||
nested_tty::make_label("Hello World")
|
||||
.map_item(|p, a| {
|
||||
a.add_style_back(TerminalStyle::fg_color(((25 * p.x % 255) as u8, 200, 0)))
|
||||
})
|
||||
.offset(Vector2::new(5, 3)),
|
||||
);
|
||||
|
||||
/* write the changes in the root-view to the terminal
|
||||
*/
|
||||
tty_app.show().await.expect("output error!");
|
||||
}
|
||||
|
19
examples/tty-02-digit/Cargo.toml
Normal file
19
examples/tty-02-digit/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "tty-02-digit"
|
||||
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"]
|
||||
|
4
examples/tty-02-digit/README.md
Normal file
4
examples/tty-02-digit/README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
# tty-02-digit
|
||||
|
||||
This example demonstrates how a very simple editor for hexadecimal digits
|
||||
can be created with `lib-nested` and the `lib-nested-tty` backend.
|
137
examples/tty-02-digit/src/main.rs
Normal file
137
examples/tty-02-digit/src/main.rs
Normal file
|
@ -0,0 +1,137 @@
|
|||
//! This example demonstrates how a very simple editor for hexadecimal digits
|
||||
//! can be created with `lib-nested` and the `lib-nested-tty` backend.
|
||||
|
||||
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},
|
||||
edit_tree::{EditTree}
|
||||
},
|
||||
nested_tty::{
|
||||
DisplaySegment, TTYApplication,
|
||||
TerminalCompositor, TerminalStyle, TerminalView,
|
||||
TerminalAtom, TerminalEvent
|
||||
},
|
||||
r3vi::{
|
||||
buffer::{singleton::*, vec::*},
|
||||
view::{port::UpdateTask, list::*}
|
||||
},
|
||||
std::sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
#[async_std::main]
|
||||
async fn main() {
|
||||
/* setup context & create Editor-Tree
|
||||
*/
|
||||
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);
|
||||
|
||||
/* structure of Repr-Tree
|
||||
*
|
||||
* === Repr-Tree ===
|
||||
*
|
||||
* <Digit 10>
|
||||
* / | \
|
||||
* / | \
|
||||
* / | \
|
||||
* u64 EditTree Char
|
||||
* - Editor \
|
||||
* - Display EditTree
|
||||
* / | \ - Editor
|
||||
* / | \ - Display
|
||||
* TTY PixelBuf SDF / | \
|
||||
* / | \
|
||||
* TTY PixelBuf SDF
|
||||
*/
|
||||
let mut rt_digit = ReprTree::new_arc( Context::parse(&ctx, "<Digit 16>") );
|
||||
|
||||
/* add initial representation
|
||||
* <Digit 16> ~ Char
|
||||
*/
|
||||
rt_digit.insert_leaf(
|
||||
Context::parse(&ctx, "Char"),
|
||||
nested::repr_tree::ReprLeaf::from_singleton_buffer( SingletonBuffer::new('5') )
|
||||
);
|
||||
|
||||
/* furthermore, setup projections to and from u8 value,
|
||||
* this synchronizes the buffers
|
||||
*/
|
||||
ctx.read().unwrap().apply_morphism(
|
||||
&rt_digit,
|
||||
&laddertypes::MorphismType {
|
||||
src_type: Context::parse(&ctx, "<Digit 16>~Char"),
|
||||
dst_type: Context::parse(&ctx, "<Digit 16>~ℤ_2^64~machine.UInt64")
|
||||
}
|
||||
);
|
||||
ctx.read().unwrap().apply_morphism(
|
||||
&rt_digit,
|
||||
&laddertypes::MorphismType {
|
||||
src_type: Context::parse(&ctx, "<Digit 16>~Char"),
|
||||
dst_type: Context::parse(&ctx, "<Digit 16>~EditTree")
|
||||
}
|
||||
);
|
||||
|
||||
/* setup terminal
|
||||
*/
|
||||
let app = TTYApplication::new({
|
||||
/* event handler
|
||||
*/
|
||||
let ctx = ctx.clone();
|
||||
let digit_edittree = rt_digit.edittree( &ctx );
|
||||
move |ev| {
|
||||
digit_edittree.get().write().unwrap().send_cmd_obj(ev.to_repr_tree(&ctx));
|
||||
}
|
||||
});
|
||||
|
||||
/* setup display view routed to `app.port`
|
||||
*/
|
||||
let compositor = TerminalCompositor::new(app.port.inner());
|
||||
|
||||
// add some views to the display compositor
|
||||
{
|
||||
let mut comp = compositor.write().unwrap();
|
||||
|
||||
comp.push(
|
||||
nested_tty::make_label("Hello World")
|
||||
.map_item(|p, a| {
|
||||
a.add_style_back(TerminalStyle::fg_color(((25 * p.x % 255) as u8, 200, 0)))
|
||||
})
|
||||
.offset(Vector2::new(5,0)));
|
||||
|
||||
let label_str = ctx.read().unwrap().type_term_to_str(&rt_digit.read().unwrap().get_type());
|
||||
comp.push(
|
||||
nested_tty::make_label(&label_str)
|
||||
.map_item(|_pt,atom| atom.add_style_front(TerminalStyle::fg_color((90,90,90))))
|
||||
.offset(Vector2::new(1,1)));
|
||||
|
||||
comp.push(rt_digit
|
||||
.edittree( &ctx ).get().read().unwrap()
|
||||
.display_view()
|
||||
.offset(Vector2::new(3,2)));
|
||||
|
||||
comp.push(rt_digit
|
||||
.descend(Context::parse(&ctx, "ℤ_2^64~machine.UInt64")).unwrap()
|
||||
.view_u64()
|
||||
.map(|d| nested_tty::make_label(&format!("Digit value={}", d)))
|
||||
.to_grid()
|
||||
.flatten()
|
||||
.offset(Vector2::new(5,3)));
|
||||
}
|
||||
|
||||
/* write the changes in the view of `term_port` to the terminal
|
||||
*/
|
||||
app.show().await.expect("output error!");
|
||||
}
|
19
examples/tty-03-string/Cargo.toml
Normal file
19
examples/tty-03-string/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "tty-03-string"
|
||||
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"]
|
||||
|
8
examples/tty-03-string/README.md
Normal file
8
examples/tty-03-string/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.
|
193
examples/tty-03-string/src/main.rs
Normal file
193
examples/tty-03-string/src/main.rs
Normal file
|
@ -0,0 +1,193 @@
|
|||
//! 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.
|
||||
|
||||
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},
|
||||
edit_tree::{EditTree}
|
||||
},
|
||||
nested_tty::{
|
||||
DisplaySegment, TTYApplication,
|
||||
TerminalCompositor, TerminalStyle, TerminalView,
|
||||
TerminalAtom, TerminalEvent
|
||||
},
|
||||
r3vi::{
|
||||
buffer::{singleton::*, vec::*},
|
||||
view::{port::UpdateTask, list::*, sequence::SequenceViewExt}
|
||||
},
|
||||
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 <List Char>
|
||||
*/
|
||||
let mut rt_string = ReprTree::from_str(
|
||||
Context::parse(&ctx, "<List Char>~<Vec Char>"),
|
||||
"hello world"
|
||||
);
|
||||
|
||||
let mut ldata = VecBuffer::new();
|
||||
for c in "Hello World".chars() {
|
||||
let rt = ReprTree::from_singleton_buffer(
|
||||
Context::parse(&ctx, "Char"),
|
||||
SingletonBuffer::new(c));
|
||||
|
||||
ldata.push(rt);
|
||||
}
|
||||
|
||||
let mut ledit = nested::editors::list::ListEditor::with_data(
|
||||
ctx.clone(),
|
||||
Context::parse(&ctx, "Char"),
|
||||
ldata
|
||||
).into_node(
|
||||
SingletonBuffer::new(0).get_port()
|
||||
);
|
||||
|
||||
nested_tty::editors::list::PTYListStyle::for_node(&mut ledit, ("<", "", ">"));
|
||||
nested_tty::editors::list::PTYListController::for_node(&mut ledit, None, None);
|
||||
let ledittree = SingletonBuffer::new(Arc::new(RwLock::new(ledit)));
|
||||
|
||||
/*
|
||||
|
||||
/* create EditTree
|
||||
*/
|
||||
ctx.read().unwrap().apply_morphism(
|
||||
&rt_string,
|
||||
&laddertypes::MorphismType {
|
||||
src_type: Context::parse(&ctx, "<List~Vec Char>"),
|
||||
dst_type: Context::parse(&ctx, "<List Char> ~ EditTree")
|
||||
}
|
||||
);
|
||||
|
||||
// .. avoid cycle of projections..
|
||||
rt_string.write().unwrap().detach(&ctx);
|
||||
|
||||
/* In order to get access to the values that are modified by the Editor,
|
||||
* we apply a morphism that, given the List of Edit-Trees, extracts
|
||||
* the value from each EditTree and shows them in a ListView.
|
||||
*/
|
||||
ctx.read().unwrap().apply_morphism(
|
||||
&rt_string,
|
||||
&laddertypes::MorphismType {
|
||||
src_type: Context::parse(&ctx, "<List Char>~EditTree"),
|
||||
dst_type: Context::parse(&ctx, "<List Char>")
|
||||
}
|
||||
);
|
||||
|
||||
/* Now, get the ListView that serves our char-values.
|
||||
* This view is a projection created by the morphism that was called above.
|
||||
*/
|
||||
let mut chars_view = rt_string
|
||||
.read().unwrap()
|
||||
.get_port::<dyn ListView<char>>()
|
||||
.unwrap();
|
||||
|
||||
/* Lets add another morphism which will store the values
|
||||
* of the character-list in a `Vec<char>`
|
||||
*/
|
||||
ctx.read().unwrap().apply_morphism(
|
||||
&rt_string,
|
||||
&laddertypes::MorphismType {
|
||||
src_type: Context::parse(&ctx, "<List Char>"),
|
||||
dst_type: Context::parse(&ctx, "<List Char>~<Vec Char>")
|
||||
}
|
||||
);
|
||||
|
||||
/* Access the Vec<char> object (wrapped behind a VecBuffer<char>)
|
||||
* from the ReprTree.
|
||||
*/
|
||||
let chars_vec = rt_string
|
||||
.descend(Context::parse(&ctx, "<Vec Char>")).unwrap()
|
||||
.vec_buffer::<char>();
|
||||
|
||||
/* transform `ListView<char>` into a `TerminalView`
|
||||
*/
|
||||
let string_view_tty = chars_view
|
||||
.to_sequence()
|
||||
.to_grid_vertical()
|
||||
.map_item(|_pt,c| TerminalAtom::new(*c, TerminalStyle::fg_color((200,10,60))));
|
||||
*/
|
||||
/* setup terminal
|
||||
*/
|
||||
let app = TTYApplication::new({
|
||||
let edittree_list = ledittree.clone();//rt_string.edittree(&ctx).clone();
|
||||
|
||||
/* event handler
|
||||
*/
|
||||
let ctx = ctx.clone();
|
||||
move |ev| {
|
||||
edittree_list.get().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 label_str = ctx.read().unwrap().type_term_to_str(&rt_string.read().unwrap().get_type());
|
||||
comp.push(
|
||||
nested_tty::make_label(&label_str)
|
||||
.map_item(|_pt, atom| atom.add_style_front(TerminalStyle::fg_color((90,90,90))))
|
||||
.offset(Vector2::new(1,1)));
|
||||
/*comp.push(
|
||||
//rt_string.edittree(&ctx).get()
|
||||
ledittree.get()
|
||||
.read().unwrap()
|
||||
.display_view()
|
||||
.offset(Vector2::new(3,2)));*/
|
||||
/*
|
||||
comp.push(
|
||||
string_view_tty
|
||||
.offset(Vector2::new(5,3)));
|
||||
*/
|
||||
}
|
||||
|
||||
/* write the changes in the view of `term_port` to the terminal
|
||||
*/
|
||||
app.show().await.expect("output error!");
|
||||
/*
|
||||
/* need to call update because changes are applied lazily
|
||||
*/
|
||||
chars_vec.get_port().0.update();
|
||||
|
||||
/* Vec<char> to String
|
||||
*/
|
||||
let string = chars_vec
|
||||
.get_port()
|
||||
.to_sequence()
|
||||
.get_view().unwrap()
|
||||
//.data.read().unwrap()
|
||||
.iter().collect::<String>();
|
||||
|
||||
eprintln!("value of the editor was: {}\n\n", string);
|
||||
*/
|
||||
}
|
19
examples/tty-04-posint/Cargo.toml
Normal file
19
examples/tty-04-posint/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "tty-04-posint"
|
||||
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"]
|
||||
|
7
examples/tty-04-posint/README.md
Normal file
7
examples/tty-04-posint/README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# tty-04-posint
|
||||
|
||||
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
|
199
examples/tty-04-posint/src/main.rs
Normal file
199
examples/tty-04-posint/src/main.rs
Normal file
|
@ -0,0 +1,199 @@
|
|||
//! 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},
|
||||
};
|
||||
|
||||
#[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 mut rt_int = nested::repr_tree::ReprTree::from_str(
|
||||
/* TYPE */
|
||||
Context::parse(&ctx, "
|
||||
ℕ
|
||||
~ <PosInt 16 BigEndian>
|
||||
~ <Seq <Digit 16>>
|
||||
~ <List <Digit 16>>
|
||||
~ <List Char>
|
||||
~ <Vec Char>
|
||||
"),
|
||||
|
||||
/* VALUE */
|
||||
"cff"
|
||||
);
|
||||
|
||||
/* initially copy values from Vec to EditTree...
|
||||
*/
|
||||
ctx.read().unwrap().build_repr_tree(
|
||||
&rt_int,
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16>~Char> ~ <Vec Char>"),
|
||||
vec![
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16>> ~ EditTree"),
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt 16 LittleEndian> ~ <Seq~List <Digit 16>> ~ EditTree"),
|
||||
]);
|
||||
|
||||
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,
|
||||
"ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16>> ~ EditTree"),
|
||||
Context::parse(&ctx,
|
||||
"ℕ ~ <PosInt 16 LittleEndian> ~ <Seq~List <Digit 16>> ~ EditTree"),
|
||||
Context::parse(&ctx,
|
||||
"ℕ ~ <PosInt 16 BigEndian> ~ EditTree"),
|
||||
Context::parse(&ctx,
|
||||
"ℕ ~ <PosInt 8 BigEndian> ~ EditTree"),
|
||||
Context::parse(&ctx,
|
||||
"ℕ ~ <PosInt 2 BigEndian> ~ EditTree"),
|
||||
];
|
||||
|
||||
set_master(&ctx, &rt_int, editor_types.clone(), 0);
|
||||
|
||||
/* list of editors
|
||||
*/
|
||||
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 =
|
||||
rt_int
|
||||
.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());
|
||||
|
||||
/* cursors are a bit screwed initially so fix them up
|
||||
* TODO: how to fix this generally?
|
||||
*/
|
||||
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(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,
|
||||
&rt_int,
|
||||
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.edittree( &ctx );
|
||||
|
||||
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.get().read().unwrap().display_view()
|
||||
.offset(Vector2::new(1,y+1)));
|
||||
}
|
||||
|
||||
let mut y = 1;
|
||||
for t in editor_types.iter() {
|
||||
show_edit_tree(&ctx, &mut comp, &rt_int.descend(t.clone()).expect(""), y);
|
||||
y += 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* write the changes in the view of `term_port` to the terminal
|
||||
*/
|
||||
app.show().await.expect("output error!");
|
||||
}
|
||||
|
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.
|
449
examples/tty-06-lines/src/main.rs
Normal file
449
examples/tty-06-lines/src/main.rs
Normal file
|
@ -0,0 +1,449 @@
|
|||
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 LineEditor {
|
||||
num_buf: SingletonBuffer< u64 >,
|
||||
diag_buf: VecBuffer< LineDiagnostic >,
|
||||
chars_edit: Arc<RwLock<ListEditor>>,
|
||||
out_port: ViewPort< dyn TerminalView >,
|
||||
view: Arc<RwLock< LineView >>,
|
||||
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
|
||||
}
|
||||
|
||||
struct LineView {
|
||||
line_num: Arc< dyn SingletonView<Item = u64> >,
|
||||
segments: Arc< dyn SequenceView<Item = 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,
|
||||
) -> Arc<RwLock<Self>> {
|
||||
let num_buf = SingletonBuffer::new(n);
|
||||
let diag_buf = VecBuffer::new();
|
||||
let chars_edit = ListEditor::new(
|
||||
ctx.clone(),
|
||||
Context::parse(&ctx, "<List Char>")
|
||||
);
|
||||
let chars_seg_seq = ListSegmentSequence::new(chars_edit.get_cursor_port(), chars_edit.get_data_port())
|
||||
.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(0, 0))
|
||||
));
|
||||
}),
|
||||
segments: proj_helper.new_sequence_arg(1, chars_seg_seq,
|
||||
|e: &mut LineEditor, idx| {
|
||||
e.cast.write().unwrap()
|
||||
.notify(&IndexArea::Range(
|
||||
(Point2::new(*idx as i16, 0) ..= Point2::new(*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,
|
||||
}));
|
||||
|
||||
let line_edit = Arc::new(RwLock::new(LineEditor {
|
||||
num_buf,
|
||||
diag_buf,
|
||||
chars_edit: Arc::new(RwLock::new(chars_edit)),
|
||||
cast: out_port.inner().get_broadcast(),
|
||||
view: line_view.clone(),
|
||||
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: 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");
|
||||
/*
|
||||
rt.insert_branch(
|
||||
Context::parse(&ctx, "EditTree"),
|
||||
|
||||
)*/
|
||||
}
|
||||
);
|
||||
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 depth = SingletonBuffer::new(0).get_port();
|
||||
|
||||
let chars_rt = self.make_line(line_value);
|
||||
let chars_edittree = chars_rt
|
||||
.descend(Context::parse(&self.ctx, "EditTree")).unwrap()
|
||||
.edittree(&self.ctx).get()
|
||||
.read().unwrap().clone();
|
||||
|
||||
let line = LineEditor::new(&self.ctx, n);
|
||||
line.write().unwrap().chars_edit = chars_edittree.get_edit::<ListEditor>().unwrap();
|
||||
let line_port = line.read().unwrap().get_port();
|
||||
|
||||
let mut line_edittree = EditTree::new(self.ctx.clone(), depth)
|
||||
.set_nav( line.read().unwrap().chars_edit.clone() )
|
||||
.set_cmd( line.read().unwrap().chars_edit.clone() )
|
||||
.set_editor( line.clone() );
|
||||
|
||||
line_edittree.disp.view
|
||||
.insert_leaf(
|
||||
Context::parse(&self.ctx, "TerminalView"),
|
||||
ReprLeaf::from_view( line_port )
|
||||
);
|
||||
|
||||
self.edit.write().unwrap()
|
||||
.get_edit::< ListEditor >().unwrap()
|
||||
.write().unwrap()
|
||||
.data
|
||||
.push( Arc::new(RwLock::new(line_edittree)) );
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
// create Editor & transfer data to Editor
|
||||
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!");
|
||||
}
|
19
examples/tty-07-color/Cargo.toml
Normal file
19
examples/tty-07-color/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "tty-06-color"
|
||||
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"]
|
||||
|
232
examples/tty-07-color/src/main.rs
Normal file
232
examples/tty-07-color/src/main.rs
Normal file
|
@ -0,0 +1,232 @@
|
|||
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},
|
||||
};
|
||||
|
||||
#[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);
|
||||
|
||||
eprintln!(
|
||||
"Char = {:?}\nu64 = {:?}\nEditTree = {:?}, <Vec EditTree> = {:?}",
|
||||
Context::parse(&ctx, "Char"),
|
||||
Context::parse(&ctx, "machine.UInt64"),
|
||||
Context::parse(&ctx, "EditTree"),
|
||||
Context::parse(&ctx, "<Vec EditTree>")
|
||||
);
|
||||
|
||||
let mut red = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, "
|
||||
ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ <Vec Char>
|
||||
"),
|
||||
"221"
|
||||
);
|
||||
ctx.read().unwrap().apply_morphism( &red,
|
||||
&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, "
|
||||
ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ <Vec Char>
|
||||
"),
|
||||
"220"
|
||||
);
|
||||
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 blue = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, "
|
||||
ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ <Vec Char>
|
||||
"),
|
||||
"5"
|
||||
);
|
||||
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();
|
||||
|
||||
|
||||
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(
|
||||
Context::parse(&ctx, "<List ℕ>")
|
||||
);
|
||||
|
||||
color.insert_leaf(
|
||||
Context::parse(&ctx, "
|
||||
<List ℕ
|
||||
~ <PosInt 16 BigEndian>
|
||||
~ <Seq <Digit 16>>
|
||||
~ <List <Digit 16>
|
||||
~ Char >
|
||||
>
|
||||
~ <List EditTree>
|
||||
~ <Vec EditTree>
|
||||
"),
|
||||
|
||||
ReprLeaf::from_vec_buffer(VecBuffer::<
|
||||
Arc<RwLock< EditTree >>
|
||||
>::with_data(vec![
|
||||
red_edit.get(),
|
||||
green_edit.get(),
|
||||
blue_edit.get()
|
||||
]))
|
||||
);
|
||||
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;
|
||||
|
||||
/* setup terminal
|
||||
*/
|
||||
let app = TTYApplication::new({
|
||||
/* event handler
|
||||
*/
|
||||
let ctx = ctx.clone();
|
||||
let edit = edit.get().clone();
|
||||
|
||||
edit.write().unwrap().goto(TreeCursor::home());
|
||||
|
||||
move |ev| {
|
||||
edit.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, &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 );
|
||||
}
|
||||
|
||||
/* write the changes in the view of `term_port` to the terminal
|
||||
*/
|
||||
app.show().await.expect("output error!");
|
||||
}
|
||||
|
11
lib-nested-core/Cargo.toml
Normal file
11
lib-nested-core/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
authors = ["Michael Sippel <micha@fragmental.art>"]
|
||||
edition = "2018"
|
||||
name = "nested"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
r3vi = { path = "../../lib-r3vi" }
|
||||
laddertypes = { path = "../../lib-laddertypes" }
|
||||
cgmath = { version = "0.18.0", features = ["serde"] }
|
||||
|
24
lib-nested-core/src/edit_tree/diagnostics.rs
Normal file
24
lib-nested-core/src/edit_tree/diagnostics.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{OuterViewPort, sequence::*},
|
||||
buffer::{vec::*, index_hashmap::*}
|
||||
},
|
||||
crate::{
|
||||
repr_tree::ReprTree
|
||||
},
|
||||
std::sync::{Arc, RwLock},
|
||||
cgmath::Point2
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Message {
|
||||
pub addr: Vec<usize>,
|
||||
pub disp: Arc<RwLock<ReprTree>>
|
||||
}
|
||||
|
||||
pub trait Diagnostics {
|
||||
fn get_msg_port(&self) -> OuterViewPort<dyn SequenceView<Item = Message>> {
|
||||
VecBuffer::new().get_port().to_sequence()
|
||||
}
|
||||
}
|
||||
|
|
@ -3,12 +3,13 @@ pub mod cursor;
|
|||
pub mod nav;
|
||||
pub mod node;
|
||||
pub mod treetype;
|
||||
pub mod diagnostics;
|
||||
|
||||
pub use {
|
||||
addr::TreeAddr,
|
||||
cursor::TreeCursor,
|
||||
nav::{TreeNav, TreeNavResult, TreeHeightOp},
|
||||
treetype::{TreeType},
|
||||
node::NestedNode
|
||||
node::EditTree
|
||||
};
|
||||
|
|
@ -15,8 +15,7 @@ use {
|
|||
},
|
||||
crate::{
|
||||
editors::list::ListCursorMode,
|
||||
tree::TreeCursor,
|
||||
terminal::{TerminalView, TerminalProjections, make_label}
|
||||
edit_tree::TreeCursor
|
||||
},
|
||||
cgmath::Vector2,
|
||||
};
|
||||
|
@ -27,9 +26,19 @@ pub enum TreeNavResult { Continue, Exit }
|
|||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||
pub enum TreeHeightOp { P, Q, Max }
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum TreeNavCmd {
|
||||
pxev, nexd, up, dn,
|
||||
qpxev, qnexd, dup, qdn,
|
||||
|
||||
dn_pxev,
|
||||
up_nexd,
|
||||
pxev_dn_qnexd
|
||||
}
|
||||
|
||||
pub trait TreeNav {
|
||||
/* CORE
|
||||
*/
|
||||
*/
|
||||
fn get_cursor(&self) -> TreeCursor {
|
||||
TreeCursor::default()
|
||||
}
|
||||
|
@ -150,35 +159,6 @@ pub trait TreeNav {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_cursor_widget(&self) -> OuterViewPort<dyn TerminalView> {
|
||||
VecBuffer::with_data(
|
||||
vec![
|
||||
make_label("@").with_fg_color((150, 80,230)),
|
||||
self.get_addr_view()
|
||||
.map(|i|
|
||||
make_label(&format!("{}", i)).with_fg_color((0, 100, 20)))
|
||||
.separate(make_label(".").with_fg_color((150, 80,230)))
|
||||
.to_grid_horizontal()
|
||||
.flatten(),
|
||||
make_label(":").with_fg_color((150, 80,230)),
|
||||
self.get_mode_view()
|
||||
.map(|mode| {
|
||||
make_label(
|
||||
match mode {
|
||||
ListCursorMode::Insert => "INSERT",
|
||||
ListCursorMode::Select => "SELECT"
|
||||
})
|
||||
.with_fg_color((200, 200, 20))
|
||||
})
|
||||
.to_grid()
|
||||
.flatten(),
|
||||
make_label(":").with_fg_color((150, 80,230))
|
||||
]
|
||||
).get_port()
|
||||
.to_sequence()
|
||||
.to_grid_horizontal()
|
||||
.flatten()
|
||||
}
|
||||
}
|
||||
|
||||
|
225
lib-nested-core/src/edit_tree/node.rs
Normal file
225
lib-nested-core/src/edit_tree/node.rs
Normal file
|
@ -0,0 +1,225 @@
|
|||
use {
|
||||
std::{sync::{Arc, RwLock}, any::Any},
|
||||
cgmath::{Vector2, Point2},
|
||||
r3vi::{
|
||||
view::{View, ViewPort, OuterViewPort, AnyOuterViewPort, singleton::*, sequence::*},
|
||||
buffer::{singleton::*, vec::*}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
repr_tree::{ReprTree, ReprTreeArc, Context},
|
||||
edit_tree::{TreeNav, TreeCursor, TreeNavResult, TreeHeightOp, diagnostics::{Diagnostics, Message}},
|
||||
editors::{list::{ListCursorMode}, ObjCommander}
|
||||
}
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EdittreeDisplay {
|
||||
/// display view
|
||||
pub view: Arc<RwLock<ReprTree>>,
|
||||
|
||||
/// diagnostics
|
||||
pub diag: Option< OuterViewPort<dyn SequenceView<Item = Message>> >,
|
||||
|
||||
/// depth
|
||||
pub depth: OuterViewPort<dyn SingletonView<Item = usize>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EdittreeControl {
|
||||
/// abstract editor
|
||||
pub editor: SingletonBuffer<
|
||||
Option< Arc<dyn Any + Send + Sync> >
|
||||
>,
|
||||
|
||||
pub spillbuf: Arc<RwLock< Vec< ReprTreeArc > >>,
|
||||
|
||||
/// commander & navigation
|
||||
pub cmd: SingletonBuffer<
|
||||
Option< Arc<RwLock<dyn ObjCommander + Send + Sync>> >
|
||||
>, /// abstract data view
|
||||
|
||||
pub close_char: SingletonBuffer< Option< char > >,
|
||||
|
||||
// could be replaced by cmd when TreeNav -CmdObjects are used
|
||||
pub tree_nav: SingletonBuffer<
|
||||
Option< Arc<RwLock<dyn TreeNav + Send + Sync>> >
|
||||
>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EditTree {
|
||||
/// context
|
||||
pub ctx: Arc<RwLock<Context>>,
|
||||
|
||||
/// viewports for terminal display
|
||||
pub disp: EdittreeDisplay,
|
||||
|
||||
/// editor & commander objects
|
||||
pub ctrl: EdittreeControl
|
||||
}
|
||||
|
||||
impl EditTree {
|
||||
pub fn new(ctx: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> Self {
|
||||
EditTree {
|
||||
disp: EdittreeDisplay {
|
||||
view: ReprTree::new_arc(Context::parse(&ctx, "Display")),
|
||||
diag: None,
|
||||
depth,
|
||||
},
|
||||
ctrl: EdittreeControl {
|
||||
editor: SingletonBuffer::new(None),
|
||||
spillbuf: Arc::new(RwLock::new(Vec::new())),
|
||||
cmd: SingletonBuffer::new(None),
|
||||
close_char: SingletonBuffer::new(None),
|
||||
tree_nav: SingletonBuffer::new(None),
|
||||
},
|
||||
ctx
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_editor(mut self, editor: Arc<dyn Any + Send + Sync>) -> Self {
|
||||
self.ctrl.editor.set(Some(editor));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_cmd(mut self, cmd: Arc<RwLock<dyn ObjCommander + Send + Sync>>) -> Self {
|
||||
self.ctrl.cmd.set(Some(cmd));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_nav(mut self, nav: Arc<RwLock<dyn TreeNav + Send + Sync>>) -> Self {
|
||||
self.ctrl.tree_nav.set(Some(nav));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_diag(mut self, diag: OuterViewPort<dyn SequenceView<Item = Message>>) -> Self {
|
||||
self.disp.diag = Some(diag);
|
||||
self
|
||||
}
|
||||
|
||||
//\\//\\
|
||||
|
||||
pub fn get_diag(&self) -> OuterViewPort<dyn SequenceView<Item = Message>> {
|
||||
self.disp.diag.clone().unwrap_or(ViewPort::new().into_outer())
|
||||
}
|
||||
|
||||
pub fn get_edit<T: Send + Sync + 'static>(&self) -> Option<Arc<RwLock<T>>> {
|
||||
if let Some(edit) = self.ctrl.editor.get() {
|
||||
if let Ok(edit) = edit.downcast::<RwLock<T>>() {
|
||||
Some(edit)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl TreeType for NestedNode {
|
||||
fn get_type(&self, addr: &TreeAddr) -> TypeLadder {
|
||||
if let Some(editor) = self.editor {
|
||||
editor.read().unwrap().get_type(addr)
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
impl TreeNav for EditTree {
|
||||
fn get_cursor(&self) -> TreeCursor {
|
||||
if let Some(tn) = self.ctrl.tree_nav.get() {
|
||||
tn.read().unwrap().get_cursor()
|
||||
} else {
|
||||
TreeCursor::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_addr_view(&self) -> OuterViewPort<dyn SequenceView<Item = isize>> {
|
||||
if let Some(tn) = self.ctrl.tree_nav.get() {
|
||||
tn.read().unwrap().get_addr_view()
|
||||
} else {
|
||||
OuterViewPort::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mode_view(&self) -> OuterViewPort<dyn SingletonView<Item = ListCursorMode>> {
|
||||
if let Some(tn) = self.ctrl.tree_nav.get() {
|
||||
tn.read().unwrap().get_mode_view()
|
||||
} else {
|
||||
OuterViewPort::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_cursor_warp(&self) -> TreeCursor {
|
||||
if let Some(tn) = self.ctrl.tree_nav.get() {
|
||||
tn.read().unwrap().get_cursor_warp()
|
||||
} else {
|
||||
TreeCursor::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_height(&self, op: &TreeHeightOp) -> usize {
|
||||
if let Some(tn) = self.ctrl.tree_nav.get() {
|
||||
tn.read().unwrap().get_height( op )
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn goby(&mut self, direction: Vector2<isize>) -> TreeNavResult {
|
||||
if let Some(tn) = self.ctrl.tree_nav.get() {
|
||||
tn.write().unwrap().goby(direction)
|
||||
} else {
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
|
||||
fn goto(&mut self, new_cursor: TreeCursor) -> TreeNavResult {
|
||||
if let Some(tn) = self.ctrl.tree_nav.get() {
|
||||
tn.write().unwrap().goto(new_cursor)
|
||||
} else {
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use crate::edit_tree::nav::TreeNavCmd;
|
||||
|
||||
impl ObjCommander for EditTree {
|
||||
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
|
||||
|
||||
if cmd_obj.read().unwrap().get_type() == &Context::parse(&self.ctx, "TreeNavCmd") {
|
||||
if let Some(cmd) = cmd_obj.read().unwrap().get_view::<dyn SingletonView<Item = TreeNavCmd>>() {
|
||||
match cmd.get() {
|
||||
TreeNavCmd::pxev => self.pxev(),
|
||||
TreeNavCmd::nexd => self.nexd(),
|
||||
TreeNavCmd::qpxev => self.qpxev(),
|
||||
TreeNavCmd::qnexd => self.qnexd(),
|
||||
|
||||
TreeNavCmd::up => self.up(),
|
||||
TreeNavCmd::dn => self.dn(),
|
||||
|
||||
_ => TreeNavResult::Continue
|
||||
}
|
||||
} else {
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
} else if let Some(cmd) = self.ctrl.cmd.get() {
|
||||
// todo: filter out tree-nav cmds and send them to tree_nav
|
||||
cmd.write().unwrap().send_cmd_obj(cmd_obj)
|
||||
} else {
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Diagnostics for EditTree {
|
||||
fn get_msg_port(&self) -> OuterViewPort<dyn SequenceView<Item = Message>> {
|
||||
self.get_diag()
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
use {
|
||||
laddertypes::{TypeTerm, TypeID},
|
||||
crate::{
|
||||
tree::{TreeAddr}
|
||||
edit_tree::{TreeAddr}
|
||||
}
|
||||
};
|
||||
|
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 );
|
||||
}
|
|
@ -3,27 +3,22 @@ use {
|
|||
view::{
|
||||
OuterViewPort,
|
||||
singleton::*,
|
||||
port::UpdateTask
|
||||
},
|
||||
buffer::singleton::*
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context, ReprTree},
|
||||
terminal::{TerminalAtom},
|
||||
tree::{NestedNode, TreeNavResult},
|
||||
commander::{ObjCommander}
|
||||
repr_tree::{Context, ReprTree, ReprLeaf, ReprTreeExt, GenericReprTreeMorphism},
|
||||
edit_tree::{EditTree, TreeNavResult},
|
||||
editors::ObjCommander,
|
||||
},
|
||||
std::sync::Arc,
|
||||
std::sync::RwLock
|
||||
};
|
||||
|
||||
pub fn init_ctx( ctx: &mut Context ) {
|
||||
ctx.add_node_ctor(
|
||||
"Char",
|
||||
Arc::new(|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
|
||||
Some(CharEditor::new_node(ctx, depth))
|
||||
}));
|
||||
}
|
||||
pub mod ctx;
|
||||
pub use crate::editors::char::ctx::init_ctx;
|
||||
|
||||
pub struct CharEditor {
|
||||
ctx: Arc<RwLock<Context>>,
|
||||
|
@ -70,33 +65,20 @@ impl CharEditor {
|
|||
self.get_port().get_view().unwrap().get()
|
||||
}
|
||||
|
||||
pub fn new_node(ctx0: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode {
|
||||
let data = SingletonBuffer::new('\0');
|
||||
pub fn new_edit_tree(
|
||||
ctx0: Arc<RwLock<Context>>,
|
||||
data: SingletonBuffer<char>,
|
||||
depth: OuterViewPort<dyn SingletonView<Item = usize>>
|
||||
) -> EditTree {
|
||||
//let data = SingletonBuffer::new('\0');
|
||||
let ctx = ctx0.clone();
|
||||
let editor = Arc::new(RwLock::new(CharEditor{ ctx, data: data.clone() }));
|
||||
|
||||
NestedNode::new(
|
||||
EditTree::new(
|
||||
ctx0.clone(),
|
||||
ReprTree::new_leaf(
|
||||
ctx0.read().unwrap().type_term_from_str("Char").unwrap(),
|
||||
data.get_port().into()
|
||||
),
|
||||
depth
|
||||
)
|
||||
.set_view(data
|
||||
.get_port()
|
||||
.map(move |c| TerminalAtom::from(if c == '\0' { ' ' } else { c }))
|
||||
.to_grid()
|
||||
)
|
||||
.set_cmd( editor.clone() )
|
||||
.set_editor( editor.clone() )
|
||||
}
|
||||
}
|
||||
/*
|
||||
use crate::StringGen;
|
||||
impl StringGen for CharEditor {
|
||||
fn get_string(&self) -> String {
|
||||
String::from(self.get())
|
||||
}
|
||||
}
|
||||
*/
|
52
lib-nested-core/src/editors/digit/cmd.rs
Normal file
52
lib-nested-core/src/editors/digit/cmd.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
|
||||
use {
|
||||
r3vi::view::singleton::SingletonView,
|
||||
crate::{
|
||||
repr_tree::{ReprTree, Context},
|
||||
edit_tree::{TreeNav, TreeNavResult},
|
||||
editors::{ObjCommander, digit::DigitEditor}
|
||||
},
|
||||
|
||||
std::sync::{Arc, RwLock}
|
||||
};
|
||||
|
||||
impl ObjCommander for DigitEditor {
|
||||
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
|
||||
let cmd_obj = cmd_obj.read().unwrap();
|
||||
let cmd_type = cmd_obj.get_type().clone();
|
||||
|
||||
if cmd_type == Context::parse(&self.ctx, "Char") {
|
||||
if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
|
||||
let c = cmd_view.get();
|
||||
|
||||
self.msg.clear();
|
||||
|
||||
if self.ctx.read().unwrap().meta_chars.contains(&c) {
|
||||
return TreeNavResult::Exit;
|
||||
|
||||
} else if c.to_digit(self.radix).is_none() {
|
||||
/* in case the character c is not in the range of digit-chars,
|
||||
add a message to the diagnostics view
|
||||
*/
|
||||
/*
|
||||
let message = IndexBuffer::from_iter(vec![
|
||||
(Point2::new(1, 0), make_label("invalid digit '")),
|
||||
(Point2::new(2, 0), make_label(&format!("{}", c))
|
||||
.map_item(|_p,a| a.add_style_back(TerminalStyle::fg_color((140,140,250))))),
|
||||
(Point2::new(3, 0), make_label("'"))
|
||||
]);
|
||||
|
||||
self.msg.push(crate::diagnostics::make_error(message.get_port().flatten()));
|
||||
*/
|
||||
|
||||
self.data.set(c);
|
||||
} else {
|
||||
self.data.set(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
}
|
||||
|
205
lib-nested-core/src/editors/digit/ctx.rs
Normal file
205
lib-nested-core/src/editors/digit/ctx.rs
Normal file
|
@ -0,0 +1,205 @@
|
|||
|
||||
use {
|
||||
laddertypes::TypeTerm,
|
||||
r3vi::{
|
||||
buffer::singleton::SingletonBuffer,
|
||||
view::{
|
||||
AnyOuterViewPort,
|
||||
singleton::*
|
||||
}
|
||||
},
|
||||
crate::{
|
||||
repr_tree::{Context, ReprTree, ReprTreeExt, ReprLeaf, GenericReprTreeMorphism},
|
||||
editors::digit::DigitEditor,
|
||||
},
|
||||
std::sync::{Arc, RwLock}
|
||||
};
|
||||
|
||||
pub fn init_ctx( ctx: Arc<RwLock<Context>> ) {
|
||||
// todo: proper scoping of Radix variable
|
||||
ctx.write().unwrap().add_varname("Radix");
|
||||
|
||||
let digit_make_edittree = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "<Digit Radix>"),
|
||||
Context::parse(&ctx, "<Digit Radix>~EditTree"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
let radix =
|
||||
match σ.get( &laddertypes::TypeID::Var(ctx.read().unwrap().get_var_typeid("Radix").unwrap()) ) {
|
||||
Some(TypeTerm::Num(n)) => *n as u32,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
let char_buf = SingletonBuffer::<char>::new('?');
|
||||
|
||||
/* Create EditTree object
|
||||
*/
|
||||
let mut edittree = DigitEditor::new(
|
||||
ctx.clone(),
|
||||
radix,
|
||||
char_buf
|
||||
).into_node(
|
||||
r3vi::buffer::singleton::SingletonBuffer::<usize>::new(0).get_port()
|
||||
);
|
||||
|
||||
src_rt.write().unwrap()
|
||||
.insert_branch(
|
||||
ReprTree::from_singleton_buffer(
|
||||
Context::parse(&ctx, "EditTree"),
|
||||
SingletonBuffer::new(Arc::new(RwLock::new(edittree)))
|
||||
)
|
||||
);
|
||||
|
||||
ctx.read().unwrap().setup_edittree( src_rt );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let digit_morph_char_to_edittree = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "<Digit Radix>~Char"),
|
||||
Context::parse(&ctx, "<Digit Radix>~EditTree"),
|
||||
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
let radix =
|
||||
match σ.get( &laddertypes::TypeID::Var(ctx.read().unwrap().get_var_typeid("Radix").unwrap()) ) {
|
||||
Some(TypeTerm::Num(n)) => *n as u32,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
/* Create EditTree object
|
||||
*/
|
||||
let mut edittree = DigitEditor::new(
|
||||
ctx.clone(),
|
||||
radix,
|
||||
src_rt
|
||||
.descend( Context::parse(&ctx, "Char") ).unwrap()
|
||||
.singleton_buffer::<char>()
|
||||
).into_node(
|
||||
r3vi::buffer::singleton::SingletonBuffer::<usize>::new(0).get_port()
|
||||
);
|
||||
|
||||
src_rt.write().unwrap()
|
||||
.insert_branch(
|
||||
ReprTree::from_singleton_buffer(
|
||||
Context::parse(&ctx, "EditTree"),
|
||||
SingletonBuffer::new(Arc::new(RwLock::new(edittree)))
|
||||
)
|
||||
);
|
||||
|
||||
ctx.read().unwrap().setup_edittree( src_rt );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let digit_morph_char_from_edittree = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "<Digit Radix>~EditTree"),
|
||||
Context::parse(&ctx, "<Digit Radix>~Char"),
|
||||
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
let edittree = src_rt.edittree( &ctx );
|
||||
let port =
|
||||
edittree
|
||||
.get()
|
||||
.read().unwrap()
|
||||
.get_edit::<DigitEditor>().unwrap()
|
||||
.read().unwrap()
|
||||
.get_char_port();
|
||||
|
||||
src_rt.insert_leaf(
|
||||
Context::parse(&ctx, "Char"),
|
||||
ReprLeaf::from_view( port )
|
||||
)
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let digit_morph_char_to_u64 = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "<Digit Radix>~Char"),
|
||||
Context::parse(&ctx, "<Digit Radix>~ℤ_2^64~machine.UInt64"),
|
||||
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |rt: &mut Arc<RwLock<ReprTree>>, σ: &std::collections::HashMap<laddertypes::TypeID, TypeTerm>| {
|
||||
/* infer radix from type
|
||||
*/
|
||||
let radix_typeid = ctx.read().unwrap().get_var_typeid("Radix").unwrap();
|
||||
let radix =
|
||||
match σ.get( &laddertypes::TypeID::Var(radix_typeid) ) {
|
||||
Some(TypeTerm::Num(n)) => (*n) as u32,
|
||||
x => {
|
||||
eprintln!("invalid radix {:?}", x);
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
if radix <= 16 {
|
||||
if let Some(src_rt) = rt.descend(Context::parse(&ctx, "Char")) {
|
||||
/* insert projected view into ReprTree
|
||||
*/
|
||||
let u64_view =
|
||||
src_rt.view_char()
|
||||
.map(move |c| c.to_digit(radix).unwrap_or(0) as u64);
|
||||
|
||||
rt.write().unwrap().attach_leaf_to::<dyn SingletonView<Item = u64>>(
|
||||
Context::parse(&ctx, "ℤ_2^64~machine.UInt64").get_lnf_vec().into_iter(),
|
||||
u64_view
|
||||
);
|
||||
} else {
|
||||
eprintln!("could not find required source representation: <Digit {}>~Char", radix);
|
||||
}
|
||||
} else {
|
||||
eprintln!("radix too large ({})", radix);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
let digit_morph_u64_to_char = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "<Digit Radix>~ℤ_2^64~machine.UInt64"),
|
||||
Context::parse(&ctx, "<Digit Radix>~Char"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |rt: &mut Arc<RwLock<ReprTree>>, σ: &std::collections::HashMap<laddertypes::TypeID, TypeTerm>| {
|
||||
/* infer radix from type
|
||||
*/
|
||||
let radix =
|
||||
match σ.get( &laddertypes::TypeID::Var(ctx.read().unwrap().get_var_typeid("Radix").unwrap()) ) {
|
||||
Some(TypeTerm::Num(n)) => (*n) as u32,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
if radix <= 16 {
|
||||
/* insert projected view into ReprTree
|
||||
*/
|
||||
let char_view =
|
||||
rt.descend(Context::parse(&ctx, "ℤ_2^64~machine.UInt64"))
|
||||
.unwrap()
|
||||
.view_u64()
|
||||
.map(move |digit| char::from_digit((digit%radix as u64) as u32, radix).unwrap_or('?'));
|
||||
|
||||
rt.write().unwrap().attach_leaf_to::<dyn SingletonView<Item = char>>(
|
||||
Context::parse(&ctx, "Char").get_lnf_vec().into_iter(),
|
||||
char_view
|
||||
);
|
||||
} else {
|
||||
eprintln!("radix too large ({})", radix);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
ctx.write().unwrap().morphisms.add_morphism( digit_make_edittree );
|
||||
ctx.write().unwrap().morphisms.add_morphism( digit_morph_char_to_edittree );
|
||||
ctx.write().unwrap().morphisms.add_morphism( digit_morph_char_from_edittree );
|
||||
ctx.write().unwrap().morphisms.add_morphism( digit_morph_char_to_u64 );
|
||||
ctx.write().unwrap().morphisms.add_morphism( digit_morph_u64_to_char );
|
||||
}
|
||||
|
||||
|
98
lib-nested-core/src/editors/digit/editor.rs
Normal file
98
lib-nested-core/src/editors/digit/editor.rs
Normal file
|
@ -0,0 +1,98 @@
|
|||
|
||||
use {
|
||||
laddertypes::TypeTerm,
|
||||
r3vi::{
|
||||
view::{OuterViewPort,singleton::*},
|
||||
buffer::{singleton::*, vec::*}
|
||||
},
|
||||
crate::{
|
||||
repr_tree::{ReprTree, Context},
|
||||
edit_tree::{
|
||||
EditTree,
|
||||
diagnostics::Message
|
||||
}
|
||||
},
|
||||
|
||||
std::sync::{Arc, RwLock}
|
||||
};
|
||||
|
||||
|
||||
pub struct DigitEditor {
|
||||
pub(super) ctx: Arc<RwLock<Context>>,
|
||||
pub(super) radix: u32,
|
||||
pub(super) data: SingletonBuffer<char>,
|
||||
pub(super) msg: VecBuffer<Message>,
|
||||
}
|
||||
|
||||
|
||||
impl DigitEditor {
|
||||
pub fn new(ctx: Arc<RwLock<Context>>, radix: u32, data: SingletonBuffer<char>) -> Self {
|
||||
DigitEditor {
|
||||
ctx,
|
||||
radix,
|
||||
data,
|
||||
msg: VecBuffer::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_node(self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> EditTree {
|
||||
// let data = self.get_data();
|
||||
let editor = Arc::new(RwLock::new(self));
|
||||
let ed = editor.write().unwrap();
|
||||
let r = ed.radix;
|
||||
|
||||
EditTree::new(ed.ctx.clone(), depth)
|
||||
.set_editor(editor.clone())
|
||||
.set_cmd(editor.clone())
|
||||
.set_diag(
|
||||
ed.msg.get_port().to_sequence()
|
||||
)
|
||||
}
|
||||
|
||||
pub fn attach_to(&mut self, source: OuterViewPort<dyn SingletonView<Item = u32>>) {
|
||||
/*
|
||||
source.add_observer(
|
||||
Arc::new(NotifyFnObserver::new(|_msg| {
|
||||
self.data.set( source.get() )
|
||||
}))
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
pub fn get_char_port(&self) -> OuterViewPort<dyn SingletonView<Item = char>> {
|
||||
self.data.get_port()
|
||||
}
|
||||
|
||||
pub fn get_data_port(&self) -> OuterViewPort<dyn SingletonView<Item = Result<u32, char>>> {
|
||||
let radix = self.radix;
|
||||
self.data.get_port().map(move |c|
|
||||
if let Some(d) = c.to_digit(radix) {
|
||||
Ok(d)
|
||||
} else {
|
||||
Err(c)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_type(&self) -> TypeTerm {
|
||||
TypeTerm::TypeID(self.ctx.read().unwrap().get_typeid("Digit").unwrap())
|
||||
}
|
||||
|
||||
pub fn get_char(&self) -> char {
|
||||
self.data.get()
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
|
||||
ReprTree::ascend(
|
||||
&ReprTree::from_view(
|
||||
self.ctx.read().unwrap().type_term_from_str("<Seq u32>").unwrap(),
|
||||
self.get_data_port()
|
||||
),
|
||||
self.get_type()
|
||||
)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
8
lib-nested-core/src/editors/digit/mod.rs
Normal file
8
lib-nested-core/src/editors/digit/mod.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
pub mod ctx;
|
||||
pub mod cmd;
|
||||
pub mod editor;
|
||||
|
||||
pub use editor::DigitEditor;
|
||||
pub use ctx::init_ctx;
|
||||
|
302
lib-nested-core/src/editors/integer/ctx.rs
Normal file
302
lib-nested-core/src/editors/integer/ctx.rs
Normal file
|
@ -0,0 +1,302 @@
|
|||
|
||||
use {
|
||||
r3vi::{
|
||||
view::{OuterViewPort, singleton::*, list::*},
|
||||
buffer::singleton::SingletonBuffer
|
||||
},
|
||||
laddertypes::{TypeTerm, MorphismType},
|
||||
crate::{
|
||||
repr_tree::{ReprTree, ReprTreeExt, ReprLeaf, Context, GenericReprTreeMorphism},
|
||||
editors::{
|
||||
list::*,
|
||||
integer::*
|
||||
},
|
||||
},
|
||||
std::sync::{Arc, RwLock}
|
||||
};
|
||||
|
||||
pub fn init_ctx(ctx: Arc<RwLock<Context>>) {
|
||||
// TODO: proper scoping
|
||||
ctx.write().unwrap().add_varname("SrcRadix");
|
||||
ctx.write().unwrap().add_varname("DstRadix");
|
||||
|
||||
|
||||
let posint_seq_morph_big_to_little = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt Radix BigEndian>
|
||||
~ <Seq <Digit Radix> ~ ℤ_2^64 ~ machine.UInt64 >"),
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt Radix LittleEndian>
|
||||
~ <Seq <Digit Radix> ~ ℤ_2^64 ~ machine.UInt64 >"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
let src_digits = src_rt
|
||||
.descend(Context::parse(&ctx, "
|
||||
<PosInt Radix BigEndian>
|
||||
~ <Seq <Digit Radix> ~ ℤ_2^64 ~ machine.UInt64 >
|
||||
")
|
||||
.apply_substitution(&|k|σ.get(k).cloned())
|
||||
.clone()
|
||||
).expect("cant descend")
|
||||
.view_seq::< u64 >();
|
||||
|
||||
src_rt.attach_leaf_to(Context::parse(&ctx, "
|
||||
<PosInt Radix LittleEndian>
|
||||
~ <Seq <Digit Radix> ~ ℤ_2^64 ~ machine.UInt64 >
|
||||
").apply_substitution(&|k|σ.get(k).cloned()).clone(),
|
||||
src_digits.reverse()
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let posint_list_morph_big_to_little = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt Radix BigEndian>
|
||||
~ <Seq~List <Digit Radix> ~ ℤ_2^64 ~ machine.UInt64 >"),
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt Radix LittleEndian>
|
||||
~ <Seq~List <Digit Radix> ~ ℤ_2^64 ~ machine.UInt64 >"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
let src_digits = src_rt
|
||||
.descend(Context::parse(&ctx, "
|
||||
<PosInt Radix BigEndian>
|
||||
~ <Seq~List <Digit Radix> ~ ℤ_2^64 ~ machine.UInt64 >
|
||||
")
|
||||
.apply_substitution(&|k|σ.get(k).cloned())
|
||||
.clone()
|
||||
).expect("cant descend")
|
||||
.view_list::< u64 >();
|
||||
|
||||
src_rt.attach_leaf_to(Context::parse(&ctx, "
|
||||
<PosInt Radix LittleEndian>
|
||||
~ <Seq~List <Digit Radix> ~ ℤ_2^64 ~ machine.UInt64 >
|
||||
").apply_substitution(&|k|σ.get(k).cloned()).clone(),
|
||||
src_digits.reverse()
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let posint_list_morph_little_to_big = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt Radix LittleEndian>
|
||||
~ <Seq~List <Digit Radix> ~ ℤ_2^64 ~ machine.UInt64 >"),
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt Radix BigEndian>
|
||||
~ <Seq~List <Digit Radix> ~ ℤ_2^64 ~ machine.UInt64 >"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
let src_digits = src_rt
|
||||
.descend(Context::parse(&ctx, "
|
||||
<PosInt Radix LittleEndian>
|
||||
~ <Seq~List <Digit Radix> ~ ℤ_2^64 ~ machine.UInt64 >
|
||||
")
|
||||
.apply_substitution(&|k|σ.get(k).cloned())
|
||||
.clone()
|
||||
).expect("cant descend")
|
||||
.view_list::< u64 >();
|
||||
|
||||
src_rt.attach_leaf_to(Context::parse(&ctx, "
|
||||
<PosInt Radix BigEndian>
|
||||
~ <Seq~List <Digit Radix> ~ ℤ_2^64 ~ machine.UInt64 >
|
||||
").apply_substitution(&|k|σ.get(k).cloned()).clone(),
|
||||
src_digits.reverse()
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
let posint_list_morph_radix = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "
|
||||
ℕ
|
||||
~ <PosInt SrcRadix LittleEndian>
|
||||
~ <Seq <Digit SrcRadix>>
|
||||
~ <List <Digit SrcRadix>
|
||||
~ ℤ_2^64
|
||||
~ machine.UInt64>
|
||||
"),
|
||||
Context::parse(&ctx, "
|
||||
ℕ
|
||||
~ <PosInt DstRadix LittleEndian>
|
||||
~ <Seq <Digit DstRadix>>
|
||||
~ <List <Digit DstRadix>
|
||||
~ ℤ_2^64
|
||||
~ machine.UInt64>
|
||||
"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
let src_radix = match σ.get(&laddertypes::TypeID::Var(
|
||||
ctx.read().unwrap().get_var_typeid("SrcRadix").unwrap()
|
||||
)) {
|
||||
Some(laddertypes::TypeTerm::Num(n)) => *n as u64,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
let dst_radix = match σ.get(&laddertypes::TypeID::Var(
|
||||
ctx.read().unwrap().get_var_typeid("DstRadix").unwrap()
|
||||
)) {
|
||||
Some(laddertypes::TypeTerm::Num(n)) => *n as u64,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
let src_digits_rt = src_rt.descend(Context::parse(&ctx, "
|
||||
<PosInt SrcRadix LittleEndian>
|
||||
~ <Seq <Digit SrcRadix>>
|
||||
~ <List <Digit SrcRadix>
|
||||
~ ℤ_2^64
|
||||
~ machine.UInt64 >
|
||||
").apply_substitution(&|k|σ.get(k).cloned()).clone()
|
||||
).expect("cant descend repr tree");
|
||||
|
||||
let dst_digits_port =
|
||||
src_digits_rt.view_list::<u64>()
|
||||
.to_sequence()
|
||||
.to_positional_uint( src_radix )
|
||||
.transform_radix( dst_radix )
|
||||
.to_list();
|
||||
|
||||
src_rt.attach_leaf_to(
|
||||
Context::parse(&ctx, "
|
||||
<PosInt DstRadix LittleEndian>
|
||||
~ <Seq <Digit DstRadix> >
|
||||
~ <List <Digit DstRadix>
|
||||
~ ℤ_2^64
|
||||
~ machine.UInt64 >
|
||||
").apply_substitution(&|k|σ.get(k).cloned()).clone(),
|
||||
dst_digits_port
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
let posint_list_morph_from_u64 = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "ℕ ~ machine.UInt64"),
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt 0 LittleEndian> ~ <Seq~List <Digit 0>~ℤ_2^64~machine.UInt64>"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |rt, σ| {
|
||||
let digits = rt
|
||||
.descend(Context::parse(&ctx, "ℕ ~ machine.UInt64")).unwrap()
|
||||
.view_u64()
|
||||
.to_sequence()
|
||||
.to_list();
|
||||
|
||||
rt.attach_leaf_to(
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt 0 LittleEndian> ~ <Seq~List <Digit 0>~ℤ_2^64~machine.UInt64>"),
|
||||
digits
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
let posint_list_morph_to_u64 = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt 0 LittleEndian> ~ <Seq~List <Digit 0>~ℤ_2^64~machine.UInt64> ~ <Vec machine.UInt64>"),
|
||||
Context::parse(&ctx, "ℕ ~ machine.UInt64"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |rt, σ| {
|
||||
let u64_view = rt
|
||||
.descend(Context::parse(&ctx, "ℕ ~ <PosInt 0 LittleEndian> ~ <Seq~List <Digit 0>~ℤ_2^64~machine.UInt64> ~ <Vec machine.UInt64>")).unwrap()
|
||||
.get_port::< RwLock<Vec< u64 >> >().unwrap()
|
||||
.to_singleton()
|
||||
.map(|digits| {
|
||||
digits.get(0).cloned().unwrap_or(0)
|
||||
});
|
||||
|
||||
rt.attach_leaf_to(
|
||||
Context::parse(&ctx, "ℕ ~ machine.UInt64"),
|
||||
u64_view
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let posint_make_edittree = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt Radix BigEndian> ~ <Seq~List <Digit Radix>> ~ EditTree"),
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt Radix BigEndian> ~ EditTree"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
let mut list_edittree = src_rt.descend(
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt Radix BigEndian> ~ <Seq~List <Digit Radix>>")
|
||||
.apply_substitution(&|x| σ.get(x).cloned()).clone()
|
||||
)
|
||||
.unwrap()
|
||||
.edittree( &ctx )
|
||||
.get().clone()
|
||||
.read().unwrap()
|
||||
.clone();
|
||||
|
||||
// clear display
|
||||
list_edittree.disp.view = ReprTree::new_arc(Context::parse(&ctx, "Display"));
|
||||
|
||||
src_rt.insert_leaf(
|
||||
Context::parse(&ctx, "<PosInt Radix BigEndian> ~ EditTree")
|
||||
.apply_substitution(&|x| σ.get(x).cloned()).clone(),
|
||||
ReprLeaf::from_singleton_buffer(
|
||||
SingletonBuffer::new(
|
||||
Arc::new(RwLock::new(list_edittree))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
ctx.read().unwrap().setup_edittree(
|
||||
&src_rt.descend(
|
||||
Context::parse(&ctx, "<PosInt Radix BigEndian>")
|
||||
.apply_substitution(&|x| σ.get(x).cloned()).clone()
|
||||
).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let posint_edittree_to_list = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt Radix BigEndian> ~ EditTree"),
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt Radix BigEndian> ~ <Seq~List <Digit Radix>> ~ EditTree"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
let mut list_edittree = src_rt.descend(
|
||||
Context::parse(&ctx, "ℕ ~ <PosInt Radix BigEndian>")
|
||||
.apply_substitution(&|x| σ.get(x).cloned()).clone())
|
||||
.unwrap()
|
||||
.edittree( &ctx )
|
||||
.get().clone()
|
||||
.read().unwrap()
|
||||
.clone();
|
||||
|
||||
// clear display
|
||||
list_edittree.disp.view = ReprTree::new_arc(Context::parse(&ctx, "Display"));
|
||||
|
||||
src_rt.insert_leaf(
|
||||
Context::parse(&ctx, "<PosInt Radix BigEndian> ~ <Seq~List <Digit Radix>>~EditTree")
|
||||
.apply_substitution(&|x| σ.get(x).cloned()).clone(),
|
||||
ReprLeaf::from_singleton_buffer(
|
||||
SingletonBuffer::new(
|
||||
Arc::new(RwLock::new(list_edittree))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
ctx.read().unwrap().setup_edittree(
|
||||
&src_rt.descend(
|
||||
Context::parse(&ctx, "<PosInt Radix BigEndian> ~ <Seq~List <Digit Radix>>")
|
||||
.apply_substitution(&|x| σ.get(x).cloned()).clone()
|
||||
).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
ctx.write().unwrap().morphisms.add_morphism( posint_make_edittree );
|
||||
ctx.write().unwrap().morphisms.add_morphism( posint_edittree_to_list );
|
||||
|
||||
ctx.write().unwrap().morphisms.add_morphism( posint_seq_morph_big_to_little );
|
||||
ctx.write().unwrap().morphisms.add_morphism( posint_list_morph_big_to_little );
|
||||
ctx.write().unwrap().morphisms.add_morphism( posint_list_morph_little_to_big );
|
||||
ctx.write().unwrap().morphisms.add_morphism( posint_list_morph_radix );
|
||||
ctx.write().unwrap().morphisms.add_morphism( posint_list_morph_from_u64 );
|
||||
ctx.write().unwrap().morphisms.add_morphism( posint_list_morph_to_u64 );
|
||||
}
|
||||
|
102
lib-nested-core/src/editors/integer/editor.rs
Normal file
102
lib-nested-core/src/editors/integer/editor.rs
Normal file
|
@ -0,0 +1,102 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{
|
||||
OuterViewPort,
|
||||
singleton::*,
|
||||
},
|
||||
buffer::{
|
||||
singleton::*,
|
||||
vec::*,
|
||||
index_hashmap::*
|
||||
}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
editors::{
|
||||
digit::DigitEditor,
|
||||
list::{ListCmd},
|
||||
ObjCommander
|
||||
},
|
||||
repr_tree::{Context, ReprTree},
|
||||
edit_tree::{EditTree, TreeNav, TreeNavResult, TreeCursor, diagnostics::{Message}},
|
||||
},
|
||||
std::sync::Arc,
|
||||
std::sync::RwLock,
|
||||
std::iter::FromIterator,
|
||||
cgmath::{Point2}
|
||||
};
|
||||
|
||||
pub struct PosIntEditor {
|
||||
radix: u32,
|
||||
digits: EditTree,
|
||||
|
||||
// todo: endianness
|
||||
}
|
||||
|
||||
impl PosIntEditor {
|
||||
pub fn new(ctx: Arc<RwLock<Context>>, radix: u32) -> Self {
|
||||
PosIntEditor {
|
||||
radix,
|
||||
digits: EditTree::new(
|
||||
ctx,
|
||||
r3vi::buffer::singleton::SingletonBuffer::new(0).get_port()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_u64(ctx: Arc<RwLock<Context>>, radix: u32, value: u64) -> Self {
|
||||
let mut edit = PosIntEditor::new(ctx, radix);
|
||||
edit.set_value_u64( value );
|
||||
edit
|
||||
}
|
||||
|
||||
pub fn set_value_u64(&mut self, mut value: u64) {
|
||||
self.digits.send_cmd_obj(ListCmd::Clear.into_repr_tree(&self.digits.ctx));
|
||||
|
||||
while value > 0 {
|
||||
let digit_val = (value % self.radix as u64) as u32;
|
||||
value /= self.radix as u64;
|
||||
|
||||
// if BigEndian
|
||||
self.digits.goto(TreeCursor::home());
|
||||
|
||||
self.digits.send_cmd_obj(ReprTree::from_char(&self.digits.ctx, char::from_digit(digit_val, self.radix).expect("invalid digit")));
|
||||
}
|
||||
self.digits.goto(TreeCursor::none());
|
||||
}
|
||||
|
||||
pub fn into_node(self) -> EditTree {
|
||||
self.digits
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = u32>> {
|
||||
let radix = self.radix;
|
||||
self.digits
|
||||
.get_data_port()
|
||||
.filter_map(move |digit_editor| {
|
||||
digit_editor.read().unwrap().data.get()?.to_digit(radix)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_value(&self) -> u32 {
|
||||
let mut value = 0;
|
||||
let mut weight = 1;
|
||||
for digit_value in self
|
||||
.get_data_port()
|
||||
.get_view()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.rev()
|
||||
{
|
||||
value += digit_value * weight;
|
||||
weight *= self.radix;
|
||||
}
|
||||
|
||||
value
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
150
lib-nested-core/src/editors/integer/mod.rs
Normal file
150
lib-nested-core/src/editors/integer/mod.rs
Normal file
|
@ -0,0 +1,150 @@
|
|||
pub mod add;
|
||||
pub mod editor;
|
||||
pub mod radix;
|
||||
pub mod ctx;
|
||||
|
||||
pub use {
|
||||
add::Add,
|
||||
editor::PosIntEditor,
|
||||
radix::RadixProjection,
|
||||
ctx::init_ctx
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
use {
|
||||
r3vi::{
|
||||
view::{
|
||||
View, ViewPort, OuterViewPort,
|
||||
Observer,
|
||||
ObserverBroadcast,
|
||||
sequence::*
|
||||
}
|
||||
},
|
||||
crate::{
|
||||
editors::integer::radix::{
|
||||
PosIntProjections
|
||||
}
|
||||
},
|
||||
std::sync::{Arc, RwLock}
|
||||
};
|
||||
|
||||
pub trait PositionalUInt : SequenceView<Item = u64> {
|
||||
fn get_radix(&self) -> u64;
|
||||
fn get_value(&self) -> u64 {
|
||||
let mut val = 0;
|
||||
let mut r = 1;
|
||||
for i in 0..self.len().unwrap_or(0) {
|
||||
if let Some(digit_val) = self.get(&i) {
|
||||
val += r * digit_val;
|
||||
r *= self.get_radix();
|
||||
}
|
||||
}
|
||||
|
||||
val
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: PositionalUInt> PositionalUInt for RwLock<V> {
|
||||
fn get_radix(&self) -> u64 {
|
||||
self.read().unwrap().get_radix()
|
||||
}
|
||||
}
|
||||
|
||||
struct PosUIntFromDigits {
|
||||
radix: u64,
|
||||
src_digits: Option<Arc<dyn SequenceView<Item = u64>>>,
|
||||
cast: Arc<RwLock<ObserverBroadcast<dyn PositionalUInt>>>
|
||||
}
|
||||
|
||||
impl View for PosUIntFromDigits {
|
||||
type Msg = usize;
|
||||
}
|
||||
|
||||
impl SequenceView for PosUIntFromDigits {
|
||||
type Item = u64;
|
||||
|
||||
fn get(&self, idx: &usize) -> Option<u64> {
|
||||
self.src_digits.get(idx)
|
||||
}
|
||||
|
||||
fn len(&self) -> Option<usize> {
|
||||
self.src_digits.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl PositionalUInt for PosUIntFromDigits {
|
||||
fn get_radix(&self) -> u64 {
|
||||
self.radix
|
||||
}
|
||||
}
|
||||
|
||||
impl Observer<dyn SequenceView<Item = u64>> for PosUIntFromDigits {
|
||||
fn reset(&mut self, new_src: Option<Arc<dyn SequenceView<Item = u64>>>) {
|
||||
self.src_digits = new_src;
|
||||
// self.cast.write().unwrap().notify(0);
|
||||
}
|
||||
|
||||
fn notify(&mut self, idx: &usize) {
|
||||
self.cast.write().unwrap().notify(idx);
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub trait DigitSeqProjection {
|
||||
fn to_positional_uint(&self, radix: u64) -> OuterViewPort<dyn PositionalUInt>;
|
||||
}
|
||||
|
||||
impl DigitSeqProjection for OuterViewPort<dyn SequenceView<Item = u64>> {
|
||||
fn to_positional_uint(&self, radix: u64) -> OuterViewPort<dyn PositionalUInt> {
|
||||
let port = ViewPort::new();
|
||||
port.add_update_hook(Arc::new(self.0.clone()));
|
||||
|
||||
let proj = Arc::new(RwLock::new(PosUIntFromDigits {
|
||||
radix,
|
||||
src_digits: None,
|
||||
cast: port.inner().get_broadcast()
|
||||
}));
|
||||
|
||||
self.add_observer(proj.clone());
|
||||
port.set_view(Some(proj));
|
||||
port.into_outer()
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
struct PosUIntToDigits {
|
||||
src: Option<Arc<dyn PositionalUInt>>,
|
||||
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = u64>>>>
|
||||
}
|
||||
|
||||
impl View for PosUIntToDigits {
|
||||
type Msg = usize;
|
||||
}
|
||||
|
||||
impl SequenceView for PosUIntToDigits {
|
||||
type Item = u64;
|
||||
|
||||
fn get(&self, idx: &usize) -> Option<u64> {
|
||||
self.src.get(idx)
|
||||
}
|
||||
|
||||
fn len(&self) -> Option<usize> {
|
||||
self.src.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl Observer<dyn PositionalUInt> for PosUIntToDigits {
|
||||
fn reset(&mut self, view: Option<Arc<dyn PositionalUInt>>) {
|
||||
self.src = view;
|
||||
// self.cast.notify_all();
|
||||
}
|
||||
|
||||
fn notify(&mut self, idx: &usize) {
|
||||
self.cast.notify(idx);
|
||||
}
|
||||
}
|
||||
|
||||
|
152
lib-nested-core/src/editors/integer/radix.rs
Normal file
152
lib-nested-core/src/editors/integer/radix.rs
Normal file
|
@ -0,0 +1,152 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{
|
||||
View, ViewPort,
|
||||
InnerViewPort, Observer, OuterViewPort,
|
||||
ObserverBroadcast,
|
||||
sequence::*,
|
||||
list::*
|
||||
},
|
||||
buffer::{vec::*}
|
||||
},
|
||||
crate::{
|
||||
editors::integer::{
|
||||
PositionalUInt
|
||||
},
|
||||
repr_tree::{ReprTree, ReprLeaf}
|
||||
},
|
||||
std::sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub trait PosIntProjections {
|
||||
fn transform_radix(&self, dst_radix: u64) -> OuterViewPort<dyn SequenceView<Item = u64>>;
|
||||
// fn to_digits(&self) -> OuterViewPort<dyn SequenceView<Item = usize>>;
|
||||
}
|
||||
|
||||
impl PosIntProjections for OuterViewPort<dyn PositionalUInt> {
|
||||
fn transform_radix(&self, dst_radix: u64) -> OuterViewPort<dyn SequenceView<Item = u64>> {
|
||||
let port = ViewPort::<dyn SequenceView<Item = u64>>::new();
|
||||
port.add_update_hook(Arc::new(self.0.clone()));
|
||||
|
||||
// let mut vec_port = ViewPort::new();
|
||||
let proj = Arc::new(RwLock::new(RadixProjection {
|
||||
src: None,
|
||||
dst_radix,
|
||||
dst_digits: VecBuffer::new(),
|
||||
cast: port.inner().get_broadcast()
|
||||
}));
|
||||
|
||||
self.add_observer(proj.clone());
|
||||
port.set_view(Some(proj as Arc<dyn SequenceView<Item = u64>>));
|
||||
port.into_outer()
|
||||
}
|
||||
/*
|
||||
fn to_digits(&self) -> OuterViewPort<dyn SequenceView<Item = usize>> {
|
||||
let port = ViewPort::new();
|
||||
port.add_update_hook(Arc::new(self.0.clone()));
|
||||
let proj = Arc::new(RwLock::new(PosUIntToDigits {
|
||||
src: None,
|
||||
cast: port.inner().get_broadcast()
|
||||
}));
|
||||
self.add_observer(proj.clone());
|
||||
port.inner().set_view(Some(proj));
|
||||
port.into_outer()
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub struct RadixProjection {
|
||||
src: Option<Arc<dyn PositionalUInt>>,
|
||||
dst_radix: u64,
|
||||
dst_digits: VecBuffer<u64>,
|
||||
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = u64>>>>
|
||||
}
|
||||
|
||||
impl View for RadixProjection {
|
||||
type Msg = usize;
|
||||
}
|
||||
|
||||
impl SequenceView for RadixProjection {
|
||||
type Item = u64;
|
||||
|
||||
fn get(&self, idx: &usize) -> Option<u64> {
|
||||
if *idx < self.dst_digits.len() {
|
||||
Some(self.dst_digits.get(*idx))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn len(&self) -> Option<usize> {
|
||||
Some(self.dst_digits.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl PositionalUInt for RadixProjection {
|
||||
fn get_radix(&self) -> u64 {
|
||||
self.dst_radix
|
||||
}
|
||||
}
|
||||
|
||||
impl Observer< dyn PositionalUInt > for RadixProjection {
|
||||
fn reset(&mut self, view: Option<Arc<dyn PositionalUInt>>) {
|
||||
self.src = view;
|
||||
self.update();
|
||||
}
|
||||
|
||||
fn notify(&mut self, idx: &usize) {
|
||||
self.update();
|
||||
// self.update_digit(idx)
|
||||
}
|
||||
}
|
||||
|
||||
impl RadixProjection {
|
||||
/// recalculate everything
|
||||
fn update(&mut self) {
|
||||
// let mut dst = self.dst_digits;
|
||||
let old_len = self.dst_digits.len();
|
||||
self.dst_digits.clear();
|
||||
|
||||
if let Some(src) = self.src.as_ref() {
|
||||
let mut val = src.get_value();
|
||||
if val == 0 {
|
||||
self.dst_digits.push(0);
|
||||
} else {
|
||||
if self.dst_radix == 0 {
|
||||
self.dst_digits.push(val);
|
||||
} else {
|
||||
while val > 0 {
|
||||
self.dst_digits.push(val % self.dst_radix);
|
||||
val /= self.dst_radix;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let new_len = self.dst_digits.len();
|
||||
for i in 0 .. usize::max(old_len, new_len) {
|
||||
self.cast.write().unwrap().notify(&i);
|
||||
}
|
||||
}
|
||||
|
||||
fn _update_dst_digit(&mut self, _idx: usize) {
|
||||
/*
|
||||
let v = 0; // calculate new digit value
|
||||
|
||||
// which src-digits are responsible?
|
||||
|
||||
if idx < self.dst_digits.len() {
|
||||
self.dst_digits.get_mut(idx) = v;
|
||||
} else if idx == self.dst_digits.len() {
|
||||
self.dst_digits.push(v);
|
||||
} else {
|
||||
// error
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,9 @@ use {
|
|||
view::{singleton::*}
|
||||
},
|
||||
crate::{
|
||||
editors::list::{ListEditor, ListCursor, ListCursorMode},
|
||||
type_system::{Context, ReprTree},
|
||||
tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
|
||||
commander::{ObjCommander}
|
||||
editors::{list::{ListEditor, ListCursor, ListCursorMode}, ObjCommander},
|
||||
repr_tree::{Context, ReprTree},
|
||||
edit_tree::{EditTree, TreeNav, TreeNavResult, TreeCursor},
|
||||
},
|
||||
std::sync::{Arc, RwLock}
|
||||
};
|
||||
|
@ -23,11 +22,11 @@ pub enum ListCmd {
|
|||
}
|
||||
|
||||
impl ListCmd {
|
||||
// note: cant use Into becaue of ctx (maybe global typedict?)
|
||||
pub fn into_repr_tree(self, ctx: &Arc<RwLock<Context>>) -> Arc<RwLock<ReprTree>> {
|
||||
let buf = r3vi::buffer::singleton::SingletonBuffer::new(self);
|
||||
ReprTree::new_leaf(
|
||||
ReprTree::from_singleton_buffer(
|
||||
Context::parse(ctx, "ListCmd"),
|
||||
buf.get_port().into()
|
||||
r3vi::buffer::singleton::SingletonBuffer::new(self)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -36,29 +35,7 @@ impl ObjCommander for ListEditor {
|
|||
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
|
||||
let cmd_repr = cmd_obj.read().unwrap();
|
||||
|
||||
if let Some(view) = cmd_repr.get_view::<dyn SingletonView<Item = NestedNode>>() {
|
||||
let node = view.get();
|
||||
let cur = self.cursor.get();
|
||||
|
||||
if let Some(idx) = cur.idx {
|
||||
match cur.mode {
|
||||
ListCursorMode::Select => {
|
||||
*self.data.get_mut(idx as usize) = Arc::new(RwLock::new(node));
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
ListCursorMode::Insert => {
|
||||
self.insert(Arc::new(RwLock::new(node)));
|
||||
self.cursor.set(ListCursor{ idx: Some(idx+1), mode: ListCursorMode::Insert });
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
|
||||
else if let Some(cmd) = cmd_repr.get_view::<dyn SingletonView<Item = ListCmd>>() {
|
||||
eprintln!("pty-list-editor some list cmmd");
|
||||
if let Some(cmd) = cmd_repr.get_view::<dyn SingletonView<Item = ListCmd>>() {
|
||||
|
||||
let cur = self.cursor.get();
|
||||
drop(cmd_repr);
|
||||
|
@ -72,12 +49,12 @@ impl ObjCommander for ListEditor {
|
|||
if let Some(idx) = cur.idx {
|
||||
match cur.mode {
|
||||
ListCursorMode::Select => {
|
||||
if let Some(mut item) = self.get_item().clone() {
|
||||
if let Some(mut item) = self.get_cur_edittree() {
|
||||
let mut item = item.write().unwrap();
|
||||
let item_cur = item.get_cursor();
|
||||
|
||||
match cmd.get() {
|
||||
ListCmd::DeletePxev => {
|
||||
eprintln!("SELECT: delete pxev");
|
||||
if idx > 0
|
||||
&& item_cur.tree_addr.iter().fold(
|
||||
true,
|
||||
|
@ -119,7 +96,6 @@ impl ObjCommander for ListEditor {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
eprintln!("ptylist: no item");
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
},
|
||||
|
@ -127,7 +103,6 @@ impl ObjCommander for ListEditor {
|
|||
ListCursorMode::Insert => {
|
||||
match cmd.get() {
|
||||
ListCmd::DeletePxev => {
|
||||
eprintln!("INSERT: delete pxev");
|
||||
self.delete_pxev();
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
|
@ -150,21 +125,36 @@ impl ObjCommander for ListEditor {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
eprintln!("ptylist: cursor has no idx");
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if let Some(cur_item) = self.get_item_mut() {
|
||||
drop(cmd_repr);
|
||||
cur_item.write().unwrap().send_cmd_obj(cmd_obj);
|
||||
TreeNavResult::Continue
|
||||
let cur = self.cursor.get();
|
||||
|
||||
if let Some(idx) = cur.idx {
|
||||
match cur.mode {
|
||||
ListCursorMode::Select => {
|
||||
// what ??
|
||||
//*self.data.get_mut(idx as usize) = Arc::new(RwLock::new(node));
|
||||
|
||||
|
||||
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
ListCursorMode::Insert => {
|
||||
self.insert( cmd_obj.clone() );
|
||||
|
||||
// todo: setup edittree
|
||||
|
||||
self.cursor.set(ListCursor{ idx: Some(idx+1), mode: ListCursorMode::Insert });
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
179
lib-nested-core/src/editors/list/ctx.rs
Normal file
179
lib-nested-core/src/editors/list/ctx.rs
Normal file
|
@ -0,0 +1,179 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{
|
||||
ViewPort, port::UpdateTask,
|
||||
OuterViewPort, Observer,
|
||||
singleton::*,
|
||||
list::*
|
||||
},
|
||||
buffer::{singleton::*, vec::*}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
repr_tree::{Context, ReprTree, ReprTreeArc, ReprLeaf, ReprTreeExt, GenericReprTreeMorphism},
|
||||
edit_tree::{EditTree},
|
||||
editors::{
|
||||
char::{CharEditor},
|
||||
list::{ListEditor}
|
||||
}
|
||||
},
|
||||
std::sync::{Arc, RwLock}
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub fn init_ctx(ctx: Arc<RwLock<Context>>) {
|
||||
ctx.write().unwrap().add_varname("Item");
|
||||
|
||||
let list_morph_editsetup1 = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "<List Item>~<List EditTree>~<Vec EditTree>"),
|
||||
Context::parse(&ctx, "<List Item>~EditTree"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
let item_id = laddertypes::TypeID::Var( ctx.read().unwrap().get_var_typeid("Item").unwrap() );
|
||||
if let Some( item_type ) = σ.get( &item_id ) {
|
||||
let mut item_vec_rt = src_rt
|
||||
.descend(
|
||||
Context::parse(&ctx, "<List Item>~<Vec EditTree>")
|
||||
.apply_substitution(&|id| σ.get(id).cloned()).clone()
|
||||
)
|
||||
.expect("cant descend src repr");
|
||||
|
||||
let item_vec_buffer = item_vec_rt.vec_buffer::< ReprTreeArc >();
|
||||
|
||||
let mut list_editor = ListEditor::with_data(ctx.clone(), item_type.clone(), item_vec_buffer);
|
||||
let edittree_list = list_editor.into_node(
|
||||
SingletonBuffer::<usize>::new(0).get_port()
|
||||
);
|
||||
src_rt.insert_leaf(
|
||||
Context::parse(&ctx, "<List Item> ~ EditTree")
|
||||
.apply_substitution(&|id| σ.get(id).cloned()).clone(),
|
||||
|
||||
ReprLeaf::from_singleton_buffer(
|
||||
SingletonBuffer::new(Arc::new(RwLock::new(edittree_list)))
|
||||
)
|
||||
);
|
||||
|
||||
ctx.read().unwrap().setup_edittree( &src_rt );
|
||||
} else {
|
||||
eprintln!("no item type");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let list_morph_editsetup3 = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "<List Item> ~ EditTree"),
|
||||
Context::parse(&ctx, "<List Item> ~ <List EditTree>"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
let edittree = src_rt.edittree( &ctx );
|
||||
let list_edit = edittree.get().read().unwrap().get_edit::< ListEditor >().unwrap();
|
||||
let edittree_items = list_edit.read().unwrap().data.get_port().to_list();
|
||||
|
||||
eprintln!("edittree_items.len() = {:?}", edittree_items.get_view().unwrap().len());
|
||||
|
||||
src_rt.attach_leaf_to(
|
||||
Context::parse(&ctx, "<List Item> ~ <List EditTree>")
|
||||
.apply_substitution(&|x| σ.get(x).cloned()).clone(),
|
||||
edittree_items
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let seq_morph_to_list_char = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "<Seq Char>"),
|
||||
Context::parse(&ctx, "<Seq Char>~<List Char>"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
src_rt.attach_leaf_to(
|
||||
Context::parse(&ctx, "<List Char>"),
|
||||
src_rt.view_seq::<char>().to_list()
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let list_morph_to_vec_char = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "<List Char>"),
|
||||
Context::parse(&ctx, "<List Char>~<Vec Char>"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
src_rt.attach_leaf_to(
|
||||
Context::parse(&ctx, "<Vec Char>"),
|
||||
src_rt.view_list::<char>()
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let seq_morph_to_list_u64 = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "<Seq machine.UInt64>"),
|
||||
Context::parse(&ctx, "<Seq machine.UInt64>~<List machine.UInt64>"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
src_rt.attach_leaf_to(
|
||||
Context::parse(&ctx, "<List machine.UInt64>"),
|
||||
src_rt.view_seq::<u64>().to_list()
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let list_morph_to_vec_u64 = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "<List machine.UInt64>"),
|
||||
Context::parse(&ctx, "<List machine.UInt64>~<Vec machine.UInt64>"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
src_rt.attach_leaf_to(
|
||||
Context::parse(&ctx, "<Vec machine.UInt64>"),
|
||||
src_rt.view_list::<u64>()
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let list_morph_from_vec_char = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "<List Char>~<Vec Char>"),
|
||||
Context::parse(&ctx, "<List Char>"),
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
let src_port = src_rt.descend(Context::parse(&ctx, "<List Char>~<Vec Char>")).expect("descend")
|
||||
.get_port::<RwLock<Vec<char>>>().unwrap();
|
||||
|
||||
src_rt.attach_leaf_to( Context::parse(&ctx, "<List Char>"), src_port.to_list() );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
let list_morph_to_vec_edittree = GenericReprTreeMorphism::new(
|
||||
Context::parse(&ctx, "<List EditTree>"),
|
||||
Context::parse(&ctx, "<List EditTree> ~ <Vec EditTree>"),
|
||||
|
||||
{
|
||||
let ctx = ctx.clone();
|
||||
move |src_rt, σ| {
|
||||
let list_port = src_rt.get_port::<dyn ListView< Arc<RwLock<EditTree>> >>().unwrap();
|
||||
src_rt.attach_leaf_to( Context::parse(&ctx, "<Vec EditTree>"), list_port );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
ctx.write().unwrap().morphisms.add_morphism( list_morph_editsetup1 );
|
||||
ctx.write().unwrap().morphisms.add_morphism( list_morph_editsetup3 );
|
||||
ctx.write().unwrap().morphisms.add_morphism( list_morph_from_vec_char );
|
||||
ctx.write().unwrap().morphisms.add_morphism( seq_morph_to_list_char );
|
||||
ctx.write().unwrap().morphisms.add_morphism( seq_morph_to_list_u64 );
|
||||
ctx.write().unwrap().morphisms.add_morphism( list_morph_to_vec_char );
|
||||
ctx.write().unwrap().morphisms.add_morphism( list_morph_to_vec_u64 );
|
||||
ctx.write().unwrap().morphisms.add_morphism( list_morph_to_vec_edittree );
|
||||
}
|
|
@ -1,15 +1,14 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{ViewPort, OuterViewPort, singleton::*, sequence::*},
|
||||
buffer::{singleton::*, vec::*}
|
||||
view::{OuterViewPort, singleton::*, sequence::*, list::*},
|
||||
buffer::{singleton::*, vec::*},
|
||||
projection::*
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context, ReprTree},
|
||||
editors::list::{ListCursor, ListCursorMode, ListCmd},
|
||||
tree::{NestedNode, TreeNav, TreeCursor},
|
||||
diagnostics::Diagnostics,
|
||||
commander::ObjCommander
|
||||
repr_tree::{Context, ReprTree, ReprTreeExt, node::ReprTreeArc},
|
||||
edit_tree::{EditTree, TreeNav, TreeCursor, diagnostics::Diagnostics},
|
||||
editors::{list::{ListCursor, ListCursorMode, ListCmd}, ObjCommander},
|
||||
},
|
||||
std::sync::{Arc, RwLock}
|
||||
};
|
||||
|
@ -17,37 +16,46 @@ use {
|
|||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub struct ListEditor {
|
||||
pub(super) cursor: SingletonBuffer<ListCursor>,
|
||||
|
||||
// todo: (?) remove RwLock<..> around NestedNode ??
|
||||
pub data: VecBuffer< Arc<RwLock<NestedNode>> >,
|
||||
|
||||
pub spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
|
||||
pub cursor: SingletonBuffer<ListCursor>,
|
||||
pub data: VecBuffer< ReprTreeArc >,
|
||||
pub spillbuf: Arc<RwLock< Vec< ReprTreeArc > >>,
|
||||
|
||||
pub(super) addr_port: OuterViewPort<dyn SequenceView<Item = isize>>,
|
||||
pub(super) mode_port: OuterViewPort<dyn SingletonView<Item = ListCursorMode>>,
|
||||
|
||||
depth: OuterViewPort<dyn SingletonView<Item = usize>>,
|
||||
|
||||
pub(crate) ctx: Arc<RwLock<Context>>,
|
||||
pub ctx: Arc<RwLock<Context>>,
|
||||
|
||||
/// item type
|
||||
pub(super) typ: TypeTerm,
|
||||
pub typ: TypeTerm,
|
||||
}
|
||||
|
||||
impl ListEditor {
|
||||
pub fn new(
|
||||
ctx: Arc<RwLock<Context>>,
|
||||
typ: TypeTerm
|
||||
) -> Self {
|
||||
Self::with_data(
|
||||
ctx,
|
||||
typ,
|
||||
VecBuffer::new()
|
||||
)
|
||||
}
|
||||
|
||||
pub fn with_data(
|
||||
ctx: Arc<RwLock<Context>>,
|
||||
typ: TypeTerm,
|
||||
data: VecBuffer< ReprTreeArc >
|
||||
) -> Self {
|
||||
let cursor = SingletonBuffer::new(ListCursor::default());
|
||||
let data : VecBuffer<Arc<RwLock<NestedNode>>> = VecBuffer::new();
|
||||
|
||||
ListEditor {
|
||||
mode_port: cursor
|
||||
.get_port()
|
||||
.map({
|
||||
let data = data.clone();
|
||||
let ctx = ctx.clone();
|
||||
move |c| {
|
||||
let ip = SingletonBuffer::new(c.mode).get_port();
|
||||
match c.mode {
|
||||
|
@ -55,9 +63,11 @@ impl ListEditor {
|
|||
ListCursorMode::Select => {
|
||||
if let Some(idx) = c.idx {
|
||||
if idx >= 0 && idx < data.len() as isize {
|
||||
data.get(idx as usize).read().unwrap().get_mode_view()
|
||||
data.get(idx as usize)
|
||||
.edittree(&ctx).get()
|
||||
.read().unwrap()
|
||||
.get_mode_view()
|
||||
} else {
|
||||
eprintln!("ListEditor::mode_port invalid cursor idx");
|
||||
ip
|
||||
}
|
||||
} else {
|
||||
|
@ -77,11 +87,15 @@ impl ListEditor {
|
|||
cursor.get_port()
|
||||
.map({
|
||||
let data = data.clone();
|
||||
let ctx = ctx.clone();
|
||||
move |cur| {
|
||||
if cur.mode == ListCursorMode::Select {
|
||||
if let Some(idx) = cur.idx {
|
||||
if idx >= 0 && idx < data.len() as isize {
|
||||
return data.get(idx as usize).read().unwrap().get_addr_view();
|
||||
return data.get(idx as usize)
|
||||
.edittree(&ctx).get()
|
||||
.read().unwrap()
|
||||
.get_addr_view();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,8 +117,7 @@ impl ListEditor {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn into_node(mut self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode {
|
||||
let data = self.get_data();
|
||||
pub fn into_node(mut self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> EditTree {
|
||||
let ctx = self.ctx.clone();
|
||||
|
||||
self.depth = depth.clone();
|
||||
|
@ -112,31 +125,24 @@ impl ListEditor {
|
|||
|
||||
let e = editor.read().unwrap();
|
||||
|
||||
let mut node = NestedNode::new(ctx, data, depth)
|
||||
let mut node = EditTree::new(ctx, depth)
|
||||
.set_editor(editor.clone())
|
||||
.set_nav(editor.clone())
|
||||
.set_cmd(editor.clone())
|
||||
.set_diag(e
|
||||
.get_data_port()
|
||||
.set_diag(e.get_edittree_seq()
|
||||
.enumerate()
|
||||
.map(
|
||||
|(idx, item_editor)| {
|
||||
let idx = *idx;
|
||||
item_editor
|
||||
.get_msg_port()
|
||||
.map(
|
||||
move |msg| {
|
||||
let mut msg = msg.clone();
|
||||
msg.addr.insert(0, idx);
|
||||
msg
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
.flatten()
|
||||
);
|
||||
.map(|(idx, item_editor)| {
|
||||
let idx = *idx;
|
||||
item_editor.get_msg_port()
|
||||
.map(move |msg| {
|
||||
let mut msg = msg.clone();
|
||||
msg.addr.insert(0, idx);
|
||||
msg
|
||||
})
|
||||
})
|
||||
.flatten());
|
||||
|
||||
node.spillbuf = e.spillbuf.clone();
|
||||
node.ctrl.spillbuf = e.spillbuf.clone();
|
||||
node
|
||||
}
|
||||
|
||||
|
@ -155,12 +161,23 @@ impl ListEditor {
|
|||
self.cursor.get_port()
|
||||
}
|
||||
|
||||
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = NestedNode>> {
|
||||
self.data.get_port().to_sequence().map(
|
||||
|x| x.read().unwrap().clone()
|
||||
)
|
||||
pub fn get_reprtree_list(&self) -> OuterViewPort<dyn ListView<ReprTreeArc>> {
|
||||
self.data.get_port().to_list()
|
||||
}
|
||||
|
||||
pub fn get_edittree_list(&self) -> OuterViewPort<dyn ListView<EditTree>> {
|
||||
self.get_reprtree_list().map({
|
||||
let ctx = self.ctx.clone();
|
||||
move|rt| {
|
||||
rt.edittree(&ctx).get().read().unwrap().clone()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_edittree_seq(&self) -> OuterViewPort<dyn SequenceView<Item = EditTree>> {
|
||||
self.get_edittree_list().to_sequence()
|
||||
}
|
||||
/*
|
||||
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
|
||||
let data_view = self.get_data_port();
|
||||
ReprTree::new_leaf(
|
||||
|
@ -168,12 +185,12 @@ impl ListEditor {
|
|||
data_view.into()
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_item(&self) -> Option<NestedNode> {
|
||||
*/
|
||||
pub fn get_item(&self) -> Option< ReprTreeArc > {
|
||||
if let Some(idx) = self.cursor.get().idx {
|
||||
let idx = crate::utils::modulo(idx as isize, self.data.len() as isize) as usize;
|
||||
if idx < self.data.len() {
|
||||
Some(self.data.get(idx).read().unwrap().clone())
|
||||
Some( self.data.get(idx).clone() )
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -182,7 +199,7 @@ impl ListEditor {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_item_mut(&mut self) -> Option<MutableVecAccess<Arc<RwLock<NestedNode>>>> {
|
||||
pub fn get_item_mut(&mut self) -> Option<MutableVecAccess< ReprTreeArc >> {
|
||||
if let Some(idx) = self.cursor.get().idx {
|
||||
let idx = crate::utils::modulo(idx as isize, self.data.len() as isize) as usize;
|
||||
if idx < self.data.len() {
|
||||
|
@ -195,6 +212,23 @@ impl ListEditor {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_edittree(&self, idx: usize) -> Arc<RwLock<EditTree>> {
|
||||
self.data.get(idx).edittree(&self.ctx).get()
|
||||
}
|
||||
|
||||
pub fn get_cur_edittree(&self) -> Option< Arc<RwLock<EditTree>> > {
|
||||
if let Some(idx) = self.cursor.get().idx {
|
||||
let idx = crate::utils::modulo(idx as isize, self.data.len() as isize) as usize;
|
||||
if idx < self.data.len() {
|
||||
Some(self.get_edittree(idx))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// is the element-type also a list-like editor (i.e. impls TreeNav)
|
||||
pub fn is_listlist(&self) -> bool {
|
||||
self.ctx.read().unwrap().is_list_type(&self.typ)
|
||||
|
@ -233,10 +267,9 @@ impl ListEditor {
|
|||
}
|
||||
|
||||
/// insert a new element
|
||||
pub fn insert(&mut self, item: Arc<RwLock<NestedNode>>) {
|
||||
eprintln!("list insert");
|
||||
|
||||
item.read().unwrap().depth.0.set_view(
|
||||
pub fn insert(&mut self, item: ReprTreeArc) {
|
||||
let item_edit = item.edittree(&self.ctx).get();
|
||||
item_edit.read().unwrap().disp.depth.0.set_view(
|
||||
self.depth.map(|d| d+1).get_view()
|
||||
);
|
||||
|
||||
|
@ -248,8 +281,7 @@ impl ListEditor {
|
|||
if self.is_listlist() {
|
||||
cur.mode = ListCursorMode::Select;
|
||||
} else {
|
||||
eprintln!("list insert: is not a listlist ({:?})", self.typ);
|
||||
item.write().unwrap().goto(TreeCursor::none());
|
||||
item_edit.write().unwrap().goto(TreeCursor::none());
|
||||
cur.idx = Some(idx + 1);
|
||||
}
|
||||
}
|
||||
|
@ -264,13 +296,11 @@ impl ListEditor {
|
|||
|
||||
self.cursor.set(cur);
|
||||
} else {
|
||||
//eprintln!("insert: no cursor");
|
||||
}
|
||||
}
|
||||
|
||||
/// split the list off at the current cursor position and return the second half
|
||||
pub fn split(&mut self) {
|
||||
eprintln!("split");
|
||||
let cur = self.cursor.get();
|
||||
if let Some(idx) = cur.idx {
|
||||
let idx = idx as usize;
|
||||
|
@ -305,46 +335,45 @@ impl ListEditor {
|
|||
}
|
||||
|
||||
pub fn listlist_split(&mut self) {
|
||||
eprintln!("listlist split");
|
||||
let cur = self.get_cursor();
|
||||
|
||||
if let Some(mut item) = self.get_item().clone() {
|
||||
item.send_cmd_obj(ListCmd::Split.into_repr_tree(&self.ctx));
|
||||
let item_edit = item.edittree(&self.ctx).get();
|
||||
let mut ie = item_edit.write().unwrap();
|
||||
ie.send_cmd_obj(ListCmd::Split.into_repr_tree(&self.ctx));
|
||||
|
||||
if cur.tree_addr.len() < 3 {
|
||||
item.goto(TreeCursor::none());
|
||||
ie.goto(TreeCursor::none());
|
||||
|
||||
self.set_leaf_mode(ListCursorMode::Insert);
|
||||
self.nexd();
|
||||
|
||||
let mut b = item.spillbuf.write().unwrap();
|
||||
let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), self.depth.map(|d| d+1)).unwrap();
|
||||
tail_node.goto(TreeCursor::home());
|
||||
let mut b = ie.ctrl.spillbuf.write().unwrap();
|
||||
|
||||
for node in b.iter() {
|
||||
eprintln!("splid :send to tail node");
|
||||
tail_node
|
||||
.send_cmd_obj(
|
||||
ReprTree::new_leaf(
|
||||
Context::parse(&self.ctx, "NestedNode"),
|
||||
SingletonBuffer::<NestedNode>::new(
|
||||
node.read().unwrap().clone()
|
||||
).get_port().into()
|
||||
)
|
||||
);
|
||||
let rt = ReprTree::new_arc(self.typ.clone());
|
||||
let mut et = self.ctx.read().unwrap().setup_edittree(&rt);
|
||||
|
||||
if let Some(edittree) = et.as_mut(){
|
||||
let mut tail_node = edittree.get();
|
||||
let mut tail_node = tail_node.write().unwrap();
|
||||
tail_node.goto(TreeCursor::home());
|
||||
|
||||
for n in b.iter() {
|
||||
tail_node.send_cmd_obj(n.clone());
|
||||
}
|
||||
|
||||
b.clear();
|
||||
drop(b);
|
||||
drop(item);
|
||||
|
||||
tail_node.goto(TreeCursor::home());
|
||||
if cur.tree_addr.len() > 1 {
|
||||
tail_node.dn();
|
||||
}
|
||||
drop(tail_node);
|
||||
|
||||
self.insert(rt);
|
||||
}
|
||||
b.clear();
|
||||
drop(b);
|
||||
drop(item);
|
||||
|
||||
tail_node.goto(TreeCursor::home());
|
||||
if cur.tree_addr.len() > 1 {
|
||||
tail_node.dn();
|
||||
}
|
||||
|
||||
self.insert(
|
||||
Arc::new(RwLock::new(tail_node))
|
||||
);
|
||||
|
||||
} else {
|
||||
self.up();
|
||||
|
@ -356,8 +385,8 @@ impl ListEditor {
|
|||
|
||||
pub fn listlist_join_pxev(&mut self, idx: isize) {
|
||||
{
|
||||
let cur_editor = self.data.get(idx as usize);
|
||||
let pxv_editor = self.data.get(idx as usize-1);
|
||||
let cur_editor = self.data.get(idx as usize).edittree(&self.ctx).get();
|
||||
let pxv_editor = self.data.get(idx as usize-1).edittree(&self.ctx).get();
|
||||
let mut cur_editor = cur_editor.write().unwrap();
|
||||
let mut pxv_editor = pxv_editor.write().unwrap();
|
||||
|
||||
|
@ -376,16 +405,9 @@ impl ListEditor {
|
|||
|
||||
let old_cur = pxv_editor.get_cursor();
|
||||
|
||||
let data = cur_editor.spillbuf.read().unwrap();
|
||||
let data = cur_editor.ctrl.spillbuf.read().unwrap();
|
||||
for x in data.iter() {
|
||||
pxv_editor.send_cmd_obj(
|
||||
ReprTree::new_leaf(
|
||||
Context::parse(&self.ctx, "NestedNode"),
|
||||
SingletonBuffer::<NestedNode>::new(
|
||||
x.read().unwrap().clone()
|
||||
).get_port().into()
|
||||
)
|
||||
);
|
||||
pxv_editor.send_cmd_obj(x.clone());
|
||||
}
|
||||
|
||||
|
||||
|
@ -415,8 +437,8 @@ impl ListEditor {
|
|||
|
||||
pub fn listlist_join_nexd(&mut self, idx: usize) {
|
||||
{
|
||||
let cur_editor = self.data.get(idx);
|
||||
let nxd_editor = self.data.get(idx + 1);
|
||||
let cur_editor = self.data.get(idx).edittree(&self.ctx).get();
|
||||
let nxd_editor = self.data.get(idx + 1).edittree(&self.ctx).get();
|
||||
let mut cur_editor = cur_editor.write().unwrap();
|
||||
let mut nxd_editor = nxd_editor.write().unwrap();
|
||||
|
||||
|
@ -434,17 +456,10 @@ impl ListEditor {
|
|||
leaf_mode: ListCursorMode::Insert
|
||||
});
|
||||
|
||||
let data = nxd_editor.spillbuf.read().unwrap();
|
||||
let data = nxd_editor.ctrl.spillbuf.read().unwrap();
|
||||
|
||||
for x in data.iter() {
|
||||
cur_editor.send_cmd_obj(
|
||||
ReprTree::new_leaf(
|
||||
Context::parse(&self.ctx, "NestedNode"),
|
||||
SingletonBuffer::<NestedNode>::new(
|
||||
x.read().unwrap().clone()
|
||||
).get_port().into()
|
||||
)
|
||||
);
|
||||
cur_editor.send_cmd_obj(x.clone());
|
||||
}
|
||||
|
||||
// fixme: is it oc0 or old_cur ??
|
||||
|
@ -490,5 +505,3 @@ impl TreeType for ListEditor {
|
|||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
|
@ -1,10 +1,8 @@
|
|||
|
||||
|
||||
pub mod cursor;
|
||||
pub mod editor;
|
||||
pub mod nav;
|
||||
pub mod segment;
|
||||
pub mod pty_editor;
|
||||
pub mod cmd;
|
||||
pub mod ctx;
|
||||
|
||||
|
@ -12,7 +10,6 @@ pub use {
|
|||
cursor::{ListCursor, ListCursorMode},
|
||||
editor::ListEditor,
|
||||
segment::{ListSegment, ListSegmentSequence},
|
||||
pty_editor::{PTYListStyle, PTYListController},
|
||||
cmd::ListCmd,
|
||||
ctx::init_ctx
|
||||
};
|
|
@ -11,7 +11,8 @@ use {
|
|||
ListCursor, ListCursorMode,
|
||||
editor::ListEditor
|
||||
},
|
||||
tree::{TreeCursor, TreeNav, TreeNavResult, TreeHeightOp}
|
||||
repr_tree::{ReprTreeExt},
|
||||
edit_tree::{TreeCursor, TreeNav, TreeNavResult, TreeHeightOp}
|
||||
},
|
||||
cgmath::Vector2
|
||||
};
|
||||
|
@ -35,7 +36,10 @@ impl TreeNav for ListEditor {
|
|||
TreeHeightOp::P => 0,
|
||||
TreeHeightOp::Q => self.data.len() - 1,
|
||||
_ => 0
|
||||
}).read().unwrap().get_height(op)
|
||||
})
|
||||
.edittree(&self.ctx).get()
|
||||
.read().unwrap()
|
||||
.get_height(op)
|
||||
} else {
|
||||
1
|
||||
}
|
||||
|
@ -43,7 +47,9 @@ impl TreeNav for ListEditor {
|
|||
TreeHeightOp::Max => {
|
||||
1 + (0..self.data.len() as usize)
|
||||
.map(|i| self.data
|
||||
.get(i).read().unwrap()
|
||||
.get(i)
|
||||
.edittree(&self.ctx).get()
|
||||
.read().unwrap()
|
||||
.get_height(&TreeHeightOp::Max)
|
||||
)
|
||||
.max()
|
||||
|
@ -68,7 +74,9 @@ impl TreeNav for ListEditor {
|
|||
ListCursorMode::Select => {
|
||||
if let Some(i) = cur.idx {
|
||||
if i < self.data.len() as isize {
|
||||
let mut sub_cur = self.data.get(i as usize).read().unwrap().get_cursor_warp();
|
||||
let mut sub_cur = self.get_edittree(i as usize)
|
||||
.read().unwrap()
|
||||
.get_cursor_warp();
|
||||
sub_cur.tree_addr.insert(0, i as isize - self.data.len() as isize);
|
||||
return sub_cur;
|
||||
} else {
|
||||
|
@ -100,7 +108,7 @@ impl TreeNav for ListEditor {
|
|||
ListCursorMode::Select => {
|
||||
if let Some(i) = cur.idx {
|
||||
if i < self.data.len() as isize {
|
||||
let mut sub_cur = self.data.get(i as usize).read().unwrap().get_cursor();
|
||||
let mut sub_cur = self.get_edittree(i as usize).read().unwrap().get_cursor();
|
||||
if sub_cur.tree_addr.len() > 0 {
|
||||
sub_cur.tree_addr.insert(0, i as isize);
|
||||
return sub_cur;
|
||||
|
@ -124,7 +132,7 @@ impl TreeNav for ListEditor {
|
|||
let old_cur = self.cursor.get();
|
||||
if let Some(i) = old_cur.idx {
|
||||
if i < self.data.len() as isize {
|
||||
self.data.get_mut(i as usize).write().unwrap().goto(TreeCursor::none());
|
||||
self.get_edittree(i as usize).write().unwrap().goto(TreeCursor::none());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,8 +153,7 @@ impl TreeNav for ListEditor {
|
|||
});
|
||||
|
||||
if new_cur.leaf_mode == ListCursorMode::Select && self.data.len() > 0 {
|
||||
self.data
|
||||
.get_mut(idx as usize)
|
||||
self.get_edittree(idx as usize)
|
||||
.write().unwrap()
|
||||
.goto(TreeCursor {
|
||||
leaf_mode: ListCursorMode::Select,
|
||||
|
@ -165,8 +172,7 @@ impl TreeNav for ListEditor {
|
|||
idx: Some(idx),
|
||||
});
|
||||
|
||||
self.data
|
||||
.get_mut(idx as usize)
|
||||
self.get_edittree(idx as usize)
|
||||
.write().unwrap()
|
||||
.goto(TreeCursor {
|
||||
leaf_mode: new_cur.leaf_mode,
|
||||
|
@ -195,7 +201,6 @@ impl TreeNav for ListEditor {
|
|||
TreeNavResult::Exit
|
||||
} else if direction.y > 0 {
|
||||
// dn
|
||||
eprintln!("dn: data.len() = {}", self.data.len());
|
||||
self.cursor.set(ListCursor {
|
||||
mode: if self.data.len() > 0 { cur.leaf_mode } else { ListCursorMode::Insert },
|
||||
idx: Some(0)
|
||||
|
@ -213,8 +218,7 @@ impl TreeNav for ListEditor {
|
|||
// dn
|
||||
|
||||
if cur.tree_addr[0] < self.data.len() as isize {
|
||||
if self.data
|
||||
.get_mut(cur.tree_addr[0] as usize)
|
||||
if self.get_edittree(cur.tree_addr[0] as usize)
|
||||
.write().unwrap()
|
||||
.goby(Vector2::new(direction.x, direction.y))
|
||||
== TreeNavResult::Continue {
|
||||
|
@ -248,11 +252,10 @@ impl TreeNav for ListEditor {
|
|||
|
||||
match cur.leaf_mode {
|
||||
ListCursorMode::Select => {
|
||||
let cur_item = self.data.get(cur.tree_addr[0] as usize);
|
||||
let cur_item = self.get_edittree(cur.tree_addr[0] as usize);
|
||||
let cur_height = cur_item.read().unwrap().get_height(&TreeHeightOp::Max);
|
||||
|
||||
let new_item = self.data
|
||||
.get_mut(idx as usize);
|
||||
let new_item = self.get_edittree(idx as usize);
|
||||
|
||||
let height = new_item.read().unwrap().get_height(
|
||||
if direction.x < 0 {
|
||||
|
@ -278,7 +281,7 @@ impl TreeNav for ListEditor {
|
|||
if direction.x > 0
|
||||
{
|
||||
if (cur.tree_addr[0] as usize) < self.data.len() {
|
||||
let cur_item = self.data.get(cur.tree_addr[0] as usize);
|
||||
let cur_item = self.get_edittree(cur.tree_addr[0] as usize);
|
||||
let cur_height = cur_item.read().unwrap().get_height(&TreeHeightOp::P);
|
||||
|
||||
if gravity && cur_height > 1 {
|
||||
|
@ -290,7 +293,7 @@ impl TreeNav for ListEditor {
|
|||
}
|
||||
} else {
|
||||
if (idx as usize) < self.data.len() {
|
||||
let pxv_item = self.data.get(idx as usize);
|
||||
let pxv_item = self.get_edittree(idx as usize);
|
||||
let pxv_height = pxv_item.read().unwrap().get_height(&TreeHeightOp::P);
|
||||
|
||||
if gravity && pxv_height > 1 {
|
||||
|
@ -325,10 +328,7 @@ impl TreeNav for ListEditor {
|
|||
// nested
|
||||
|
||||
if cur.tree_addr[0] < self.data.len() as isize {
|
||||
|
||||
let cur_item = self.data
|
||||
.get_mut(cur.tree_addr[0] as usize);
|
||||
|
||||
let cur_item = self.get_edittree(cur.tree_addr[0] as usize);
|
||||
let result = cur_item.write().unwrap().goby(direction);
|
||||
|
||||
match result
|
||||
|
@ -354,8 +354,7 @@ impl TreeNav for ListEditor {
|
|||
let mut new_addr = Vec::new();
|
||||
|
||||
if direction.x < 0 {
|
||||
let pxv_item = self.data
|
||||
.get_mut(cur.tree_addr[0] as usize - 1);
|
||||
let pxv_item = self.get_edittree(cur.tree_addr[0] as usize - 1);
|
||||
|
||||
let pxv_height = pxv_item.read().unwrap().get_height(&TreeHeightOp::Q) as isize;
|
||||
let cur_height = cur_item.read().unwrap().get_height(&TreeHeightOp::P) as isize;
|
||||
|
@ -367,15 +366,13 @@ impl TreeNav for ListEditor {
|
|||
depth as isize - 1
|
||||
};
|
||||
|
||||
eprintln!("<- LEFT CROSS: pxv_height = {}, cur_height = {}, dist_from_ground = {}, n_steps_down = {}", pxv_height, cur_height, dist_from_ground, n_steps_down);
|
||||
new_addr.push( cur.tree_addr[0] - 1 );
|
||||
for _i in 0..n_steps_down {
|
||||
new_addr.push( -1 );
|
||||
}
|
||||
|
||||
} else {
|
||||
let nxd_item = self.data
|
||||
.get_mut(cur.tree_addr[0] as usize + 1);
|
||||
let nxd_item = self.get_edittree(cur.tree_addr[0] as usize + 1);
|
||||
|
||||
let cur_height = cur_item.read().unwrap().get_height(&TreeHeightOp::Q) as isize;
|
||||
let nxd_height = nxd_item.read().unwrap().get_height(&TreeHeightOp::P) as isize;
|
||||
|
@ -387,7 +384,6 @@ impl TreeNav for ListEditor {
|
|||
depth as isize - 1
|
||||
};
|
||||
|
||||
eprintln!("-> RIGHT CROSS: cur_height = {}, nxd_height = {}, dist_from_ground = {}, n_steps_down = {}", cur_height, nxd_height, dist_from_ground, n_steps_down);
|
||||
new_addr.push( cur.tree_addr[0] + 1 );
|
||||
for _i in 0..n_steps_down {
|
||||
new_addr.push( 0 );
|
||||
|
@ -396,7 +392,6 @@ impl TreeNav for ListEditor {
|
|||
|
||||
drop(cur_item);
|
||||
|
||||
eprintln!("CROSS: goto {:?}", new_addr);
|
||||
cur.tree_addr = new_addr;
|
||||
self.goto(cur)
|
||||
} else {
|
||||
|
@ -426,4 +421,3 @@ impl TreeNav for ListEditor {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,10 +9,7 @@ use {
|
|||
},
|
||||
crate::{
|
||||
editors::list::{ListCursor, ListCursorMode},
|
||||
terminal::{TerminalView, TerminalStyle, make_label},
|
||||
tree::{NestedNode, TreeNav},
|
||||
utils::color::{bg_style_from_depth, fg_style_from_depth},
|
||||
PtySegment
|
||||
edit_tree::{EditTree}
|
||||
},
|
||||
std::sync::Arc,
|
||||
std::sync::RwLock,
|
||||
|
@ -21,46 +18,13 @@ use {
|
|||
pub enum ListSegment {
|
||||
InsertCursor,
|
||||
Item {
|
||||
editor: NestedNode,
|
||||
editor: EditTree,
|
||||
cur_dist: isize,
|
||||
}
|
||||
}
|
||||
|
||||
impl PtySegment for ListSegment {
|
||||
fn pty_view(&self) -> OuterViewPort<dyn TerminalView> {
|
||||
match self {
|
||||
ListSegment::InsertCursor => {
|
||||
make_label("|")
|
||||
.map_item(move |_pt, atom| {
|
||||
atom.add_style_front(TerminalStyle::fg_color((150,80,230)))
|
||||
.add_style_front(TerminalStyle::bold(true))
|
||||
})
|
||||
}
|
||||
ListSegment::Item{ editor, cur_dist } => {
|
||||
let e = editor.clone();
|
||||
let cur_dist = *cur_dist;
|
||||
editor.get_view().map_item(move |_pt, atom| {
|
||||
let c = e.get_cursor();
|
||||
let cur_depth = c.tree_addr.len();
|
||||
let select =
|
||||
if cur_dist == 0 {
|
||||
cur_depth
|
||||
} else {
|
||||
usize::MAX
|
||||
};
|
||||
|
||||
atom
|
||||
.add_style_back(bg_style_from_depth(select))
|
||||
.add_style_back(TerminalStyle::bold(select==1))
|
||||
.add_style_back(fg_style_from_depth(e.depth.get_view().get()))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ListSegmentSequence {
|
||||
data: Arc<dyn SequenceView<Item = NestedNode>>,
|
||||
data: Arc<dyn SequenceView<Item = EditTree>>,
|
||||
cursor: Arc<dyn SingletonView<Item = ListCursor>>,
|
||||
|
||||
cur_cursor: ListCursor,
|
||||
|
@ -78,11 +42,12 @@ impl SequenceView for ListSegmentSequence {
|
|||
type Item = ListSegment;
|
||||
|
||||
fn len(&self) -> Option<usize> {
|
||||
let l = self.data.len()?;
|
||||
match self.cur_cursor.mode {
|
||||
ListCursorMode::Insert => {
|
||||
Some(self.data.len()? + if self.cur_cursor.idx.is_some() { 1 } else { 0 })
|
||||
Some(l + if self.cur_cursor.idx.is_some() { 1 } else { 0 })
|
||||
}
|
||||
_ => self.data.len(),
|
||||
_ => Some(l),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +89,7 @@ impl SequenceView for ListSegmentSequence {
|
|||
impl ListSegmentSequence {
|
||||
pub fn new(
|
||||
cursor_port: OuterViewPort<dyn SingletonView<Item = ListCursor>>,
|
||||
data_port: OuterViewPort<dyn SequenceView<Item = NestedNode>>,
|
||||
data_port: OuterViewPort<dyn SequenceView<Item = EditTree>>,
|
||||
) -> Arc<RwLock<Self>> {
|
||||
let out_port = ViewPort::new();
|
||||
let mut proj_helper = ProjectionHelper::new(out_port.update_hooks.clone());
|
|
@ -1,4 +1,14 @@
|
|||
|
||||
pub mod list;
|
||||
//pub mod product;
|
||||
//pub mod sum;
|
||||
|
||||
pub mod char;
|
||||
pub mod digit;
|
||||
pub mod integer;
|
||||
//pub mod typeterm;
|
||||
|
||||
|
||||
pub trait Commander {
|
||||
type Cmd;
|
||||
|
||||
|
@ -7,11 +17,12 @@ pub trait Commander {
|
|||
|
||||
use std::sync::{Arc, RwLock};
|
||||
use crate::{
|
||||
type_system::ReprTree,
|
||||
tree::{nav::TreeNavResult}
|
||||
repr_tree::ReprTree,
|
||||
edit_tree::nav::TreeNavResult
|
||||
};
|
||||
|
||||
pub trait ObjCommander {
|
||||
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult;
|
||||
}
|
||||
|
||||
|
|
@ -12,10 +12,6 @@ use {
|
|||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context},
|
||||
terminal::{
|
||||
TerminalEditor, TerminalEditorResult,
|
||||
TerminalEvent, TerminalView
|
||||
},
|
||||
editors::{
|
||||
list::ListCursorMode,
|
||||
product::{
|
|
@ -8,14 +8,9 @@ use {
|
|||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
terminal::TerminalView,
|
||||
editors::list::ListCursorMode,
|
||||
type_system::{Context, ReprTree},
|
||||
tree::{TreeNav, TreeCursor, TreeNavResult},
|
||||
diagnostics::{Diagnostics, Message},
|
||||
tree::NestedNode,
|
||||
commander::{ObjCommander},
|
||||
PtySegment
|
||||
editors::{list::ListCursorMode, ObjCommander},
|
||||
repr_tree::{Context, ReprTree},
|
||||
edit_tree::{TreeNav, TreeCursor, TreeNavResult, diagnostics::{Diagnostics, Message}, NestedNode},
|
||||
},
|
||||
cgmath::{Vector2},
|
||||
std::sync::{Arc, RwLock}
|
||||
|
@ -28,7 +23,7 @@ pub struct SumEditor {
|
|||
addr_port: ViewPort< dyn SequenceView<Item = isize> >,
|
||||
mode_port: ViewPort< dyn SingletonView<Item = ListCursorMode> >,
|
||||
|
||||
port: ViewPort< dyn TerminalView >,
|
||||
// port: ViewPort< dyn TerminalView >,
|
||||
diag_port: ViewPort< dyn SequenceView<Item = Message> >
|
||||
}
|
||||
|
||||
|
@ -36,12 +31,12 @@ impl SumEditor {
|
|||
pub fn new(
|
||||
editors: Vec< NestedNode >
|
||||
) -> Self {
|
||||
let port = ViewPort::new();
|
||||
// let port = ViewPort::new();
|
||||
|
||||
SumEditor {
|
||||
cur: 0,
|
||||
editors,
|
||||
port,
|
||||
// port,
|
||||
diag_port: ViewPort::new(),
|
||||
|
||||
|
||||
|
@ -55,15 +50,15 @@ impl SumEditor {
|
|||
}
|
||||
|
||||
pub fn into_node(self, ctx: Arc<RwLock<Context>>) -> NestedNode {
|
||||
let view = self.pty_view();
|
||||
// let view = self.pty_view();
|
||||
let editor = Arc::new(RwLock::new(self));
|
||||
|
||||
NestedNode::new(
|
||||
ctx.clone(),
|
||||
ReprTree::new_arc(TypeTerm::TypeID(ctx.read().unwrap().get_typeid("Sum").unwrap())),
|
||||
// ReprTree::new_arc(TypeTerm::TypeID(ctx.read().unwrap().get_typeid("Sum").unwrap())),
|
||||
r3vi::buffer::singleton::SingletonBuffer::new(0).get_port()
|
||||
)
|
||||
.set_view(view)
|
||||
// .set_view(view)
|
||||
.set_editor(editor.clone())
|
||||
.set_cmd(editor.clone())
|
||||
.set_nav(editor.clone())
|
||||
|
@ -76,6 +71,7 @@ impl SumEditor {
|
|||
|
||||
pub fn select(&mut self, idx: usize) {
|
||||
self.cur = idx;
|
||||
/* FIXME
|
||||
|
||||
let tv = self.editors[ self.cur ].get_view();
|
||||
tv.add_observer( self.port.get_cast() );
|
||||
|
@ -100,6 +96,7 @@ impl SumEditor {
|
|||
self.mode_port.update_hooks.write().unwrap().clear();
|
||||
self.mode_port.add_update_hook( Arc::new(dv.0.clone()) );
|
||||
self.mode_port.set_view( Some(dv.get_view_arc()) );
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,12 +126,6 @@ impl TreeNav for SumEditor {
|
|||
}
|
||||
}
|
||||
|
||||
impl PtySegment for SumEditor {
|
||||
fn pty_view(&self) -> OuterViewPort<dyn TerminalView> {
|
||||
self.port.outer()
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjCommander for SumEditor {
|
||||
fn send_cmd_obj(&mut self, obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
|
||||
self.editors[ self.cur ].send_cmd_obj( obj )
|
|
@ -3,10 +3,9 @@ use {
|
|||
view::{singleton::*}
|
||||
},
|
||||
crate::{
|
||||
type_system::{Context, ReprTree},
|
||||
editors::{list::{ListEditor, ListCmd, ListCursorMode}},
|
||||
tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
|
||||
commander::ObjCommander
|
||||
repr_tree::{Context, ReprTree},
|
||||
edit_tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
|
||||
editors::{list::{ListEditor, ListCmd, ListCursorMode}, ObjCommander},
|
||||
},
|
||||
std::{sync::{Arc, RwLock}},
|
||||
|
||||
|
@ -241,7 +240,6 @@ impl ObjCommander for TypeTermEditor {
|
|||
self.set_state( State::Ladder );
|
||||
}
|
||||
} else {
|
||||
eprintln!("ERROR");
|
||||
}
|
||||
} else {
|
||||
self.set_state( State::AnySymbol );
|
|
@ -4,13 +4,11 @@ use {
|
|||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context, MorphismTypePattern},
|
||||
terminal::{TerminalStyle, TerminalProjections},
|
||||
repr_tree::{Context, MorphismType},
|
||||
editors::{
|
||||
list::{PTYListStyle, PTYListController, ListEditor, ListSegmentSequence},
|
||||
list::{ListEditor, ListSegmentSequence},
|
||||
typeterm::{State, TypeTermEditor}
|
||||
},
|
||||
PtySegment
|
||||
}
|
||||
},
|
||||
std::{sync::{Arc, RwLock}},
|
||||
cgmath::{Point2}
|
||||
|
@ -27,8 +25,9 @@ pub fn init_ctx(ctx: &mut Context) {
|
|||
ctx.add_list_typename("Type::App".into()); // = <T1 T2 ...>
|
||||
ctx.add_list_typename("Type::Ladder".into()); // = T1~T2~...
|
||||
|
||||
/*
|
||||
ctx.add_morphism(
|
||||
MorphismTypePattern { src_tyid: ctx.get_typeid("List"), dst_tyid: ctx.get_typeid("Type").unwrap() },
|
||||
MorphismType { src_tyid: Context::parse(&ctx, "<List T>"), dst_tyid: Context::parse(&ctx, "Type") },
|
||||
Arc::new(move |node, _dst_type:_| {
|
||||
let ctx : Arc<RwLock<Context>> = Arc::new(RwLock::new(Context::with_parent(Some(node.ctx.clone()))));
|
||||
ctx.write().unwrap().meta_chars.push('~');
|
||||
|
@ -36,7 +35,8 @@ pub fn init_ctx(ctx: &mut Context) {
|
|||
let new_node = TypeTermEditor::with_node( ctx, node.clone(), State::Any );
|
||||
Some(new_node)
|
||||
}));
|
||||
|
||||
*/
|
||||
/*
|
||||
ctx.add_morphism(
|
||||
MorphismTypePattern { src_tyid: ctx.get_typeid("List"), dst_tyid: ctx.get_typeid("Type::Ladder").unwrap() },
|
||||
Arc::new(|mut node, _dst_type: _| {
|
||||
|
@ -140,5 +140,6 @@ pub fn init_ctx(ctx: &mut Context) {
|
|||
|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
|
||||
Some(TypeTermEditor::new_node(ctx, depth))
|
||||
}));
|
||||
*/
|
||||
}
|
||||
|
|
@ -11,10 +11,9 @@ use {
|
|||
},
|
||||
laddertypes::{TypeID, TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context, ReprTree},
|
||||
editors::{list::{ListCursorMode, ListEditor, ListCmd}},
|
||||
tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
|
||||
commander::ObjCommander
|
||||
repr_tree::{Context, ReprTree},
|
||||
edit_tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
|
||||
editors::{list::{ListCursorMode, ListEditor, ListCmd}, ObjCommander},
|
||||
},
|
||||
std::{sync::{Arc, RwLock}}
|
||||
};
|
||||
|
@ -169,8 +168,8 @@ impl TypeTermEditor {
|
|||
|
||||
node.goto(TreeCursor::home());
|
||||
|
||||
let _editor = node.editor.get();
|
||||
self.close_char.set(node.close_char.get());
|
||||
let _editor = node.edit.editor.get();
|
||||
self.close_char.set(node.edit.close_char.get());
|
||||
self.cur_node.set(node);
|
||||
self.state = new_state;
|
||||
}
|
||||
|
@ -205,9 +204,9 @@ impl TypeTermEditor {
|
|||
cur_node: SingletonBuffer::new(cur_node.clone()),
|
||||
close_char: SingletonBuffer::new(None),
|
||||
spillbuf: Arc::new(RwLock::new(Vec::new())),
|
||||
depth: cur_node.depth.clone()
|
||||
depth: cur_node.disp.depth.clone()
|
||||
};
|
||||
|
||||
/* FIXME
|
||||
let view = editor.cur_node
|
||||
.get_port()
|
||||
.map(|node| {
|
||||
|
@ -215,24 +214,25 @@ impl TypeTermEditor {
|
|||
})
|
||||
.to_grid()
|
||||
.flatten();
|
||||
let _cc = editor.cur_node.get().close_char;
|
||||
*/
|
||||
let _cc = editor.cur_node.get().edit.close_char;
|
||||
let editor = Arc::new(RwLock::new(editor));
|
||||
|
||||
let mut super_node = NestedNode::new(ctx, data, cur_node.depth)
|
||||
.set_view(view)
|
||||
let mut super_node = NestedNode::new(ctx, data, cur_node.disp.depth)
|
||||
// .set_view(view)
|
||||
.set_nav(editor.clone())
|
||||
.set_cmd(editor.clone())
|
||||
.set_editor(editor.clone());
|
||||
|
||||
editor.write().unwrap().close_char = super_node.close_char.clone();
|
||||
super_node.spillbuf = editor.read().unwrap().spillbuf.clone();
|
||||
editor.write().unwrap().close_char = super_node.edit.close_char.clone();
|
||||
super_node.edit.spillbuf = editor.read().unwrap().spillbuf.clone();
|
||||
|
||||
super_node
|
||||
}
|
||||
|
||||
fn forward_spill(&mut self) {
|
||||
let node = self.cur_node.get();
|
||||
let mut buf = node.spillbuf.write().unwrap();
|
||||
let mut buf = node.edit.spillbuf.write().unwrap();
|
||||
for n in buf.iter() {
|
||||
self.spillbuf.write().unwrap().push(n.clone());
|
||||
}
|
||||
|
@ -285,7 +285,6 @@ impl TypeTermEditor {
|
|||
}
|
||||
|
||||
pub fn normalize_empty(&mut self) {
|
||||
eprintln!("normalize singleton");
|
||||
let subladder_list_node = self.cur_node.get().clone();
|
||||
let subladder_list_edit = subladder_list_node.get_edit::<ListEditor>().unwrap();
|
||||
|
||||
|
@ -298,7 +297,6 @@ impl TypeTermEditor {
|
|||
/* unwrap a ladder if it only contains one element
|
||||
*/
|
||||
pub fn normalize_singleton(&mut self) {
|
||||
eprintln!("normalize singleton");
|
||||
|
||||
if self.state == State::Ladder {
|
||||
let subladder_list_node = self.cur_node.get().clone();
|
||||
|
@ -362,7 +360,6 @@ impl TypeTermEditor {
|
|||
/* replace with new list-node (ladder/app) with self as first element
|
||||
*/
|
||||
pub(super) fn morph_to_list(&mut self, state: State) {
|
||||
eprintln!("morph into ladder");
|
||||
|
||||
let mut old_node = self.cur_node.get().clone();
|
||||
|
||||
|
@ -374,7 +371,7 @@ impl TypeTermEditor {
|
|||
* that has same state & child-node as current node.
|
||||
*/
|
||||
let old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), SingletonBuffer::new(0).get_port() );
|
||||
old_node.depth.0.set_view( old_edit_node.depth.map(|x|x).get_view() );
|
||||
old_node.disp.depth.0.set_view( old_edit_node.disp.depth.map(|x|x).get_view() );
|
||||
|
||||
let old_edit_clone = old_edit_node.get_edit::<TypeTermEditor>().unwrap();
|
||||
old_edit_clone.write().unwrap().set_state( self.state );
|
|
@ -7,7 +7,7 @@ use {
|
|||
}
|
||||
},
|
||||
crate::{
|
||||
tree::{TreeNav, TreeCursor, TreeNavResult, TreeHeightOp},
|
||||
edit_tree::{TreeNav, TreeCursor, TreeNavResult, TreeHeightOp},
|
||||
editors::{typeterm::TypeTermEditor, list::ListCursorMode}
|
||||
},
|
||||
cgmath::Vector2
|
8
lib-nested-core/src/lib.rs
Normal file
8
lib-nested-core/src/lib.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
#![feature(trait_upcasting)]
|
||||
|
||||
pub mod repr_tree;
|
||||
pub mod edit_tree;
|
||||
pub mod editors;
|
||||
pub mod utils;
|
||||
|
279
lib-nested-core/src/repr_tree/context.rs
Normal file
279
lib-nested-core/src/repr_tree/context.rs
Normal file
|
@ -0,0 +1,279 @@
|
|||
use {
|
||||
crate::{
|
||||
edit_tree::EditTree,
|
||||
repr_tree::{GenericReprTreeMorphism, ReprTree, ReprTreeExt, ReprTreeArc},
|
||||
},
|
||||
laddertypes::{
|
||||
parser::ParseLadderType, sugar::SugaredTypeTerm, unparser::UnparseLadderType,
|
||||
BimapTypeDict, Morphism, MorphismBase, MorphismType, TypeDict, TypeID, TypeTerm,
|
||||
},
|
||||
r3vi::{
|
||||
buffer::singleton::*,
|
||||
view::{singleton::*, OuterViewPort},
|
||||
},
|
||||
std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, RwLock},
|
||||
}
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub static TYPEID_edittree : TypeID = TypeID::Fun(0);
|
||||
pub static TYPEID_char : TypeID = TypeID::Fun(1);
|
||||
pub static TYPEID_u64 : TypeID = TypeID::Fun(2);
|
||||
pub static TYPEID_list : TypeID = TypeID::Fun(3);
|
||||
pub static TYPEID_vec : TypeID = TypeID::Fun(4);
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Context {
|
||||
/// assigns a name to every type
|
||||
pub type_dict: Arc<RwLock<BimapTypeDict>>,
|
||||
|
||||
pub morphisms: laddertypes::morphism::MorphismBase< GenericReprTreeMorphism >,
|
||||
|
||||
/// named vertices of the graph
|
||||
nodes: HashMap< String, Arc<RwLock<ReprTree>> >,
|
||||
|
||||
/// todo: beautify
|
||||
/// types that can be edited as lists
|
||||
/// do we really need this?
|
||||
pub list_types: Vec< TypeID >,
|
||||
pub meta_chars: Vec< char >,
|
||||
|
||||
edittree_hook: Arc< dyn Fn(&mut EditTree, TypeTerm) + Send +Sync +'static >,
|
||||
|
||||
/// recursion
|
||||
parent: Option<Arc<RwLock<Context>>>,
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl Context {
|
||||
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_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))
|
||||
}
|
||||
},
|
||||
morphisms: MorphismBase::new( TYPEID_list ),
|
||||
nodes: HashMap::new(),
|
||||
list_types: match parent.as_ref() {
|
||||
Some(p) => p.read().unwrap().list_types.clone(),
|
||||
None => Vec::new()
|
||||
},
|
||||
meta_chars: match parent.as_ref() {
|
||||
Some(p) => p.read().unwrap().meta_chars.clone(),
|
||||
None => Vec::new()
|
||||
},
|
||||
parent,
|
||||
edittree_hook: Arc::new(|_et, _t| {})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
Context::with_parent(None)
|
||||
}
|
||||
|
||||
pub fn set_edittree_hook(&mut self, hook: Arc< dyn Fn(&mut EditTree, TypeTerm) + Send +Sync +'static >) {
|
||||
self.edittree_hook = hook;
|
||||
}
|
||||
|
||||
pub fn depth(&self) -> usize {
|
||||
if let Some(parent) = self.parent.as_ref() {
|
||||
parent.read().unwrap().depth() + 1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_morphism( &self, rt: &Arc<RwLock<ReprTree>>, ty: &MorphismType ) {
|
||||
if let Some(path)
|
||||
= self.morphisms.find_morphism_path( ty.clone().normalize() )
|
||||
{
|
||||
let mut path = path.into_iter();
|
||||
if let Some(mut src_type) = path.next() {
|
||||
for dst_type in path {
|
||||
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 {
|
||||
eprintln!("no path found");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_repr_tree(
|
||||
&self,
|
||||
rt: &Arc<RwLock<ReprTree>>,
|
||||
root: TypeTerm,
|
||||
leaves: Vec< TypeTerm >
|
||||
) {
|
||||
let mut st_problem = laddertypes::steiner_tree::PathApproxSteinerTreeSolver::new(
|
||||
root,
|
||||
leaves
|
||||
);
|
||||
|
||||
if let Some( steiner_tree ) = st_problem.solve( &self.morphisms ) {
|
||||
for morphism_type in steiner_tree.into_edges() {
|
||||
eprintln!("--> apply morph to {}", self.type_term_to_str(&morphism_type.dst_type));
|
||||
if let Some(( morphism, mut τ, σ )) =
|
||||
self.morphisms.find_morphism_with_subtyping( &morphism_type )
|
||||
{
|
||||
let mut rt = rt.descend( τ ).expect("descend src repr");
|
||||
(morphism.setup_projection)( &mut rt, &σ );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eprintln!("could not find steiner tree to build the requested repr tree");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_repr(ctx: &Arc<RwLock<Self>>, t: &TypeTerm) -> ReprTreeArc {
|
||||
let rt = Arc::new(RwLock::new(ReprTree::new( TypeTerm::unit() )));
|
||||
ctx.write().unwrap().apply_morphism( &rt, &MorphismType{ src_type: TypeTerm::unit(), dst_type: t.clone() } );
|
||||
rt
|
||||
}
|
||||
|
||||
pub fn parse(ctx: &Arc<RwLock<Self>>, s: &str) -> TypeTerm {
|
||||
ctx.read().unwrap().type_term_from_str(s).expect("could not parse type term")
|
||||
}
|
||||
|
||||
pub fn add_typename(&mut self, tn: &str) -> TypeID {
|
||||
self.type_dict.write().unwrap().add_typename(tn.to_string())
|
||||
}
|
||||
|
||||
pub fn add_varname(&mut self, vn: &str) -> TypeID {
|
||||
self.type_dict.write().unwrap().add_varname(vn.to_string())
|
||||
}
|
||||
|
||||
pub fn add_synonym(&mut self, new: &str, old: &str) {
|
||||
self.type_dict.write().unwrap().add_synonym(new.to_string(), old.to_string());
|
||||
}
|
||||
|
||||
pub fn add_list_typename(&mut self, tn: &str) {
|
||||
let tid = self.add_typename(tn);
|
||||
self.list_types.push( tid );
|
||||
}
|
||||
|
||||
pub fn is_list_type(&self, t: &TypeTerm) -> bool {
|
||||
match t {
|
||||
TypeTerm::TypeID(id) => {
|
||||
self.list_types.contains(id)
|
||||
}
|
||||
TypeTerm::Ladder(args) |
|
||||
TypeTerm::App(args) => {
|
||||
if args.len() > 0 {
|
||||
if self.is_list_type(&args[0]) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_typeid(&self, tn: &str) -> Option<TypeID> {
|
||||
self.type_dict.read().unwrap().get_typeid(&tn.into())
|
||||
}
|
||||
|
||||
pub fn get_fun_typeid(&self, tn: &str) -> Option<u64> {
|
||||
match self.get_typeid(tn) {
|
||||
Some(TypeID::Fun(x)) => Some(x),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_typename(&self, tid: &TypeID) -> Option<String> {
|
||||
self.type_dict.read().unwrap().get_typename(tid)
|
||||
}
|
||||
|
||||
pub fn get_var_typeid(&self, tn: &str) -> Option<u64> {
|
||||
match self.get_typeid(tn) {
|
||||
Some(TypeID::Var(x)) => Some(x),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_term_from_str(&self, tn: &str) -> Result<TypeTerm, laddertypes::parser::ParseError> {
|
||||
self.type_dict.write().unwrap().parse(&tn)
|
||||
}
|
||||
|
||||
pub fn type_term_to_str(&self, t: &TypeTerm) -> String {
|
||||
self.type_dict.read().unwrap().unparse(&t)
|
||||
}
|
||||
|
||||
/// adds an object without any representations
|
||||
pub fn add_obj(ctx: Arc<RwLock<Context>>, name: String, typename: &str) {
|
||||
let type_tag = ctx.read().unwrap()
|
||||
.type_dict.write().unwrap()
|
||||
.parse(typename).unwrap();
|
||||
/*
|
||||
if let Some(node) = Context::make_node(&ctx, type_tag, SingletonBuffer::new(0).get_port()) {
|
||||
ctx.write().unwrap().nodes.insert(name, node);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
pub fn get_obj(&self, name: &String) -> Option< ReprTreeArc > {
|
||||
if let Some(obj) = self.nodes.get(name) {
|
||||
Some(obj.clone())
|
||||
} else if let Some(parent) = self.parent.as_ref() {
|
||||
parent.read().unwrap().get_obj(name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_edittree(
|
||||
&self,
|
||||
rt: &Arc<RwLock<ReprTree>>
|
||||
) -> Option<SingletonBuffer<Arc<RwLock<EditTree>>>> {
|
||||
if let Some(new_edittree) =
|
||||
rt.descend(self.type_term_from_str("EditTree").unwrap())
|
||||
{
|
||||
let typ = rt.read().unwrap().get_type().clone();
|
||||
let buf = new_edittree.singleton_buffer::<Arc<RwLock<EditTree>>>();
|
||||
(*self.edittree_hook)(
|
||||
&mut *buf.get().write().unwrap(),
|
||||
typ
|
||||
);
|
||||
Some(buf)
|
||||
} else {
|
||||
eprintln!("cant find edit tree repr {} ~Ψ~ {}",
|
||||
self.type_term_to_str(rt.read().unwrap().get_halo_type()),
|
||||
self.type_term_to_str(rt.read().unwrap().get_type())
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
216
lib-nested-core/src/repr_tree/leaf.rs
Normal file
216
lib-nested-core/src/repr_tree/leaf.rs
Normal file
|
@ -0,0 +1,216 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{
|
||||
ViewPort, OuterViewPort,
|
||||
AnyViewPort, AnyInnerViewPort, AnyOuterViewPort,
|
||||
port::UpdateTask,
|
||||
View, Observer,
|
||||
singleton::*,
|
||||
sequence::*,
|
||||
list::*
|
||||
},
|
||||
buffer::{singleton::*, vec::*}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, RwLock},
|
||||
any::Any
|
||||
},
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ReprLeaf {
|
||||
out_port: AnyViewPort,
|
||||
in_port: AnyInnerViewPort,
|
||||
data: Option< Arc<dyn Any + Send + Sync> >,
|
||||
|
||||
/// keepalive for the observer that updates the buffer from in_port
|
||||
keepalive: Option<Arc<dyn Any + Send + Sync>>,
|
||||
in_keepalive: Option<Arc<dyn Any + Send + Sync>>,
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl ReprLeaf {
|
||||
pub fn from_view<V>( src_port: OuterViewPort<V> ) -> Self
|
||||
where V: View + ?Sized + 'static,
|
||||
V::Msg: Clone
|
||||
{
|
||||
let mut in_port = ViewPort::<V>::new();
|
||||
let in_keepalive = in_port.attach_to(src_port);
|
||||
|
||||
let mut out_port = ViewPort::<V>::new();
|
||||
let out_keepalive = out_port.attach_to(in_port.outer());
|
||||
|
||||
ReprLeaf {
|
||||
keepalive: Some(out_keepalive),
|
||||
in_keepalive: Some(in_keepalive),
|
||||
in_port: in_port.inner().into(),
|
||||
out_port: out_port.into(),
|
||||
data: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn detach<V>(&mut self)
|
||||
where V: View + ?Sized + 'static,
|
||||
V::Msg: Clone
|
||||
{
|
||||
self.keepalive = None;
|
||||
self.in_keepalive = None;
|
||||
|
||||
let ip = self.in_port.clone()
|
||||
.downcast::<V>().ok()
|
||||
.unwrap();
|
||||
ip.0.detach();
|
||||
|
||||
if self.data.is_none() {
|
||||
let mut op = self.out_port.clone()
|
||||
.downcast::<V>().ok()
|
||||
.unwrap();
|
||||
|
||||
op.detach();
|
||||
self.keepalive = Some(op.attach_to(ip.0.outer()));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn detach_vec<Item>(&mut self)
|
||||
where Item: Clone + Send + Sync + 'static
|
||||
{
|
||||
self.keepalive = None;
|
||||
self.in_keepalive = None;
|
||||
|
||||
let ip = self.in_port.clone()
|
||||
.downcast::<dyn ListView<Item>>().ok()
|
||||
.unwrap();
|
||||
|
||||
ip.0.detach();
|
||||
|
||||
if let Some(data) = self.data.as_mut() {
|
||||
let mut op = self.out_port.clone()
|
||||
.downcast::<RwLock<Vec<Item>>>().ok()
|
||||
.unwrap();
|
||||
op.detach();
|
||||
|
||||
let data = data.clone().downcast::< RwLock<Vec<Item>> >().ok().unwrap();
|
||||
let buffer = VecBuffer::with_data_arc_port(data, op.inner());
|
||||
self.keepalive = Some(buffer.attach_to(ip.0.outer()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attach_to<V>(&mut self, src_port: OuterViewPort<V>)
|
||||
where V: View + ?Sized + 'static,
|
||||
V::Msg: Clone
|
||||
{
|
||||
self.in_keepalive = Some(self.in_port.clone()
|
||||
.downcast::<V>().ok().unwrap()
|
||||
.0.attach_to( src_port ));
|
||||
}
|
||||
|
||||
pub fn from_singleton_buffer<T>( buffer: SingletonBuffer<T> ) -> Self
|
||||
where T: Clone + Send + Sync + 'static
|
||||
{
|
||||
let in_port = ViewPort::<dyn SingletonView<Item = T>>::new();
|
||||
ReprLeaf {
|
||||
in_keepalive: None,
|
||||
keepalive: Some(buffer.attach_to(in_port.outer())),
|
||||
in_port: in_port.inner().into(),
|
||||
out_port: buffer.get_port().0.into(),
|
||||
data: Some(buffer.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_vec_buffer<T>( buffer: VecBuffer<T> ) -> Self
|
||||
where T: Clone + Send + Sync + 'static
|
||||
{
|
||||
let in_port = ViewPort::< dyn ListView<T> >::new();
|
||||
ReprLeaf {
|
||||
in_keepalive: None,
|
||||
keepalive: Some(buffer.attach_to(in_port.outer())),
|
||||
in_port: in_port.inner().into(),
|
||||
out_port: buffer.get_port().0.into(),
|
||||
data: Some(buffer.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_singleton_buffer<T>(&mut self) -> Option<SingletonBuffer<T>>
|
||||
where T: Clone + Send + Sync + 'static
|
||||
{
|
||||
let sgl_port = self.get_port::< dyn SingletonView<Item = T> >().unwrap().0;
|
||||
|
||||
let data_arc =
|
||||
if let Some(data) = self.data.as_ref() {
|
||||
data.clone().downcast::<RwLock<T>>().ok()
|
||||
} else {
|
||||
sgl_port.update();
|
||||
let value = sgl_port.outer().get_view().unwrap().get();
|
||||
eprintln!("make new data ARC from old value");
|
||||
Some(Arc::new(RwLock::new( value )))
|
||||
};
|
||||
|
||||
if let Some(data_arc) = data_arc {
|
||||
self.data = Some(data_arc.clone() as Arc<dyn Any + Send + Sync>);
|
||||
let buf = SingletonBuffer {
|
||||
value: data_arc,
|
||||
port: sgl_port.inner()
|
||||
};
|
||||
self.keepalive = Some(buf.attach_to(
|
||||
self.in_port.0.clone()
|
||||
.downcast::<dyn SingletonView<Item = T>>()
|
||||
.ok().unwrap()
|
||||
.outer()
|
||||
));
|
||||
Some(buf)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_vec_buffer<T>(&mut self) -> Option<VecBuffer<T>>
|
||||
where T: Clone + Send + Sync + 'static
|
||||
{
|
||||
let vec_port = self.get_port::< RwLock<Vec<T>> >().unwrap().0;
|
||||
|
||||
let data_arc =
|
||||
if let Some(data) = self.data.as_ref() {
|
||||
data.clone().downcast::<RwLock<Vec<T>>>().ok()
|
||||
} else {
|
||||
vec_port.update();
|
||||
if let Some(value) = vec_port.outer().get_view() {
|
||||
let value = value.read().unwrap().clone();
|
||||
eprintln!("make new data ARC from old VECTOR-value");
|
||||
Some(Arc::new(RwLock::new( value )))
|
||||
} else {
|
||||
eprintln!("no data vec");
|
||||
Some(Arc::new(RwLock::new( Vec::new() )))
|
||||
// None
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(data_arc) = data_arc {
|
||||
self.data = Some(data_arc.clone() as Arc<dyn Any + Send + Sync>);
|
||||
let buf = VecBuffer::with_data_arc_port(data_arc, vec_port.inner());
|
||||
self.keepalive = Some(buf.attach_to(
|
||||
self.in_port.0.clone()
|
||||
.downcast::< dyn ListView<T> >()
|
||||
.ok().unwrap()
|
||||
.outer()
|
||||
));
|
||||
Some(buf)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_port<V>(&self) -> Option<OuterViewPort<V>>
|
||||
where V: View + ?Sized + 'static,
|
||||
V::Msg: Clone
|
||||
{
|
||||
self.out_port.clone().downcast::<V>().ok().map(|p| p.outer())
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
150
lib-nested-core/src/repr_tree/mod.rs
Normal file
150
lib-nested-core/src/repr_tree/mod.rs
Normal file
|
@ -0,0 +1,150 @@
|
|||
pub mod node;
|
||||
pub mod leaf;
|
||||
pub mod context;
|
||||
pub mod morphism;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use {
|
||||
context::{Context},
|
||||
leaf::ReprLeaf,
|
||||
node::{ReprTree, ReprTreeArc},
|
||||
morphism::{GenericReprTreeMorphism}
|
||||
};
|
||||
|
||||
use {
|
||||
r3vi::{
|
||||
view::{
|
||||
ViewPort, OuterViewPort,
|
||||
AnyViewPort, AnyInnerViewPort, AnyOuterViewPort,
|
||||
port::UpdateTask,
|
||||
View, Observer,
|
||||
singleton::*,
|
||||
sequence::*,
|
||||
list::*
|
||||
},
|
||||
buffer::{singleton::*, vec::*}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, RwLock},
|
||||
any::Any
|
||||
},
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub trait ReprTreeExt {
|
||||
fn get_type(&self) -> TypeTerm;
|
||||
|
||||
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< ReprTreeArc >;
|
||||
fn descend_create(&self, ctx: &Arc<RwLock<Context>>, 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;
|
||||
|
||||
fn view_char(&self) -> OuterViewPort<dyn SingletonView<Item = char>>;
|
||||
fn view_u8(&self) -> OuterViewPort<dyn SingletonView<Item = u8>>;
|
||||
fn view_u64(&self) -> OuterViewPort<dyn SingletonView<Item = u64>>;
|
||||
fn view_usize(&self) -> OuterViewPort<dyn SingletonView<Item = usize>>;
|
||||
|
||||
fn view_singleton<T: Send + Sync + 'static>(&self) -> OuterViewPort<dyn SingletonView<Item = T>>;
|
||||
fn view_seq<T: Send + Sync + 'static>(&self) -> OuterViewPort<dyn SequenceView<Item = T>>;
|
||||
fn view_list<T: Clone + Send + Sync + 'static>(&self) -> OuterViewPort<dyn ListView<T>>;
|
||||
|
||||
fn singleton_buffer<T: Clone + Send + Sync + 'static>(&self) -> SingletonBuffer<T>;
|
||||
fn vec_buffer<T: Clone + Send + Sync + 'static>(&self) -> VecBuffer<T>;
|
||||
|
||||
fn edittree(&self, ctx: &Arc<RwLock<Context>>) -> SingletonBuffer< Arc<RwLock<crate::edit_tree::EditTree>> > {
|
||||
self.descend_create(&ctx, Context::parse(&ctx, "EditTree"))
|
||||
.expect("failed to get EditTree")
|
||||
.singleton_buffer()
|
||||
}
|
||||
}
|
||||
|
||||
impl ReprTreeExt for Arc<RwLock<ReprTree>> {
|
||||
fn get_type(&self) -> TypeTerm {
|
||||
self.read().unwrap().get_type().clone()
|
||||
}
|
||||
|
||||
fn insert_leaf(&mut self, type_ladder: impl Into<TypeTerm>, leaf: ReprLeaf) {
|
||||
self.write().unwrap().insert_leaf(type_ladder.into().get_lnf_vec().into_iter(), leaf)
|
||||
}
|
||||
|
||||
fn insert_branch(&mut self, repr: Arc<RwLock<ReprTree>>) {
|
||||
self.write().unwrap().insert_branch(repr)
|
||||
}
|
||||
|
||||
fn create_branch(&mut self, rung: impl Into<TypeTerm>) {
|
||||
let mut lnf = rung.into().get_lnf_vec().into_iter();
|
||||
if let Some(rung) = lnf.next() {
|
||||
let mut parent = ReprTree::new_arc( rung );
|
||||
self.insert_branch( parent.clone() );
|
||||
|
||||
for rung in lnf {
|
||||
let r = ReprTree::new_arc( rung );
|
||||
parent.insert_branch(r.clone());
|
||||
parent = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_port<V: View + ?Sized + 'static>(&self) -> Option<OuterViewPort<V>> where V::Msg: Clone {
|
||||
self.read().unwrap().get_port::<V>()
|
||||
}
|
||||
|
||||
fn attach_leaf_to<V: View + ?Sized + 'static>(&self, type_ladder: impl Into<TypeTerm>, v: OuterViewPort<V>) where V::Msg: Clone {
|
||||
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< ReprTreeArc > {
|
||||
ReprTree::descend( self, target_type )
|
||||
}
|
||||
|
||||
fn descend_create(&self, ctx: &Arc<RwLock<Context>>, target_type: impl Into<TypeTerm>)-> Option< ReprTreeArc > {
|
||||
ReprTree::descend_create( &ctx, &self, target_type )
|
||||
}
|
||||
|
||||
fn view_char(&self) -> OuterViewPort<dyn SingletonView<Item = char>> {
|
||||
self.read().unwrap().view_char()
|
||||
}
|
||||
|
||||
fn view_u8(&self) -> OuterViewPort<dyn SingletonView<Item = u8>> {
|
||||
self.read().unwrap().view_u8()
|
||||
}
|
||||
|
||||
fn view_u64(&self) -> OuterViewPort<dyn SingletonView<Item = u64>> {
|
||||
self.read().unwrap().view_u64()
|
||||
}
|
||||
|
||||
fn view_usize(&self) -> OuterViewPort<dyn SingletonView<Item = usize>> {
|
||||
self.read().unwrap().view_usize()
|
||||
}
|
||||
|
||||
fn view_singleton<T: Send + Sync + 'static>(&self) -> OuterViewPort<dyn SingletonView<Item = T>> {
|
||||
self.read().unwrap().view_singleton::<T>()
|
||||
}
|
||||
|
||||
fn view_seq<T: Send + Sync + 'static>(&self) -> OuterViewPort<dyn SequenceView<Item = T>> {
|
||||
self.read().unwrap().view_seq::<T>()
|
||||
}
|
||||
|
||||
fn view_list<T: Clone + Send + Sync + 'static>(&self) -> OuterViewPort<dyn ListView<T>> {
|
||||
self.read().unwrap().view_list::<T>()
|
||||
}
|
||||
|
||||
fn singleton_buffer<T: Clone + Send + Sync + 'static>(&self) -> SingletonBuffer<T> {
|
||||
self.write().unwrap().singleton_buffer::<T>().expect("")
|
||||
}
|
||||
|
||||
fn vec_buffer<T: Clone + Send + Sync + 'static>(&self) -> VecBuffer<T> {
|
||||
self.write().unwrap().vec_buffer::<T>().expect("")
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
211
lib-nested-core/src/repr_tree/morphism.rs
Normal file
211
lib-nested-core/src/repr_tree/morphism.rs
Normal file
|
@ -0,0 +1,211 @@
|
|||
use {
|
||||
laddertypes::{TypeTerm, TypeID, morphism::Morphism},
|
||||
r3vi::view::{AnyOuterViewPort, port::*, list::*},
|
||||
crate::{
|
||||
repr_tree::{
|
||||
ReprTree, ReprTreeExt, ReprLeaf,
|
||||
context::{*}
|
||||
},
|
||||
},
|
||||
std::{
|
||||
sync::{Arc, RwLock},
|
||||
collections::HashMap
|
||||
}
|
||||
};
|
||||
|
||||
pub use laddertypes::morphism::MorphismType;
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct GenericReprTreeMorphism {
|
||||
pub(super) morph_type: MorphismType,
|
||||
pub(super) setup_projection: Arc<
|
||||
dyn Fn( &mut Arc<RwLock<ReprTree>>, &HashMap<TypeID, TypeTerm> )
|
||||
// -> Result< ReprLeaf, () >
|
||||
+ Send + Sync
|
||||
>
|
||||
}
|
||||
|
||||
impl Morphism for GenericReprTreeMorphism {
|
||||
fn get_type(&self) -> MorphismType {
|
||||
self.morph_type.clone()
|
||||
}
|
||||
|
||||
fn list_map_morphism(&self, list_typeid: TypeID) -> Option< GenericReprTreeMorphism > {
|
||||
self.into_list_map_dyn(list_typeid)
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericReprTreeMorphism {
|
||||
pub fn new(
|
||||
src_type: TypeTerm,
|
||||
dst_type: TypeTerm,
|
||||
|
||||
setup: impl Fn( &mut Arc<RwLock<ReprTree>>, &HashMap<TypeID, TypeTerm> )
|
||||
+ Send + Sync + 'static
|
||||
) -> Self {
|
||||
GenericReprTreeMorphism {
|
||||
morph_type: MorphismType {
|
||||
src_type, dst_type
|
||||
}.normalize(),
|
||||
|
||||
setup_projection: Arc::new(setup)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_list_map< SrcItem, DstItem >(&self, list_typeid: TypeID)
|
||||
-> GenericReprTreeMorphism
|
||||
where
|
||||
SrcItem: Clone + Send + Sync + 'static,
|
||||
DstItem: Clone + Send + Sync + 'static
|
||||
{
|
||||
let mut lst_map_type = MorphismType {
|
||||
src_type: TypeTerm::App(vec![
|
||||
TypeTerm::TypeID(list_typeid),
|
||||
self.morph_type.src_type.clone()
|
||||
]),
|
||||
dst_type: TypeTerm::App(vec![
|
||||
TypeTerm::TypeID(list_typeid),
|
||||
self.morph_type.dst_type.clone()
|
||||
])
|
||||
}.normalize();
|
||||
|
||||
let item_morph = self.clone();
|
||||
|
||||
GenericReprTreeMorphism{
|
||||
morph_type: lst_map_type.clone(),
|
||||
setup_projection: Arc::new(move |repr_tree, subst| {
|
||||
let mut lst_map_type = lst_map_type.clone();
|
||||
lst_map_type.src_type.apply_substitution( &|x| subst.get(x).cloned() );
|
||||
lst_map_type.dst_type.apply_substitution( &|x| subst.get(x).cloned() );
|
||||
|
||||
lst_map_type = lst_map_type.normalize();
|
||||
|
||||
eprintln!(
|
||||
"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 top_type = item_ladder.remove( item_ladder.len() - 1 );
|
||||
|
||||
if let Ok(item_sigma) = laddertypes::unify(
|
||||
&top_type,
|
||||
&TypeTerm::App(vec![
|
||||
TypeTerm::TypeID( list_typeid ),
|
||||
TypeTerm::TypeID( TypeID::Var( 200 ) )
|
||||
])
|
||||
) {
|
||||
eprintln!("List OF List...");
|
||||
} else {
|
||||
let src_port = repr_tree
|
||||
.descend( lst_map_type.src_type.clone() )
|
||||
.expect("descend src seq")
|
||||
.view_list::<SrcItem>();
|
||||
|
||||
let subst = subst.clone();
|
||||
let item_morph = item_morph.clone();
|
||||
|
||||
let dst_view = src_port.map(
|
||||
move |x| {
|
||||
let mut item_rt = ReprTree::from_singleton_buffer(
|
||||
top_type.clone(),
|
||||
r3vi::buffer::singleton::SingletonBuffer::new(x.clone())
|
||||
);
|
||||
|
||||
|
||||
// TODO: required?
|
||||
for t in item_ladder.iter().rev() {
|
||||
let mut n = ReprTree::new_arc( t.clone() );
|
||||
n.insert_branch( item_rt );
|
||||
item_rt = n;
|
||||
}
|
||||
|
||||
(item_morph.setup_projection)( &mut item_rt, &subst );
|
||||
item_rt.descend( item_morph.morph_type.dst_type.clone() ).expect("descend to item rt")
|
||||
.view_singleton::< DstItem >()
|
||||
.get_view().unwrap()
|
||||
.get()
|
||||
});
|
||||
|
||||
|
||||
repr_tree.attach_leaf_to(
|
||||
lst_map_type.dst_type.clone(),
|
||||
dst_view as r3vi::view::OuterViewPort::< dyn r3vi::view::list::ListView<DstItem> >
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_list_map_dyn(&self, typeid_list: TypeID)
|
||||
-> Option< GenericReprTreeMorphism >
|
||||
{
|
||||
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();
|
||||
|
||||
eprintln!("into list map dyn");
|
||||
|
||||
if src_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) )
|
||||
}
|
||||
else if src_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) )
|
||||
}
|
||||
else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) &&
|
||||
dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_u64))
|
||||
{
|
||||
Some( self.into_list_map::< char, u64 >(TYPEID_list) )
|
||||
}
|
||||
else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_u64)) &&
|
||||
dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char))
|
||||
{
|
||||
Some( self.into_list_map::< u64, char >(TYPEID_list) )
|
||||
}
|
||||
else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) &&
|
||||
dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_edittree))
|
||||
{
|
||||
Some( self.into_list_map::< char, Arc<RwLock<crate::edit_tree::EditTree>> >(TYPEID_list) )
|
||||
}
|
||||
else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_edittree)) &&
|
||||
dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char))
|
||||
{
|
||||
Some( self.into_list_map::< Arc<RwLock<crate::edit_tree::EditTree>>, char >(TYPEID_list) )
|
||||
}
|
||||
/*
|
||||
else if src_item_type_lnf.last() == Some(&TypeTerm::App(vec![ TypeTerm::TypeID(typeid_list), TypeTerm::TypeID(typeid_char) ])) &&
|
||||
dst_item_type_lnf.last() == Some(&TypeTerm::App(vec![ TypeTerm::TypeID(typeid_list), TypeTerm::TypeID(typeid_char) ]))
|
||||
{
|
||||
Some( self.into_list_map::< char, char >(typeid_list) )
|
||||
}
|
||||
else if src_item_type_lnf.last() == Some(&TypeTerm::App(vec![ TypeTerm::TypeID(typeid_list), TypeTerm::TypeID(typeid_u64) ])) &&
|
||||
dst_item_type_lnf.last() == Some(&TypeTerm::App(vec![ TypeTerm::TypeID(typeid_list), TypeTerm::TypeID(typeid_u64) ]))
|
||||
{
|
||||
Some( self.into_list_map::< u64, u64 >(typeid_list) )
|
||||
}
|
||||
else if src_item_type_lnf.last() == Some(&TypeTerm::App(vec![ TypeTerm::TypeID(typeid_list), TypeTerm::TypeID(typeid_char) ])) &&
|
||||
dst_item_type_lnf.last() == Some(&TypeTerm::App(vec![ TypeTerm::TypeID(typeid_list), TypeTerm::TypeID(typeid_u64) ]))
|
||||
{
|
||||
Some( self.into_list_map::< OuterViewPort<dyn ListView<char>>, OuterViewPort<dyn ListView<u64>> >(typeid_list) )
|
||||
}
|
||||
else if src_item_type_lnf.last() == Some(&TypeTerm::App(vec![ TypeTerm::TypeID(typeid_list), TypeTerm::TypeID(typeid_u64) ])) &&
|
||||
dst_item_type_lnf.last() == Some(&TypeTerm::App(vec![ TypeTerm::TypeID(typeid_list), TypeTerm::TypeID(typeid_char) ]))
|
||||
{
|
||||
Some( self.into_list_map::< OuterViewPort<dyn ListView<u64>>, OuterViewPort<dyn ListView<char>> >(typeid_list) )
|
||||
}
|
||||
*/
|
||||
else
|
||||
{
|
||||
eprintln!("no list map type for {:?}", dst_item_type_lnf.last());
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
514
lib-nested-core/src/repr_tree/node.rs
Normal file
514
lib-nested-core/src/repr_tree/node.rs
Normal file
|
@ -0,0 +1,514 @@
|
|||
|
||||
|
||||
use {
|
||||
r3vi::{
|
||||
view::{
|
||||
ViewPort, OuterViewPort,
|
||||
AnyViewPort, AnyInnerViewPort, AnyOuterViewPort,
|
||||
port::UpdateTask,
|
||||
View, Observer,
|
||||
singleton::*,
|
||||
sequence::*,
|
||||
list::*
|
||||
},
|
||||
buffer::{singleton::*, vec::*}
|
||||
},
|
||||
laddertypes::{TypeTerm, TypeID},
|
||||
std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, RwLock},
|
||||
any::Any
|
||||
},
|
||||
super::{Context, ReprLeaf, ReprTreeExt, context::{TYPEID_list, TYPEID_vec, TYPEID_char, TYPEID_u64, TYPEID_edittree}}
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ReprTree {
|
||||
halo: TypeTerm,
|
||||
type_tag: TypeTerm,
|
||||
required_branches: Vec< TypeTerm >,
|
||||
branches: HashMap<TypeTerm, ReprTreeArc>,
|
||||
leaf: Option< ReprLeaf >
|
||||
}
|
||||
|
||||
pub type ReprTreeArc = Arc<RwLock<ReprTree>>;
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl std::fmt::Debug for ReprTree {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "| type: {:?}", self.type_tag)?;
|
||||
|
||||
for (_k,x) in self.branches.iter() {
|
||||
writeln!(f, "|--> child: {:?}", x)?;
|
||||
}
|
||||
writeln!(f, "");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl ReprTree {
|
||||
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)) );
|
||||
}
|
||||
|
||||
ReprTree {
|
||||
halo: TypeTerm::unit(),
|
||||
type_tag: head_type,
|
||||
required_branches: Vec::new(),
|
||||
branches,
|
||||
leaf: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_arc(type_tag: impl Into<TypeTerm>) -> ReprTreeArc {
|
||||
Arc::new(RwLock::new(Self::new(type_tag)))
|
||||
}
|
||||
|
||||
pub fn get_type(&self) -> &TypeTerm {
|
||||
&self.type_tag
|
||||
}
|
||||
|
||||
pub fn set_halo(&mut self, halo_type: impl Into<TypeTerm>) {
|
||||
self.halo = halo_type.into();
|
||||
for (branch_type, branch) in self.branches.iter() {
|
||||
branch.write().unwrap().set_halo( TypeTerm::Ladder(vec![
|
||||
self.halo.clone(),
|
||||
self.type_tag.clone()
|
||||
]).normalize()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_halo_type(&self) -> &TypeTerm {
|
||||
&self.halo
|
||||
}
|
||||
|
||||
pub fn get_leaf_types(&self) -> Vec< TypeTerm > {
|
||||
let mut leaf_types = Vec::new();
|
||||
if self.leaf.is_some() {
|
||||
leaf_types.push( self.get_type().clone() );
|
||||
}
|
||||
for (branch_type, branch) in self.branches.iter() {
|
||||
for t in branch.read().unwrap().get_leaf_types() {
|
||||
leaf_types.push(TypeTerm::Ladder(vec![
|
||||
self.get_type().clone(),
|
||||
t
|
||||
]).normalize())
|
||||
}
|
||||
}
|
||||
leaf_types
|
||||
}
|
||||
|
||||
pub fn insert_branch(&mut self, repr: ReprTreeArc) {
|
||||
let branch_type = repr.read().unwrap().get_type().clone();
|
||||
|
||||
assert!(branch_type.is_flat());
|
||||
|
||||
repr.write().unwrap().set_halo( TypeTerm::Ladder(vec![
|
||||
self.halo.clone(),
|
||||
self.type_tag.clone()
|
||||
]).normalize() );
|
||||
|
||||
self.branches.insert(branch_type, repr.clone());
|
||||
}
|
||||
|
||||
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> ) -> ReprTreeArc
|
||||
where V: View + ?Sized + 'static,
|
||||
V::Msg: Clone
|
||||
{
|
||||
let mut rt = ReprTree::new(type_tag);
|
||||
rt.leaf = Some(ReprLeaf::from_view(view));
|
||||
Arc::new(RwLock::new(rt))
|
||||
}
|
||||
|
||||
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);
|
||||
rt.leaf = Some(ReprLeaf::from_singleton_buffer(buf));
|
||||
Arc::new(RwLock::new(rt))
|
||||
}
|
||||
|
||||
pub fn from_str(
|
||||
type_tag: impl Into<TypeTerm>,
|
||||
val: &str
|
||||
) -> ReprTreeArc {
|
||||
let mut lnf = type_tag.into().get_lnf_vec();
|
||||
|
||||
let mut rt = ReprTree::from_vec_buffer(
|
||||
lnf.pop().unwrap(),
|
||||
VecBuffer::with_data( val.chars().collect() )
|
||||
);
|
||||
|
||||
while let Some(t) = lnf.pop() {
|
||||
let mut new_rt = ReprTree::new_arc(t);
|
||||
new_rt.insert_branch(rt);
|
||||
rt = new_rt;
|
||||
}
|
||||
|
||||
rt
|
||||
}
|
||||
|
||||
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);
|
||||
rt.leaf = Some(ReprLeaf::from_vec_buffer(buf));
|
||||
Arc::new(RwLock::new(rt))
|
||||
}
|
||||
|
||||
pub fn attach_to<V>(
|
||||
&mut self,
|
||||
src_port: OuterViewPort<V>
|
||||
)
|
||||
where V: View + ?Sized + 'static,
|
||||
V::Msg: Clone
|
||||
{
|
||||
if let Some(leaf) = self.leaf.as_mut() {
|
||||
leaf.attach_to(src_port);
|
||||
} else {
|
||||
eprintln!("cant attach branch without leaf");
|
||||
}
|
||||
}
|
||||
|
||||
/// find, and if necessary, create corresponding path in repr-tree.
|
||||
/// Attach src_port to input of that node
|
||||
pub fn attach_leaf_to<V>(
|
||||
&mut self,
|
||||
mut type_ladder: impl Iterator<Item = TypeTerm>,
|
||||
src_port: OuterViewPort<V>
|
||||
)
|
||||
where V: View + ?Sized + 'static,
|
||||
V::Msg: Clone
|
||||
{
|
||||
while let Some(rung_type) = type_ladder.next() {
|
||||
if &rung_type != self.get_type() {
|
||||
if let Some(next_repr) = self.branches.get(&rung_type) {
|
||||
next_repr.write().unwrap().attach_leaf_to(type_ladder, src_port);
|
||||
} else {
|
||||
let mut next_repr = ReprTree::new(rung_type.clone());
|
||||
next_repr.attach_leaf_to(type_ladder, src_port);
|
||||
self.insert_branch(Arc::new(RwLock::new(next_repr)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(leaf) = self.leaf.as_mut() {
|
||||
leaf.attach_to(src_port);
|
||||
} else {
|
||||
if self.type_tag == TypeTerm::App(vec![
|
||||
TypeTerm::TypeID(TYPEID_vec),
|
||||
TypeTerm::TypeID(TYPEID_edittree)
|
||||
]) {
|
||||
let mut leaf = ReprLeaf::from_vec_buffer(
|
||||
VecBuffer::<
|
||||
Arc<RwLock<crate::edit_tree::EditTree>>
|
||||
>::new()
|
||||
);
|
||||
|
||||
leaf.attach_to(src_port);
|
||||
self.leaf = Some(leaf);
|
||||
}
|
||||
else if self.type_tag == TypeTerm::App(vec![
|
||||
TypeTerm::TypeID(TYPEID_vec),
|
||||
TypeTerm::TypeID(TYPEID_char)
|
||||
]) {
|
||||
let mut leaf = ReprLeaf::from_vec_buffer(
|
||||
VecBuffer::<char>::new()
|
||||
);
|
||||
|
||||
leaf.attach_to(src_port);
|
||||
self.leaf = Some(leaf);
|
||||
}
|
||||
else if self.type_tag == TypeTerm::App(vec![
|
||||
TypeTerm::TypeID(TYPEID_vec),
|
||||
TypeTerm::TypeID(TYPEID_u64)
|
||||
]) {
|
||||
let mut leaf = ReprLeaf::from_vec_buffer(
|
||||
VecBuffer::<u64>::new()
|
||||
);
|
||||
|
||||
leaf.attach_to(src_port);
|
||||
self.leaf = Some(leaf);
|
||||
} else {
|
||||
self.leaf = Some(ReprLeaf::from_view(src_port));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn detach(&mut self, ctx: &Arc<RwLock<Context>>) {
|
||||
if let Some(leaf) = self.leaf.as_mut() {
|
||||
if self.type_tag ==
|
||||
TypeTerm::TypeID(TYPEID_edittree)
|
||||
{
|
||||
leaf.detach::< dyn SingletonView<
|
||||
Item = Arc<RwLock< crate::edit_tree::EditTree >>
|
||||
> >();
|
||||
}
|
||||
else if self.type_tag ==
|
||||
TypeTerm::TypeID(TYPEID_char)
|
||||
{
|
||||
leaf.detach::< dyn SingletonView<Item = char> >();
|
||||
}
|
||||
else if self.type_tag == TypeTerm::TypeID(TYPEID_u64)
|
||||
{
|
||||
leaf.detach::< dyn SingletonView<Item = u64> >();
|
||||
}
|
||||
else if self.type_tag == TypeTerm::App(vec![
|
||||
TypeTerm::TypeID(TYPEID_vec),
|
||||
TypeTerm::TypeID(TYPEID_edittree),
|
||||
]) {
|
||||
leaf.detach_vec::<
|
||||
Arc<RwLock< crate::edit_tree::EditTree >>
|
||||
>();
|
||||
}
|
||||
else if self.type_tag == TypeTerm::App(vec![
|
||||
TypeTerm::TypeID(TYPEID_vec),
|
||||
TypeTerm::TypeID(TYPEID_char),
|
||||
]) {
|
||||
leaf.detach_vec::< char >();
|
||||
}
|
||||
else if self.type_tag == TypeTerm::App(vec![
|
||||
TypeTerm::TypeID(TYPEID_vec),
|
||||
TypeTerm::TypeID(TYPEID_u64),
|
||||
]) {
|
||||
leaf.detach_vec::< u64 >();
|
||||
}
|
||||
else if self.type_tag == TypeTerm::App(vec![
|
||||
TypeTerm::TypeID(TYPEID_list),
|
||||
TypeTerm::TypeID(TYPEID_edittree),
|
||||
]) {
|
||||
leaf.detach::< dyn ListView<Arc<RwLock<crate::edit_tree::EditTree>>> >();
|
||||
}
|
||||
else if self.type_tag == TypeTerm::App(vec![
|
||||
TypeTerm::TypeID(TYPEID_list),
|
||||
TypeTerm::TypeID(TYPEID_char),
|
||||
]) {
|
||||
leaf.detach::< dyn ListView<char> >();
|
||||
}
|
||||
else if self.type_tag == TypeTerm::App(vec![
|
||||
TypeTerm::TypeID(TYPEID_list),
|
||||
TypeTerm::TypeID(TYPEID_u64),
|
||||
]) {
|
||||
leaf.detach::< dyn ListView<u64> >();
|
||||
}
|
||||
else {
|
||||
eprintln!("cant detach type {}", ctx.read().unwrap().type_term_to_str(&self.type_tag));
|
||||
}
|
||||
}
|
||||
|
||||
for (t,b) in self.branches.iter_mut() {
|
||||
b.write().unwrap().detach(&ctx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rebuild_projections(&mut self, ctx: &Arc<RwLock<Context>>) {
|
||||
self.detach(ctx);
|
||||
|
||||
for (btyp, brt) in self.branches.iter_mut() {
|
||||
brt.write().unwrap().rebuild_projections(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn require_repr(&mut self, ctx: &Arc<RwLock<Context>>, typ: impl Into<TypeTerm>) {
|
||||
self.required_branches.push( typ.into() );
|
||||
self.rebuild_projections(ctx);
|
||||
}
|
||||
|
||||
pub fn insert_leaf(
|
||||
&mut self,
|
||||
mut type_ladder: impl Iterator<Item = TypeTerm>,
|
||||
leaf: ReprLeaf
|
||||
) {
|
||||
while let Some(type_term) = type_ladder.next() {
|
||||
if &type_term != self.get_type() {
|
||||
if let Some(next_repr) = self.branches.get(&type_term) {
|
||||
next_repr.write().unwrap().insert_leaf(type_ladder, leaf.clone());
|
||||
} else {
|
||||
let mut next_repr = ReprTree::new(type_term.clone());
|
||||
next_repr.insert_leaf(type_ladder, leaf.clone());
|
||||
self.insert_branch(Arc::new(RwLock::new(next_repr)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.leaf = Some(leaf);
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
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< ReprTreeArc > {
|
||||
if let Some(first) = repr_ladder.next() {
|
||||
let rt = rt.read().unwrap();
|
||||
repr_ladder.fold(
|
||||
rt.descend_one(first),
|
||||
|s, t| s?.descend(t))
|
||||
} else {
|
||||
Some(rt.clone())
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
lnf.remove(0);
|
||||
}
|
||||
ReprTree::descend_ladder(rt, lnf.into_iter())
|
||||
} else {
|
||||
Some(rt.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn descend_create(
|
||||
ctx: &Arc<RwLock<Context>>,
|
||||
rt: &Arc<RwLock<Self>>,
|
||||
dst_type: impl Into<TypeTerm>
|
||||
) -> Option< ReprTreeArc > {
|
||||
let dst_type = dst_type.into();
|
||||
if let Some(branch) = ReprTree::descend(rt, dst_type.clone()) {
|
||||
Some(branch)
|
||||
} else {
|
||||
/*
|
||||
let mt =
|
||||
laddertypes::MorphismType {
|
||||
// todo: use halo type ?
|
||||
src_type: laddertypes::TypeTerm::Ladder(vec![
|
||||
rt.read().unwrap().get_halo_type().clone(),
|
||||
rt.get_type()
|
||||
]),
|
||||
dst_type:laddertypes::TypeTerm::Ladder(vec![
|
||||
rt.read().unwrap().get_halo_type().clone(),
|
||||
rt.get_type(),
|
||||
dst_type.clone()
|
||||
]),
|
||||
}.normalize();
|
||||
|
||||
// branch does not exist, try to create it
|
||||
ctx.read().unwrap().apply_morphism(rt,
|
||||
&mt
|
||||
);
|
||||
*/
|
||||
rt.write().unwrap().require_repr(ctx, dst_type.clone());
|
||||
ReprTree::descend(rt, dst_type)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ascend(rt: &Arc<RwLock<Self>>, type_term: impl Into<TypeTerm>) -> ReprTreeArc {
|
||||
let mut n = Self::new(type_term);
|
||||
n.insert_branch(rt.clone());
|
||||
Arc::new(RwLock::new(n))
|
||||
}
|
||||
|
||||
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
// Buffer Access \\
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
pub fn singleton_buffer<T: Clone + Send + Sync + 'static>(&mut self) -> Option<SingletonBuffer<T>> {
|
||||
if let Some(leaf) = self.leaf.as_mut() {
|
||||
leaf.as_singleton_buffer::<T>()
|
||||
} else {
|
||||
// create new singleton buffer
|
||||
/*
|
||||
// default value??
|
||||
let buf = SingletonBuffer::<T>::default();
|
||||
self.leaf = Some(ReprLeaf::from_singleton_buffer(buf.clone()));
|
||||
Some(buf)
|
||||
*/
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vec_buffer<T: Clone + Send + Sync + 'static>(&mut self) -> Option<VecBuffer<T>> {
|
||||
if let Some(leaf) = self.leaf.as_mut() {
|
||||
leaf.as_vec_buffer::<T>()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
// View Access \\
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
pub fn get_port<V: View + ?Sized + 'static>(&self) -> Option<OuterViewPort<V>>
|
||||
where
|
||||
V::Msg: Clone,
|
||||
{
|
||||
if let Some(leaf) = self.leaf.as_ref() {
|
||||
leaf.get_port::<V>()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_view<V: View + ?Sized + 'static>(&self) -> Option<Arc<V>>
|
||||
where
|
||||
V::Msg: Clone,
|
||||
{
|
||||
self.get_port::<V>()?
|
||||
.get_view()
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub fn view_singleton<T: 'static>(&self) -> OuterViewPort<dyn SingletonView<Item = T>> {
|
||||
self.get_port::<dyn SingletonView<Item = T>>().expect("no singleton-view available")
|
||||
}
|
||||
|
||||
pub fn view_seq<T: 'static>(&self) -> OuterViewPort<dyn SequenceView<Item = T>> {
|
||||
self.get_port::<dyn SequenceView<Item = T>>().expect("no sequence-view available")
|
||||
}
|
||||
|
||||
pub fn view_list<T: Clone + Send + Sync + 'static>(&self) -> OuterViewPort<dyn ListView<T>> {
|
||||
self.get_port::<dyn ListView<T>>().expect("no list-view available")
|
||||
}
|
||||
|
||||
pub fn view_char(&self) -> OuterViewPort<dyn SingletonView<Item = char>> {
|
||||
self.get_port::<dyn SingletonView<Item = char>>().expect("no char-view available")
|
||||
}
|
||||
|
||||
pub fn view_u8(&self) -> OuterViewPort<dyn SingletonView<Item = u8>> {
|
||||
self.get_port::<dyn SingletonView<Item = u8>>().expect("no u8-view available")
|
||||
}
|
||||
|
||||
pub fn view_u64(&self) -> OuterViewPort<dyn SingletonView<Item = u64>> {
|
||||
self.get_port::<dyn SingletonView<Item = u64>>().expect("no u64-view available")
|
||||
}
|
||||
|
||||
pub fn view_usize(&self) -> OuterViewPort<dyn SingletonView<Item = usize>> {
|
||||
self.get_port::<dyn SingletonView<Item = usize>>().expect("no usize-view available")
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
198
lib-nested-core/src/repr_tree/tests.rs
Normal file
198
lib-nested-core/src/repr_tree/tests.rs
Normal file
|
@ -0,0 +1,198 @@
|
|||
|
||||
use {
|
||||
r3vi::{
|
||||
buffer::singleton::{
|
||||
SingletonBuffer
|
||||
},
|
||||
view::port::UpdateTask
|
||||
},
|
||||
crate::{
|
||||
repr_tree::{Context, ReprTreeExt, ReprTree, ReprLeaf}
|
||||
},
|
||||
std::sync::{Arc, RwLock}
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn halo_type() {
|
||||
let ctx = Arc::new(RwLock::new(Context::new()));
|
||||
|
||||
let mut rt1 = ReprTree::new_arc(Context::parse(&ctx, "ℕ"));
|
||||
let mut rt2 = ReprTree::new_arc(Context::parse(&ctx, "<PosInt 10 BigEndian>"));
|
||||
rt1.insert_branch( rt2.clone() );
|
||||
assert_eq!( rt2.read().unwrap().get_halo_type(), &Context::parse(&ctx, "ℕ") );
|
||||
|
||||
let mut rt3 = ReprTree::new_arc(Context::parse(&ctx, "<Seq <Digit 10>>"));
|
||||
rt2.insert_branch( rt3.clone() );
|
||||
assert_eq!( rt3.read().unwrap().get_halo_type(), &Context::parse(&ctx, "ℕ~<PosInt 10 BigEndian>") );
|
||||
|
||||
let rt4 = ReprTree::new_arc(Context::parse(&ctx, "<List <Digit 10>>"));
|
||||
rt3.insert_branch( rt4.clone() );
|
||||
assert_eq!( rt4.read().unwrap().get_halo_type(), &Context::parse(&ctx, "ℕ~<PosInt 10 BigEndian>~<Seq <Digit 10>>") );
|
||||
|
||||
|
||||
let mut r = ReprTree::new_arc(Context::parse(&ctx, "ℕ"));
|
||||
r.create_branch(Context::parse(&ctx, "<PosInt 10 BigEndian>~<Seq <Digit 10>>"));
|
||||
assert_eq!( r.descend(Context::parse(&ctx, "<PosInt 10 BigEndian>")).unwrap().read().unwrap().get_halo_type(), &Context::parse(&ctx, "ℕ") );
|
||||
assert_eq!( r.descend(Context::parse(&ctx, "<PosInt 10 BigEndian>~<Seq <Digit 10>>")).unwrap().read().unwrap().get_halo_type(), &Context::parse(&ctx, "ℕ~<PosInt 10 BigEndian>") );
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn char_view() {
|
||||
let ctx = Arc::new(RwLock::new(Context::new()));
|
||||
crate::editors::digit::init_ctx( ctx.clone() );
|
||||
|
||||
let mut rt_digit = ReprTree::new_arc( Context::parse(&ctx, "<Digit 16>") );
|
||||
rt_digit.insert_leaf(
|
||||
Context::parse(&ctx, "Char"),
|
||||
ReprLeaf::from_singleton_buffer( SingletonBuffer::new('5') )
|
||||
);
|
||||
|
||||
//<><><><>
|
||||
let mut digit_char_buffer = rt_digit
|
||||
.descend( Context::parse(&ctx, "Char") ).unwrap()
|
||||
.singleton_buffer::<char>();
|
||||
|
||||
assert_eq!( digit_char_buffer.get(), '5' );
|
||||
//<><><><>
|
||||
|
||||
let digit_char_view = rt_digit
|
||||
.descend(Context::parse(&ctx, "Char")).unwrap()
|
||||
.view_char();
|
||||
|
||||
assert_eq!( digit_char_view.get_view().unwrap().get(), '5' );
|
||||
|
||||
|
||||
//<><><><>
|
||||
// `Char-view` is correctly coupled to `char-buffer`
|
||||
digit_char_buffer.set('2');
|
||||
assert_eq!( digit_char_view.get_view().unwrap().get(), '2' );
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn digit_projection_char_to_u64() {
|
||||
let ctx = Arc::new(RwLock::new(Context::new()));
|
||||
crate::editors::digit::init_ctx( ctx.clone() );
|
||||
|
||||
let mut rt_digit = ReprTree::new_arc( Context::parse(&ctx, "<Digit 16>") );
|
||||
|
||||
rt_digit.insert_leaf(
|
||||
Context::parse(&ctx, "Char"),
|
||||
ReprLeaf::from_singleton_buffer( SingletonBuffer::new('5') )
|
||||
);
|
||||
|
||||
//<><><><>
|
||||
// add another representation
|
||||
|
||||
ctx.read().unwrap().apply_morphism(
|
||||
rt_digit.clone(),
|
||||
&laddertypes::MorphismType {
|
||||
src_type: Context::parse(&ctx, "<Digit 16>~Char"),
|
||||
dst_type: Context::parse(&ctx, "<Digit 16>~ℤ_2^64~machine.UInt64")
|
||||
}
|
||||
);
|
||||
|
||||
let digit_u64_view = rt_digit
|
||||
.descend(Context::parse(&ctx, "ℤ_2^64~machine.UInt64")).unwrap()
|
||||
.view_u64();
|
||||
|
||||
assert_eq!( digit_u64_view.get_view().unwrap().get(), 5 as u64 );
|
||||
|
||||
|
||||
// projection behaves accordingly , when buffer is changed
|
||||
|
||||
let mut digit_char_buffer = rt_digit
|
||||
.descend( Context::parse(&ctx, "Char") ).unwrap()
|
||||
.singleton_buffer::<char>();
|
||||
|
||||
digit_char_buffer.set('2');
|
||||
assert_eq!( digit_u64_view.get_view().unwrap().get(), 2 as u64 );
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn digit_projection_u64_to_char() {
|
||||
let ctx = Arc::new(RwLock::new(Context::new()));
|
||||
crate::editors::digit::init_ctx( ctx.clone() );
|
||||
|
||||
let mut rt_digit = ReprTree::new_arc( Context::parse(&ctx, "<Digit 16>") );
|
||||
|
||||
rt_digit.insert_leaf(
|
||||
Context::parse(&ctx, "ℤ_2^64~machine.UInt64"),
|
||||
ReprLeaf::from_singleton_buffer( SingletonBuffer::new(5 as u64) )
|
||||
);
|
||||
|
||||
//<><><><>
|
||||
// add another representation
|
||||
|
||||
ctx.read().unwrap().apply_morphism(
|
||||
rt_digit.clone(),
|
||||
&laddertypes::MorphismType {
|
||||
src_type: Context::parse(&ctx, "<Digit 16>~ℤ_2^64~machine.UInt64"),
|
||||
dst_type: Context::parse(&ctx, "<Digit 16>~Char")
|
||||
}
|
||||
);
|
||||
|
||||
let digit_u64_view = rt_digit
|
||||
.descend(Context::parse(&ctx, "Char")).unwrap()
|
||||
.view_char();
|
||||
|
||||
assert_eq!( digit_u64_view.get_view().unwrap().get(), '5' );
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn char_buffered_projection() {
|
||||
let ctx = Arc::new(RwLock::new(Context::new()));
|
||||
crate::editors::digit::init_ctx( ctx.clone() );
|
||||
|
||||
let mut rt_digit = ReprTree::new_arc( Context::parse(&ctx, "<Digit 16>") );
|
||||
|
||||
rt_digit.insert_leaf(
|
||||
Context::parse(&ctx, "ℤ_2^64~machine.UInt64"),
|
||||
ReprLeaf::from_singleton_buffer( SingletonBuffer::new(8 as u64) )
|
||||
);
|
||||
|
||||
let mut digit_u64_buffer = rt_digit
|
||||
.descend(Context::parse(&ctx, "ℤ_2^64~machine.UInt64")).unwrap()
|
||||
.singleton_buffer::<u64>();
|
||||
|
||||
assert_eq!( digit_u64_buffer.get(), 8 );
|
||||
|
||||
rt_digit.insert_leaf(
|
||||
Context::parse(&ctx, "Char"),
|
||||
ReprLeaf::from_singleton_buffer( SingletonBuffer::new('5') )
|
||||
);
|
||||
|
||||
let digit_char_buf = rt_digit
|
||||
.descend(Context::parse(&ctx, "Char")).unwrap()
|
||||
.singleton_buffer::<char>();
|
||||
let digit_char_view = rt_digit
|
||||
.descend(Context::parse(&ctx, "Char")).unwrap()
|
||||
.view_char();
|
||||
|
||||
// before setting up the morphism, char-view remains as initialized
|
||||
assert_eq!( digit_char_buf.get(), '5' );
|
||||
assert_eq!( digit_char_view.get_view().unwrap().get(), '5' );
|
||||
|
||||
// now we attach the char-repr to the u64-repr
|
||||
ctx.read().unwrap().apply_morphism(
|
||||
rt_digit.clone(),
|
||||
&laddertypes::MorphismType {
|
||||
src_type: Context::parse(&ctx, "<Digit 16>~ℤ_2^64~machine.UInt64"),
|
||||
dst_type: Context::parse(&ctx, "<Digit 16>~Char")
|
||||
}
|
||||
);
|
||||
|
||||
// char buffer and view should now follow the u64-buffer
|
||||
assert_eq!( digit_char_view.get_view().unwrap().get(), '8' );
|
||||
assert_eq!( digit_char_buf.get(), '8' );
|
||||
|
||||
// now u64-buffer changes, and char-buffer should change accordingly
|
||||
digit_u64_buffer.set(3);
|
||||
assert_eq!( digit_u64_buffer.get(), 3 );
|
||||
|
||||
// char buffer should follow
|
||||
digit_char_view.0.update();
|
||||
assert_eq!( digit_char_buf.get(), '3' );
|
||||
assert_eq!( digit_char_view.get_view().unwrap().get(), '3' );
|
||||
}
|
||||
|
2
lib-nested-core/src/utils/mod.rs
Normal file
2
lib-nested-core/src/utils/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod modulo;
|
||||
pub use modulo::modulo;
|
10
lib-nested-softbuffer/Cargo.toml
Normal file
10
lib-nested-softbuffer/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
authors = ["Michael Sippel <micha@fragmental.art>"]
|
||||
name = "lib-nested-softbuffer"
|
||||
|
||||
[dependencies]
|
||||
r3vi = { path = "../../lib-r3vi" }
|
||||
laddertypes = { path = "../../lib-laddertypes" }
|
||||
nested = { path = "../lib-nested-core" }
|
||||
softbuffer = "0.4.2"
|
||||
|
|
@ -1,24 +1,23 @@
|
|||
[package]
|
||||
authors = ["Michael Sippel <micha@fragmental.art>"]
|
||||
edition = "2018"
|
||||
name = "nested"
|
||||
name = "nested-tty"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
#r3vi = { git = "https://git.exobiont.de/senvas/lib-r3vi.git" }
|
||||
r3vi = { path = "../../lib-r3vi" }
|
||||
laddertypes = { path = "../../lib-laddertypes" }
|
||||
no_deadlocks = "*"
|
||||
nested = { path = "../lib-nested-core" }
|
||||
cgmath = { version = "0.18.0", features = ["serde"] }
|
||||
termion = "2.0.1"
|
||||
serde = { version = "1.0", features = ["serde_derive"] }
|
||||
termion = "2.0.3"
|
||||
vte = "0.10.1"
|
||||
ansi_colours = "1.0"
|
||||
signal-hook = "0.3.1"
|
||||
signal-hook-async-std = "0.2.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
bincode = "1.3.3"
|
||||
serde_json = "*"
|
||||
signal-hook = "*"
|
||||
signal-hook-async-std = "*"
|
||||
|
||||
[dependencies.async-std]
|
||||
version = "1.9.0"
|
||||
features = ["unstable", "attributes"]
|
||||
|
||||
|
|
@ -10,7 +10,8 @@ use {
|
|||
projection::projection_helper::ProjectionHelper,
|
||||
},
|
||||
crate::{
|
||||
terminal::{TerminalAtom, TerminalStyle, TerminalView},
|
||||
atom::{TerminalAtom, TerminalStyle},
|
||||
TerminalView,
|
||||
},
|
||||
cgmath::{Point2, Vector2},
|
||||
std::io::Read,
|
|
@ -1,7 +1,7 @@
|
|||
use {
|
||||
super::TerminalStyle,
|
||||
serde::{Deserialize, Serialize},
|
||||
};
|
||||
pub mod style;
|
||||
pub use style::TerminalStyle;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
|
||||
pub struct TerminalAtom {
|
|
@ -6,7 +6,7 @@ use {
|
|||
},
|
||||
projection::projection_helper::*,
|
||||
},
|
||||
crate::{terminal::{TerminalAtom, TerminalView}},
|
||||
crate::{TerminalAtom, TerminalView},
|
||||
cgmath::Point2,
|
||||
std::sync::Arc,
|
||||
std::sync::RwLock,
|
|
@ -1,5 +1,5 @@
|
|||
use {
|
||||
crate::terminal::TerminalStyle,
|
||||
crate::atom::TerminalStyle,
|
||||
};
|
||||
|
||||
pub fn bg_style_from_depth(depth: usize) -> TerminalStyle {
|
54
lib-nested-tty/src/edit_tree/cursor_widget.rs
Normal file
54
lib-nested-tty/src/edit_tree/cursor_widget.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{
|
||||
OuterViewPort
|
||||
},
|
||||
buffer::vec::*,
|
||||
projection::decorate_sequence::Separate
|
||||
},
|
||||
nested::{
|
||||
edit_tree::{
|
||||
TreeNav
|
||||
},
|
||||
editors::list::{
|
||||
ListCursorMode
|
||||
}
|
||||
},
|
||||
crate::{TerminalView, make_label, TerminalProjections}
|
||||
};
|
||||
|
||||
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![
|
||||
make_label("@").with_fg_color((150, 80,230)),
|
||||
self.get_addr_view()
|
||||
.map(|i|
|
||||
make_label(&format!("{}", i)).with_fg_color((0, 100, 20)))
|
||||
.separate(make_label(".").with_fg_color((150, 80,230)))
|
||||
.to_grid_horizontal()
|
||||
.flatten(),
|
||||
make_label(":").with_fg_color((150, 80,230)),
|
||||
self.get_mode_view()
|
||||
.map(|mode| {
|
||||
make_label(
|
||||
match mode {
|
||||
ListCursorMode::Insert => "INSERT",
|
||||
ListCursorMode::Select => "SELECT"
|
||||
})
|
||||
.with_fg_color((200, 200, 20))
|
||||
})
|
||||
.to_grid()
|
||||
.flatten(),
|
||||
make_label(":").with_fg_color((150, 80,230))
|
||||
]
|
||||
).get_port()
|
||||
.to_sequence()
|
||||
.to_grid_horizontal()
|
||||
.flatten()
|
||||
}
|
||||
}
|
|
@ -1,27 +1,3 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{OuterViewPort, sequence::*},
|
||||
buffer::{vec::*, index_hashmap::*}
|
||||
},
|
||||
crate::{
|
||||
terminal::{
|
||||
TerminalView, TerminalStyle, make_label
|
||||
}
|
||||
},
|
||||
cgmath::Point2
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Message {
|
||||
pub addr: Vec<usize>,
|
||||
pub port: OuterViewPort<dyn TerminalView>
|
||||
}
|
||||
|
||||
pub trait Diagnostics {
|
||||
fn get_msg_port(&self) -> OuterViewPort<dyn SequenceView<Item = Message>> {
|
||||
VecBuffer::new().get_port().to_sequence()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_error(msg: OuterViewPort<dyn TerminalView>) -> Message {
|
||||
let mut mb = IndexBuffer::new();
|
110
lib-nested-tty/src/edit_tree/keymap.rs
Normal file
110
lib-nested-tty/src/edit_tree/keymap.rs
Normal file
|
@ -0,0 +1,110 @@
|
|||
use {
|
||||
termion::event::{Event, Key},
|
||||
r3vi::{
|
||||
buffer::singleton::*
|
||||
},
|
||||
nested::{
|
||||
repr_tree::{Context, ReprTree},
|
||||
editors::list::ListCmd,
|
||||
edit_tree::nav::TreeNavCmd
|
||||
},
|
||||
crate::{
|
||||
TerminalEvent
|
||||
},
|
||||
std::sync::{Arc, RwLock}
|
||||
};
|
||||
|
||||
fn neo2_treenav_keymap( key: &Key ) -> Option<TreeNavCmd> {
|
||||
match key {
|
||||
Key::Ctrl(c) => {
|
||||
match c {
|
||||
|
||||
// left hand
|
||||
'l' => Some(TreeNavCmd::up),
|
||||
'i' => Some(TreeNavCmd::qnexd),
|
||||
'a' => Some(TreeNavCmd::dn),
|
||||
'e' => Some(TreeNavCmd::pxev),
|
||||
|
||||
// right hand
|
||||
'n' => Some(TreeNavCmd::nexd),
|
||||
'r' => Some(TreeNavCmd::dn_pxev),
|
||||
't' => Some(TreeNavCmd::qnexd),
|
||||
'g' => Some(TreeNavCmd::up_nexd),
|
||||
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
fn universal_treenav_keymap( key: &Key ) -> Option<TreeNavCmd> {
|
||||
match key {
|
||||
Key::Left => Some(TreeNavCmd::pxev),
|
||||
Key::Right => Some(TreeNavCmd::nexd),
|
||||
Key::Up => Some(TreeNavCmd::up),
|
||||
Key::Down => Some(TreeNavCmd::dn),
|
||||
Key::Home => Some(TreeNavCmd::qpxev),
|
||||
Key::End => Some(TreeNavCmd::qnexd),
|
||||
Key::PageUp => Some(TreeNavCmd::up_nexd),
|
||||
Key::PageDown => Some(TreeNavCmd::pxev_dn_qnexd),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
fn tty_list_keymap( key: &Key ) -> Option<ListCmd> {
|
||||
match key {
|
||||
// Key::Char('\t') => Some( ListCmd::ToggleLeafMode ),
|
||||
|
||||
Key::Backspace => Some( ListCmd::DeletePxev ),
|
||||
Key::Delete => Some( ListCmd::DeleteNexd ),
|
||||
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
impl TerminalEvent {
|
||||
pub fn to_repr_tree( &self, ctx: &Arc<RwLock<Context>> ) -> Arc<RwLock<ReprTree>> {
|
||||
match self {
|
||||
TerminalEvent::Input(Event::Key(key)) => {
|
||||
if let Some(tree_nav_cmd) = neo2_treenav_keymap(key) {
|
||||
ReprTree::from_singleton_buffer(
|
||||
Context::parse(&ctx, "TreeNavCmd"),
|
||||
SingletonBuffer::new(tree_nav_cmd)
|
||||
)
|
||||
} else if let Some(tree_nav_cmd) = universal_treenav_keymap(key) {
|
||||
ReprTree::from_singleton_buffer(
|
||||
Context::parse(&ctx, "TreeNavCmd"),
|
||||
SingletonBuffer::new(tree_nav_cmd)
|
||||
)
|
||||
} else {
|
||||
if let Some(list_cmd) = tty_list_keymap(key) {
|
||||
ReprTree::from_singleton_buffer(
|
||||
Context::parse(&ctx, "ListCmd"),
|
||||
SingletonBuffer::new(list_cmd)
|
||||
)
|
||||
} else {
|
||||
match key {
|
||||
Key::Char(c) => {
|
||||
ReprTree::from_char(&ctx, *c)
|
||||
}
|
||||
_ => {
|
||||
ReprTree::from_singleton_buffer(
|
||||
Context::parse(&ctx, "TerminalEvent"),
|
||||
SingletonBuffer::new(self.clone())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
ReprTree::from_singleton_buffer(
|
||||
Context::parse(&ctx, "TerminalEvent"),
|
||||
SingletonBuffer::new(self.clone())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
4
lib-nested-tty/src/edit_tree/mod.rs
Normal file
4
lib-nested-tty/src/edit_tree/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
pub mod color;
|
||||
pub mod keymap;
|
||||
pub mod cursor_widget;
|
0
lib-nested-tty/src/editors/char.rs
Normal file
0
lib-nested-tty/src/editors/char.rs
Normal file
|
@ -3,13 +3,17 @@ use {
|
|||
view::{ViewPort, OuterViewPort, sequence::*},
|
||||
projection::decorate_sequence::*,
|
||||
},
|
||||
crate::{
|
||||
type_system::{Context, ReprTree},
|
||||
nested::{
|
||||
repr_tree::{Context, ReprTree},
|
||||
editors::list::*,
|
||||
terminal::{TerminalEvent, TerminalView, make_label},
|
||||
tree::{TreeCursor, TreeNav, TreeNavResult},
|
||||
tree::NestedNode,
|
||||
PtySegment
|
||||
edit_tree::{TreeCursor, TreeNav, TreeNavResult, EditTree},
|
||||
repr_tree::{ReprTreeExt, ReprLeaf}
|
||||
},
|
||||
crate::{
|
||||
DisplaySegment,
|
||||
TerminalStyle,
|
||||
TerminalEvent, TerminalView, make_label,
|
||||
edit_tree::color::{bg_style_from_depth, fg_style_from_depth}
|
||||
},
|
||||
std::sync::{Arc, RwLock},
|
||||
termion::event::{Event, Key}
|
||||
|
@ -17,6 +21,41 @@ use {
|
|||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl DisplaySegment for ListSegment {
|
||||
fn display_view(&self) -> OuterViewPort<dyn TerminalView> {
|
||||
match self {
|
||||
ListSegment::InsertCursor => {
|
||||
make_label("|")
|
||||
.map_item(move |_pt, atom| {
|
||||
atom.add_style_front(TerminalStyle::fg_color((150,80,230)))
|
||||
.add_style_front(TerminalStyle::bold(true))
|
||||
})
|
||||
}
|
||||
ListSegment::Item{ editor, cur_dist } => {
|
||||
let e = editor.clone();
|
||||
let cur_dist = *cur_dist;
|
||||
editor.display_view().map_item(move |_pt, atom| {
|
||||
let c = e.get_cursor();
|
||||
let cur_depth = c.tree_addr.len();
|
||||
let select =
|
||||
if cur_dist == 0 {
|
||||
cur_depth
|
||||
} else {
|
||||
usize::MAX
|
||||
};
|
||||
|
||||
atom
|
||||
.add_style_back(bg_style_from_depth(select))
|
||||
.add_style_back(TerminalStyle::bold(select==1))
|
||||
.add_style_back(fg_style_from_depth(e.disp.depth.get_view().get()))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub struct PTYListStyle {
|
||||
style: (String, String, String)
|
||||
}
|
||||
|
@ -31,35 +70,39 @@ impl PTYListStyle {
|
|||
pub fn get_seg_seq_view(&self, editor: &ListEditor) -> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> {
|
||||
let seg_seq = ListSegmentSequence::new(
|
||||
editor.get_cursor_port(),
|
||||
editor.get_data_port()
|
||||
editor.get_edittree_seq()
|
||||
);
|
||||
let se = seg_seq.read().unwrap();
|
||||
se.get_view().map(move |segment| segment.pty_view())
|
||||
se.get_view().map(move |segment| segment.display_view())
|
||||
}
|
||||
|
||||
pub fn pty_view(&self, editor: &ListEditor) -> OuterViewPort<dyn TerminalView> {
|
||||
let seg_seq = ListSegmentSequence::new(
|
||||
editor.get_cursor_port(),
|
||||
editor.get_data_port()
|
||||
editor.get_edittree_seq()
|
||||
);
|
||||
let seg_seq = seg_seq.read().unwrap();
|
||||
|
||||
let seg_seq0 = seg_seq.read().unwrap();
|
||||
let seg_seq = seg_seq0.get_view();
|
||||
drop(seg_seq0);
|
||||
|
||||
seg_seq
|
||||
.get_view()
|
||||
.map(move |segment| segment.pty_view())
|
||||
.map(move |segment| segment.display_view())
|
||||
.separate(make_label(&self.style.1))
|
||||
.wrap(make_label(&self.style.0), make_label(&self.style.2))
|
||||
.to_grid_horizontal()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub fn for_node(node: &mut NestedNode, style: (&str, &str, &str)) {
|
||||
node.view = Some(
|
||||
Self::new(style)
|
||||
.pty_view(
|
||||
&node.get_edit::<ListEditor>().unwrap().read().unwrap()
|
||||
)
|
||||
);
|
||||
pub fn for_node(node: &mut EditTree, style: (&str, &str, &str)) {
|
||||
let editor = node.get_edit::<ListEditor>().unwrap();
|
||||
let editor = editor.read().unwrap();
|
||||
let pty_view = Self::new(style).pty_view(&editor);
|
||||
node.disp.view
|
||||
.attach_leaf_to(
|
||||
Context::parse(&node.ctx, "TerminalView"),
|
||||
pty_view
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,10 +137,11 @@ impl PTYListController {
|
|||
}
|
||||
|
||||
pub fn for_node(
|
||||
node: &mut NestedNode,
|
||||
node: &mut EditTree,
|
||||
split_char: Option<char>,
|
||||
close_char: Option<char>
|
||||
) {
|
||||
/*
|
||||
{
|
||||
let ctx = node.ctx.as_ref();
|
||||
let mut ctx = ctx.write().unwrap();
|
||||
|
@ -109,39 +153,46 @@ impl PTYListController {
|
|||
ctx.meta_chars.push(*c);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
let editor = node.get_edit::<ListEditor>().unwrap();
|
||||
let controller = Arc::new(RwLock::new(PTYListController::from_editor( editor, split_char, close_char, node.depth.clone() )));
|
||||
let controller = Arc::new(RwLock::new(PTYListController::from_editor( editor, split_char, close_char, node.disp.depth.clone() )));
|
||||
|
||||
node.cmd.set(Some(controller.clone()));
|
||||
node.close_char.set(close_char);
|
||||
node.ctrl.cmd.set(Some(controller.clone()));
|
||||
node.ctrl.close_char.set(close_char);
|
||||
}
|
||||
|
||||
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = NestedNode>> {
|
||||
self.editor.read().unwrap().get_data_port()
|
||||
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = EditTree>> {
|
||||
self.editor.read().unwrap().get_edittree_seq()
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.editor.write().unwrap().clear();
|
||||
}
|
||||
|
||||
pub fn get_item(&self) -> Option<NestedNode> {
|
||||
/*
|
||||
pub fn get_item(&self) -> Option<EditTree> {
|
||||
self.editor.read().unwrap().get_item()
|
||||
}
|
||||
|
||||
pub fn handle_term_event(&mut self, event: &TerminalEvent, _cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
|
||||
*/
|
||||
pub fn handle_term_event(&mut self, event: &TerminalEvent, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
|
||||
let mut e = self.editor.write().unwrap();
|
||||
match event {
|
||||
TerminalEvent::Input(Event::Key(Key::Insert)) => {
|
||||
e.toggle_leaf_mode();
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
_ => TreeNavResult::Continue
|
||||
TerminalEvent::Input(Event::Key(Key::Char(c))) => {
|
||||
let ctx = e.ctx.clone();
|
||||
drop(e);
|
||||
self.handle_any_event(
|
||||
ReprTree::from_char(&ctx, *c)
|
||||
)
|
||||
}
|
||||
_ => TreeNavResult::Continue
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_meta_char(&mut self, c: char, child_close_char: Option<char>) -> TreeNavResult {
|
||||
eprintln!("handle meta char: got '{}', child_close={:?}, self.close={:?}, split={:?}", c, child_close_char, self.close_char, self.split_char);
|
||||
// eprintln!("handle meta char: got '{}', child_close={:?}, self.close={:?}, split={:?}", c, child_close_char, self.close_char, self.split_char);
|
||||
let mut e = self.editor.write().unwrap();
|
||||
let cur = e.cursor.get();
|
||||
|
||||
|
@ -149,7 +200,7 @@ impl PTYListController {
|
|||
// || Some(c) == child_close_char
|
||||
{
|
||||
e.listlist_split();
|
||||
eprintln!("done listlist split");
|
||||
// eprintln!("done listlist split");
|
||||
TreeNavResult::Continue
|
||||
} else if Some(c) == child_close_char {
|
||||
e.goto(TreeCursor::none());
|
||||
|
@ -171,23 +222,47 @@ impl PTYListController {
|
|||
|
||||
match cur.mode {
|
||||
ListCursorMode::Insert => {
|
||||
let mut new_edit = Context::make_node(&e.ctx, e.typ.clone(), self.depth.map(|d| d+1)).unwrap();
|
||||
new_edit.goto(TreeCursor::home());
|
||||
let rt = ReprTree::new_arc(e.typ.clone());
|
||||
|
||||
match new_edit.send_cmd_obj(cmd_obj.clone()) {
|
||||
TreeNavResult::Continue => {
|
||||
e.insert(Arc::new(RwLock::new(new_edit.clone())));
|
||||
TreeNavResult::Continue
|
||||
let src_ladder = laddertypes::TypeTerm::Ladder(vec![
|
||||
rt.read().unwrap().get_type().clone()
|
||||
]);
|
||||
let dst_ladder = laddertypes::TypeTerm::Ladder(vec![
|
||||
rt.read().unwrap().get_type().clone(),
|
||||
ctx.type_term_from_str("EditTree").expect("")
|
||||
]);
|
||||
ctx.apply_morphism(
|
||||
&rt,
|
||||
&laddertypes::MorphismType {
|
||||
src_type: src_ladder,
|
||||
dst_type: dst_ladder
|
||||
}
|
||||
TreeNavResult::Exit => {
|
||||
TreeNavResult::Exit
|
||||
);
|
||||
|
||||
let new_edittree = ctx.setup_edittree( &rt );
|
||||
|
||||
if let Some(new_edittree) = new_edittree {
|
||||
let mut ne = new_edittree.get();
|
||||
let mut ne = ne.write().unwrap();
|
||||
match ne.send_cmd_obj(cmd_obj.clone()) {
|
||||
TreeNavResult::Continue => {
|
||||
drop(ne);
|
||||
e.insert(rt);
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
TreeNavResult::Exit => {
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("cant get edit tree");
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
},
|
||||
ListCursorMode::Select => {
|
||||
if let Some(item) = e.get_item_mut() {
|
||||
if let Some(item) = e.get_cur_edittree() {
|
||||
let res = item.write().unwrap().send_cmd_obj(cmd_obj.clone());
|
||||
let child_close_char = item.read().unwrap().close_char.get();
|
||||
let child_close_char = item.read().unwrap().ctrl.close_char.get();
|
||||
|
||||
match res {
|
||||
TreeNavResult::Continue => TreeNavResult::Continue,
|
||||
|
@ -218,7 +293,7 @@ impl PTYListController {
|
|||
}
|
||||
|
||||
use r3vi::view::singleton::SingletonView;
|
||||
use crate::commander::ObjCommander;
|
||||
use nested::editors::ObjCommander;
|
||||
|
||||
impl ObjCommander for PTYListController {
|
||||
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
|
||||
|
@ -226,7 +301,7 @@ impl ObjCommander for PTYListController {
|
|||
let cmd_type = cmd_obj.read().unwrap().get_type().clone();
|
||||
|
||||
if cmd_type == Context::parse(&e.ctx, "ListCmd").into()
|
||||
|| cmd_type == Context::parse(&e.ctx, "NestedNode").into()
|
||||
|| cmd_type == Context::parse(&e.ctx, "EditTree").into()
|
||||
{
|
||||
e.send_cmd_obj( cmd_obj )
|
||||
}
|
85
lib-nested-tty/src/editors/mod.rs
Normal file
85
lib-nested-tty/src/editors/mod.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
|
||||
pub mod list;
|
||||
|
||||
use {
|
||||
nested::{
|
||||
edit_tree::{EditTree},
|
||||
repr_tree::{ReprTree, Context}
|
||||
},
|
||||
r3vi::{
|
||||
view::{singleton::*, sequence::*},
|
||||
projection::decorate_sequence::*
|
||||
},
|
||||
crate::{
|
||||
make_label,
|
||||
DisplaySegment,
|
||||
atom::{TerminalAtom, TerminalStyle}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn edittree_make_char_view(
|
||||
node: EditTree
|
||||
) -> EditTree {
|
||||
node.disp.view
|
||||
.write().unwrap()
|
||||
.insert_branch(ReprTree::from_view(
|
||||
Context::parse(&node.ctx, "TerminalView"),
|
||||
node.get_edit::< nested::editors::char::CharEditor >()
|
||||
.unwrap()
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_port()
|
||||
.map(move |c| TerminalAtom::from(if c == '\0' { ' ' } else { c }))
|
||||
.to_grid()
|
||||
));
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
pub fn edittree_make_digit_view(
|
||||
node: EditTree
|
||||
) -> EditTree {
|
||||
node.disp.view
|
||||
.write().unwrap()
|
||||
.insert_branch(ReprTree::from_view(
|
||||
Context::parse(&node.ctx, "TerminalView"),
|
||||
node.get_edit::< nested::editors::digit::DigitEditor >()
|
||||
.unwrap()
|
||||
.read()
|
||||
.unwrap()
|
||||
.get_data_port()
|
||||
.map(move |digit|
|
||||
match digit {
|
||||
Ok(digit) => TerminalAtom::new( char::from_digit(digit, 16).unwrap_or('?'), TerminalStyle::fg_color((220, 220, 0)) ),
|
||||
Err(c) => TerminalAtom::new( c, TerminalStyle::fg_color((220, 0, 0)) )
|
||||
}
|
||||
)
|
||||
.to_grid()
|
||||
));
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn edittree_make_seq_view(
|
||||
mut node: EditTree
|
||||
) -> EditTree {
|
||||
node.disp.view
|
||||
.write().unwrap()
|
||||
.insert_branch(ReprTree::new_leaf(
|
||||
Context::parse(&node.ctx, "TerminalView"),
|
||||
node.get_edit::< nested::editors::list::ListEditor >()
|
||||
.unwrap()
|
||||
.read().unwrap()
|
||||
.get_data_port()
|
||||
.map(move |item_edittree|
|
||||
edittree_make_tty_view( item_edittree ).display_view()
|
||||
)
|
||||
.wrap(make_label("("), make_label(")"))
|
||||
.to_grid_horizontal()
|
||||
.flatten()
|
||||
.into()
|
||||
));
|
||||
node
|
||||
}
|
||||
*/
|
0
lib-nested-tty/src/editors/product.rs
Normal file
0
lib-nested-tty/src/editors/product.rs
Normal file
0
lib-nested-tty/src/editors/singleton.rs
Normal file
0
lib-nested-tty/src/editors/singleton.rs
Normal file
8
lib-nested-tty/src/editors/sum.rs
Normal file
8
lib-nested-tty/src/editors/sum.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
|
||||
impl PtySegment for SumEditor {
|
||||
fn pty_view(&self) -> OuterViewPort<dyn TerminalView> {
|
||||
self.port.outer()
|
||||
}
|
||||
}
|
||||
|
181
lib-nested-tty/src/lib.rs
Normal file
181
lib-nested-tty/src/lib.rs
Normal file
|
@ -0,0 +1,181 @@
|
|||
|
||||
#![feature(trait_alias)]
|
||||
|
||||
// <<<<>>>><<>><><<>><<< * >>><<>><><<>><<<<>>>> \\
|
||||
|
||||
pub mod atom;
|
||||
|
||||
pub mod compositor;
|
||||
pub mod ansi_parser;
|
||||
|
||||
pub mod terminal;
|
||||
pub mod tty_application;
|
||||
|
||||
pub mod editors;
|
||||
pub mod edit_tree;
|
||||
//pub mod widgets;
|
||||
|
||||
// <<<<>>>><<>><><<>><<< * >>><<>><><<>><<<<>>>> \\
|
||||
|
||||
pub use {
|
||||
atom::{TerminalAtom, TerminalStyle},
|
||||
terminal::{Terminal, TerminalEvent},
|
||||
tty_application::TTYApplication,
|
||||
compositor::TerminalCompositor,
|
||||
};
|
||||
|
||||
use r3vi::view::grid::*;
|
||||
|
||||
// <<<<>>>><<>><><<>><<< * >>><<>><><<>><<<<>>>> \\
|
||||
|
||||
pub trait TerminalView = GridView<Item = TerminalAtom>;
|
||||
|
||||
// <<<<>>>><<>><><<>><<< * >>><<>><><<>><<<<>>>> \\
|
||||
|
||||
use r3vi::view::OuterViewPort;
|
||||
|
||||
pub trait DisplaySegment {
|
||||
fn display_view(&self) -> OuterViewPort<dyn TerminalView>;
|
||||
}
|
||||
|
||||
|
||||
use nested::repr_tree::{Context, ReprTreeExt};
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
impl DisplaySegment for nested::edit_tree::EditTree {
|
||||
fn display_view(&self) -> OuterViewPort<dyn TerminalView> {
|
||||
if let Some( tv_repr ) = self.disp.view
|
||||
.descend( Context::parse(&self.ctx, "TerminalView") )
|
||||
{
|
||||
if let Some(port) =
|
||||
tv_repr
|
||||
.read().unwrap()
|
||||
.get_port::<dyn TerminalView>() {
|
||||
port
|
||||
}
|
||||
|
||||
else {
|
||||
make_label("# could not get ViewPort #")
|
||||
}
|
||||
} else {
|
||||
make_label("# No TTY View available #")
|
||||
.map_item(|_p,a| a.add_style_back(TerminalStyle::fg_color((220, 30, 30))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
use {
|
||||
r3vi::{
|
||||
buffer::vec::*,
|
||||
},
|
||||
cgmath::Point2,
|
||||
};
|
||||
|
||||
pub fn make_label(s: &str) -> OuterViewPort<dyn TerminalView> {
|
||||
let label = VecBuffer::with_data(s.chars().collect());
|
||||
|
||||
let v = label.get_port()
|
||||
.to_sequence()
|
||||
.map(|c| TerminalAtom::from(c))
|
||||
.to_index()
|
||||
.map_key(
|
||||
|idx| Point2::new(*idx as i16, 0),
|
||||
|pt| if pt.y == 0 { Some(pt.x as usize) } else { None },
|
||||
);
|
||||
|
||||
v
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub trait TerminalProjections {
|
||||
fn with_style(&self, style: TerminalStyle) -> OuterViewPort<dyn TerminalView>;
|
||||
fn with_fg_color(&self, col: (u8, u8, u8)) -> OuterViewPort<dyn TerminalView>;
|
||||
fn with_bg_color(&self, col: (u8, u8, u8)) -> OuterViewPort<dyn TerminalView>;
|
||||
}
|
||||
|
||||
impl TerminalProjections for OuterViewPort<dyn TerminalView> {
|
||||
fn with_style(&self, style: TerminalStyle) -> OuterViewPort<dyn TerminalView> {
|
||||
self.map_item(
|
||||
move |_idx, a|
|
||||
a.add_style_front(style)
|
||||
)
|
||||
}
|
||||
|
||||
fn with_fg_color(&self, col: (u8, u8, u8)) -> OuterViewPort<dyn TerminalView> {
|
||||
self.with_style(TerminalStyle::fg_color(col))
|
||||
}
|
||||
|
||||
fn with_bg_color(&self, col: (u8, u8, u8)) -> OuterViewPort<dyn TerminalView> {
|
||||
self.with_style(TerminalStyle::bg_color(col))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub fn setup_edittree_hook(ctx: &Arc<RwLock<Context>>) {
|
||||
|
||||
let char_type = Context::parse(&ctx, "Char");
|
||||
let digit_type = Context::parse(&ctx, "<Digit Radix>");
|
||||
let list_type = Context::parse(&ctx, "<List Item>");
|
||||
let posint_bin_type = Context::parse(&ctx, "<PosInt 2 BigEndian>");
|
||||
let posint_oct_type = Context::parse(&ctx, "<PosInt 8 BigEndian>");
|
||||
let posint_dec_type = Context::parse(&ctx, "<PosInt 10 BigEndian>");
|
||||
let posint_hex_type = Context::parse(&ctx, "<PosInt 16 BigEndian>");
|
||||
let item_tyid = ctx.read().unwrap().get_var_typeid("Item").unwrap();
|
||||
|
||||
ctx.write().unwrap().meta_chars.push('\n');
|
||||
//ctx.write().unwrap().meta_chars.push(',');
|
||||
//ctx.write().unwrap().meta_chars.push('\"');
|
||||
//ctx.write().unwrap().meta_chars.push('}');
|
||||
|
||||
// Define a hook which is executed when a new editTree of type `t` is created.
|
||||
// this will setup the display and navigation elements of the editor.
|
||||
// It provides the necessary bridge to the rendering- & input-backend.
|
||||
ctx.write().unwrap().set_edittree_hook(
|
||||
Arc::new(
|
||||
move |et: &mut nested::edit_tree::EditTree, t: laddertypes::TypeTerm| {
|
||||
if let Ok(σ) = laddertypes::unify(&t, &char_type.clone()) {
|
||||
*et = crate::editors::edittree_make_char_view(et.clone());
|
||||
}
|
||||
else if let Ok(σ) = laddertypes::unify(&t, &digit_type) {
|
||||
*et = crate::editors::edittree_make_digit_view(et.clone());
|
||||
}
|
||||
else if let Ok(σ) = laddertypes::unify(&t, &posint_bin_type) {
|
||||
crate::editors::list::PTYListStyle::for_node( &mut *et, ("0b", "", ""));
|
||||
crate::editors::list::PTYListController::for_node( &mut *et, None, None );
|
||||
}
|
||||
else if let Ok(σ) = laddertypes::unify(&t, &posint_oct_type) {
|
||||
crate::editors::list::PTYListStyle::for_node( &mut *et, ("0o", "", ""));
|
||||
crate::editors::list::PTYListController::for_node( &mut *et, None, None );
|
||||
}
|
||||
else if let Ok(σ) = laddertypes::unify(&t, &posint_dec_type) {
|
||||
crate::editors::list::PTYListStyle::for_node( &mut *et, ("0d", "", ""));
|
||||
crate::editors::list::PTYListController::for_node( &mut *et, None, None );
|
||||
}
|
||||
else if let Ok(σ) = laddertypes::unify(&t, &posint_hex_type) {
|
||||
crate::editors::list::PTYListStyle::for_node( &mut *et, ("0x", "", ""));
|
||||
crate::editors::list::PTYListController::for_node( &mut *et, None, None );
|
||||
}
|
||||
else if let Ok(σ) = laddertypes::unify(&t, &list_type) {
|
||||
let item_type = σ.get( &laddertypes::TypeID::Var(item_tyid) ).unwrap();
|
||||
|
||||
// choose style based on element type
|
||||
if *item_type == char_type {
|
||||
crate::editors::list::PTYListStyle::for_node( &mut *et, ("\"", "", "\""));
|
||||
crate::editors::list::PTYListController::for_node( &mut *et, None, Some('\"') );
|
||||
} else {
|
||||
crate::editors::list::PTYListStyle::for_node( &mut *et, ("{", ", ", "}"));
|
||||
crate::editors::list::PTYListController::for_node( &mut *et, Some(','), Some('}') );
|
||||
}
|
||||
//*et = nested_tty::editors::edittree_make_list_edit(et.clone());
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
|
@ -7,7 +7,8 @@ use {
|
|||
index::*,
|
||||
}
|
||||
},
|
||||
super::{TerminalStyle, TerminalView},
|
||||
crate::atom::{TerminalStyle},
|
||||
crate::{TerminalView},
|
||||
async_std::{stream::StreamExt, task},
|
||||
cgmath::{Point2, Vector2},
|
||||
signal_hook,
|
||||
|
@ -24,7 +25,7 @@ use {
|
|||
},
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub enum TerminalEvent {
|
||||
Resize(Vector2<i16>),
|
||||
Input(termion::event::Event),
|
71
lib-nested-tty/src/tty_application.rs
Normal file
71
lib-nested-tty/src/tty_application.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
use {
|
||||
cgmath::Vector2,
|
||||
nested::{
|
||||
edit_tree::EditTree,
|
||||
repr_tree::{Context, ReprTree},
|
||||
},
|
||||
crate::{
|
||||
terminal::TermOutWriter, DisplaySegment, Terminal, TerminalAtom, TerminalCompositor,
|
||||
TerminalEvent, TerminalStyle, TerminalView,
|
||||
},
|
||||
r3vi::{
|
||||
buffer::singleton::*,
|
||||
view::{port::UpdateTask, singleton::*, ViewPort},
|
||||
},
|
||||
std::sync::{Arc, Mutex, RwLock},
|
||||
termion::event::{Event, Key},
|
||||
};
|
||||
|
||||
pub struct TTYApplication {
|
||||
pub port: ViewPort<dyn TerminalView>,
|
||||
term_writer: Arc<TermOutWriter>,
|
||||
}
|
||||
|
||||
impl TTYApplication {
|
||||
pub fn new(event_handler: impl Fn(TerminalEvent) + Send + Sync + 'static) -> Self {
|
||||
let port = ViewPort::new();
|
||||
let portmutex = Mutex::new(());
|
||||
let term = Terminal::new(port.outer());
|
||||
let term_writer = term.get_writer();
|
||||
|
||||
async_std::task::spawn(TTYApplication::event_loop(term, port.clone(), Arc::new(event_handler)));
|
||||
async_std::task::spawn(TTYApplication::update_loop(port.clone()));
|
||||
|
||||
TTYApplication {
|
||||
port,
|
||||
term_writer,
|
||||
}
|
||||
}
|
||||
|
||||
/* this task handles all terminal events (e.g. key press, resize)
|
||||
*/
|
||||
async fn event_loop(mut term: Terminal, port: ViewPort<dyn TerminalView>, event_handler: Arc<dyn Fn(TerminalEvent) + Send + Sync>) {
|
||||
loop {
|
||||
let ev = term.next_event().await;
|
||||
if ev == TerminalEvent::Input(Event::Key(Key::Ctrl('d'))) {
|
||||
break;
|
||||
}
|
||||
|
||||
event_handler( ev );
|
||||
port.update();
|
||||
}
|
||||
}
|
||||
|
||||
/* this task will continuously pull forward
|
||||
* all notifications which are influencing
|
||||
* the view in `term_port`
|
||||
*/
|
||||
async fn update_loop(port: ViewPort<dyn TerminalView>) {
|
||||
loop {
|
||||
port.update();
|
||||
async_std::task::sleep(std::time::Duration::from_millis(50)).await;
|
||||
}
|
||||
}
|
||||
|
||||
/* write the changes in the view of `term_port` to the terminal
|
||||
*/
|
||||
pub async fn show(&self) -> Result<(), std::io::Error> {
|
||||
self.term_writer.show().await
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
[package]
|
||||
name = "fib"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
nested = { path = "../../nested" }
|
|
@ -1,62 +0,0 @@
|
|||
use std::{
|
||||
fs::File,
|
||||
io::{Read, Write},
|
||||
os::unix::io::FromRawFd,
|
||||
};
|
||||
|
||||
fn fib(n: u64) -> u64 {
|
||||
let mut y = 0;
|
||||
let mut y1 = 1;
|
||||
let mut y2 = 0;
|
||||
|
||||
for _ in 0..n {
|
||||
y = y1 + y2;
|
||||
y2 = y1;
|
||||
y1 = y;
|
||||
}
|
||||
|
||||
y
|
||||
}
|
||||
|
||||
fn main() {
|
||||
nested::magic_header();
|
||||
|
||||
eprintln!(" Fibonacci Sequence");
|
||||
|
||||
nested::magic_header();
|
||||
|
||||
eprintln!(
|
||||
"
|
||||
interface (Sequence ℕ) 0 1"
|
||||
);
|
||||
|
||||
let mut f0 = unsafe { File::from_raw_fd(0) };
|
||||
eprintln!(
|
||||
"
|
||||
>0: n
|
||||
( ℕ )
|
||||
( MachineInt )
|
||||
( MachineWord )
|
||||
( Stream MachineSyllab )
|
||||
"
|
||||
);
|
||||
|
||||
let mut f1 = unsafe { File::from_raw_fd(1) };
|
||||
eprintln!(
|
||||
"
|
||||
<1: n'th fibonacci number
|
||||
( ℕ )
|
||||
( MachineInt )
|
||||
( MachineWord )
|
||||
( Stream MachineSyllab )
|
||||
"
|
||||
);
|
||||
|
||||
nested::magic_header();
|
||||
|
||||
let mut bytes = [0 as u8; 8];
|
||||
f0.read_exact(&mut bytes).expect("");
|
||||
let n = u64::from_le_bytes(bytes);
|
||||
bytes = fib(n).to_le_bytes();
|
||||
f1.write(&bytes).expect("");
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
[package]
|
||||
name = "int2str"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
nested = { path = "../../nested" }
|
|
@ -1,36 +0,0 @@
|
|||
use std::{fs::File, io::Read, os::unix::io::FromRawFd};
|
||||
|
||||
fn main() {
|
||||
nested::magic_header();
|
||||
eprintln!(" Human-readably Print MachineInt");
|
||||
nested::magic_header();
|
||||
|
||||
let mut f0 = unsafe { File::from_raw_fd(0) };
|
||||
eprintln!(
|
||||
"
|
||||
>0:
|
||||
( ℕ )
|
||||
( MachineInt )
|
||||
( MachineWord )
|
||||
( Stream MachineSyllab )
|
||||
"
|
||||
);
|
||||
|
||||
eprintln!(
|
||||
"
|
||||
<1:
|
||||
( ℕ )
|
||||
( PositionalInt 10 BigEndian )
|
||||
( Sequence ( Digit 10 ) )
|
||||
( Sequence UTF-8-Char )
|
||||
( Stream UTF-8-Char )
|
||||
( Stream MachineSyllab )
|
||||
"
|
||||
);
|
||||
|
||||
nested::magic_header();
|
||||
|
||||
let mut bytes = [0 as u8; 8];
|
||||
f0.read_exact(&mut bytes).expect("");
|
||||
println!("{}", u64::from_le_bytes(bytes));
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
use nested::{
|
||||
core::{TypeDict, ViewPort},
|
||||
integer::RadixProjection,
|
||||
vec::VecBuffer,
|
||||
};
|
||||
|
||||
#[async_std::main]
|
||||
async fn main() {
|
||||
let mut td = TypeDict::new();
|
||||
for tn in vec![
|
||||
"MachineWord",
|
||||
"MachineInt",
|
||||
"MachineSyllab",
|
||||
"Vec",
|
||||
"Stream",
|
||||
"Json",
|
||||
"Sequence",
|
||||
"UTF-8-Char",
|
||||
"PositionalInt",
|
||||
"Digit",
|
||||
"LittleEndian",
|
||||
"BigEndian",
|
||||
"DiffStream",
|
||||
"ℕ",
|
||||
"$src_radix",
|
||||
"$dst_radix",
|
||||
] {
|
||||
td.add_typename(tn.into());
|
||||
}
|
||||
|
||||
let radix_types = vec![
|
||||
td.type_term_from_str("( ℕ )").unwrap(),
|
||||
td.type_term_from_str("( PositionalInt 10 LittleEndian )")
|
||||
.unwrap(),
|
||||
td.type_term_from_str("( Sequence ( Digit 10 ) )").unwrap(),
|
||||
td.type_term_from_str("( Sequence UTF-8-Char )").unwrap(),
|
||||
td.type_term_from_str("( Sequence MachineSyllab )").unwrap(),
|
||||
];
|
||||
|
||||
let src_types = vec![
|
||||
td.type_term_from_str("( ℕ )").unwrap(),
|
||||
td.type_term_from_str("( PositionalInt $src_radix LittleEndian )")
|
||||
.unwrap(),
|
||||
td.type_term_from_str("( Sequence ( Digit $src_radix ) )")
|
||||
.unwrap(),
|
||||
td.type_term_from_str("( Sequence MachineInt )").unwrap(),
|
||||
td.type_term_from_str("( DiffStream ( Vec MachineInt ) )")
|
||||
.unwrap(),
|
||||
td.type_term_from_str("( Json )").unwrap(),
|
||||
td.type_term_from_str("( Stream UTF-8-Char )").unwrap(),
|
||||
td.type_term_from_str("( Stream MachineSyllab )").unwrap(),
|
||||
];
|
||||
|
||||
let dst_types = vec![
|
||||
td.type_term_from_str("( ℕ )").unwrap(),
|
||||
td.type_term_from_str("( PositionalInt $dst_radix LittleEndian )")
|
||||
.unwrap(),
|
||||
td.type_term_from_str("( Sequence ( Digit $dst_radix ) )")
|
||||
.unwrap(),
|
||||
td.type_term_from_str("( Sequence MachineInt )").unwrap(),
|
||||
td.type_term_from_str("( DiffStream ( Vec MachineInt ) )")
|
||||
.unwrap(),
|
||||
td.type_term_from_str("( Json )").unwrap(),
|
||||
td.type_term_from_str("( Stream UTF-8-Char )").unwrap(),
|
||||
td.type_term_from_str("( Stream MachineSyllab )").unwrap(),
|
||||
];
|
||||
|
||||
nested::magic_header();
|
||||
eprintln!(" Convert Radix of Positional Integer");
|
||||
nested::magic_header();
|
||||
|
||||
eprintln!("\n$1: src_radix");
|
||||
for t in radix_types.iter() {
|
||||
eprintln!(" {}", td.type_term_to_str(t));
|
||||
}
|
||||
|
||||
eprintln!("\n$2: dst_radix");
|
||||
for t in radix_types.iter() {
|
||||
eprintln!(" {}", td.type_term_to_str(t));
|
||||
}
|
||||
|
||||
eprintln!("\n>0: n");
|
||||
for t in src_types.iter() {
|
||||
eprintln!(" {}", td.type_term_to_str(t));
|
||||
}
|
||||
|
||||
eprintln!("\n<1: n");
|
||||
for t in dst_types.iter() {
|
||||
eprintln!(" {}", td.type_term_to_str(t));
|
||||
}
|
||||
|
||||
nested::magic_header();
|
||||
|
||||
let mut args = std::env::args();
|
||||
args.next().expect("Arg $0 missing!");
|
||||
|
||||
let src_radix_str = args.next().expect("Arg $1 required!");
|
||||
let dst_radix_str = args.next().expect("Arg $2 required!");
|
||||
|
||||
let src_radix = usize::from_str_radix(&src_radix_str, 10).expect("could not parse src_radix");
|
||||
let dst_radix = usize::from_str_radix(&dst_radix_str, 10).expect("could not parse dst_radix");
|
||||
|
||||
assert!(src_radix > 1);
|
||||
assert!(dst_radix > 1);
|
||||
|
||||
let src_digits_port = ViewPort::new();
|
||||
let dst_digits_port = ViewPort::new();
|
||||
|
||||
let mut src_digits = VecBuffer::<usize>::new(src_digits_port.inner());
|
||||
|
||||
let _proj = RadixProjection::new(
|
||||
src_radix,
|
||||
dst_radix,
|
||||
src_digits_port.outer().to_sequence(),
|
||||
dst_digits_port.inner(),
|
||||
);
|
||||
|
||||
// output dst digits
|
||||
let writer = {
|
||||
use std::os::unix::io::FromRawFd;
|
||||
|
||||
dst_digits_port
|
||||
.outer()
|
||||
.serialize_json(unsafe { std::fs::File::from_raw_fd(1) })
|
||||
};
|
||||
|
||||
// start reading src digits
|
||||
{
|
||||
use async_std::os::unix::io::FromRawFd;
|
||||
|
||||
src_digits
|
||||
.from_json(unsafe { async_std::fs::File::from_raw_fd(0) })
|
||||
.await;
|
||||
}
|
||||
|
||||
drop(writer);
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
[package]
|
||||
name = "str2int"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
nested = { path = "../../nested" }
|
|
@ -1,69 +0,0 @@
|
|||
use std::{
|
||||
fs::File,
|
||||
io::{Read, Write},
|
||||
os::unix::io::FromRawFd,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
nested::magic_header();
|
||||
eprintln!(" Parse MachineInt from String");
|
||||
nested::magic_header();
|
||||
|
||||
eprintln!(
|
||||
"
|
||||
$1: radix
|
||||
( ℕ )
|
||||
( PositionalInt 10 BigEndian )
|
||||
( Sequence ( Digit 10 ) )
|
||||
( Sequence UTF-8-Char )
|
||||
( Sequence MachineSyllab )
|
||||
"
|
||||
);
|
||||
|
||||
eprintln!(
|
||||
"
|
||||
>0: n
|
||||
( ℕ )
|
||||
( PositionalInt $radix BigEndian )
|
||||
( Sequence ( Digit $radix ) )
|
||||
( Sequence UTF-8-Char )
|
||||
( Stream UTF-8-Char )
|
||||
( Stream MachineSyllab )
|
||||
"
|
||||
);
|
||||
|
||||
eprintln!(
|
||||
"
|
||||
<1: n
|
||||
( ℕ )
|
||||
( MachineInt )
|
||||
( MachineWord )
|
||||
( Stream MachineSyllab )
|
||||
"
|
||||
);
|
||||
|
||||
nested::magic_header();
|
||||
|
||||
let mut f0 = unsafe { File::from_raw_fd(0) };
|
||||
let mut f1 = unsafe { File::from_raw_fd(1) };
|
||||
|
||||
let mut args = std::env::args();
|
||||
args.next().expect("Arg $0 missing!");
|
||||
|
||||
let radix_str = args.next().expect("Arg $1 required!");
|
||||
|
||||
let radix = u32::from_str_radix(&radix_str, 10).expect("could not parse radix");
|
||||
if radix > 16 {
|
||||
panic!("invalid radix! (radix<=16 required)");
|
||||
}
|
||||
|
||||
let mut chars = Vec::new();
|
||||
f0.read_to_end(&mut chars).expect("");
|
||||
chars.retain(|c| (*c as char).is_alphanumeric());
|
||||
f1.write(
|
||||
&u64::from_str_radix(&String::from_utf8_lossy(&chars), radix)
|
||||
.unwrap()
|
||||
.to_le_bytes(),
|
||||
)
|
||||
.expect("");
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
|
||||
use {
|
||||
r3vi::{
|
||||
view::{OuterViewPort, singleton::*}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context},
|
||||
editors::{
|
||||
list::*,
|
||||
integer::*
|
||||
},
|
||||
type_system::{MorphismTypePattern},
|
||||
},
|
||||
std::sync::{Arc, RwLock}
|
||||
};
|
||||
|
||||
pub fn init_ctx(ctx: &mut Context) {
|
||||
ctx.add_typename("MachineInt".into());
|
||||
ctx.add_typename("u32".into());
|
||||
ctx.add_typename("u64".into());
|
||||
ctx.add_typename("LittleEndian".into());
|
||||
ctx.add_typename("BigEndian".into());
|
||||
|
||||
ctx.add_node_ctor(
|
||||
"Digit", Arc::new(
|
||||
|ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
|
||||
match ty {
|
||||
TypeTerm::App(args) => {
|
||||
if args.len() > 1 {
|
||||
match args[1] {
|
||||
TypeTerm::Num(radix) => {
|
||||
let node = DigitEditor::new(ctx.clone(), radix as u32).into_node(depth);
|
||||
Some(
|
||||
node
|
||||
)
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
ctx.add_list_typename("PosInt".into());
|
||||
let pattern = MorphismTypePattern {
|
||||
src_tyid: ctx.get_typeid("List"),
|
||||
dst_tyid: ctx.get_typeid("PosInt").unwrap()
|
||||
};
|
||||
ctx.add_morphism(pattern,
|
||||
Arc::new(
|
||||
|mut node, dst_type| {
|
||||
// todo: check src_type parameter to be ( Digit radix )
|
||||
|
||||
match dst_type {
|
||||
TypeTerm::App(args) => {
|
||||
if args.len() > 1 {
|
||||
match args[1] {
|
||||
TypeTerm::Num(_radix) => {
|
||||
PTYListController::for_node(
|
||||
&mut node,
|
||||
Some(','),
|
||||
None,
|
||||
);
|
||||
|
||||
PTYListStyle::for_node(
|
||||
&mut node,
|
||||
("0d", "", "")
|
||||
);
|
||||
|
||||
Some(node)
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
ctx.add_node_ctor(
|
||||
"PosInt", Arc::new(
|
||||
|ctx0: Arc<RwLock<Context>>, dst_typ: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
|
||||
match dst_typ.clone() {
|
||||
TypeTerm::App(args) => {
|
||||
if args.len() > 1 {
|
||||
match args[1] {
|
||||
TypeTerm::Num(radix) => {
|
||||
let ctx = ctx0.read().unwrap();
|
||||
let mut node = Context::make_node(
|
||||
&ctx0,
|
||||
TypeTerm::App(vec![
|
||||
TypeTerm::TypeID(ctx.get_typeid("List").unwrap()),
|
||||
TypeTerm::TypeID(
|
||||
ctx.get_typeid("Digit").unwrap()
|
||||
)
|
||||
.num_arg(radix)
|
||||
.clone()
|
||||
.into()
|
||||
]),
|
||||
depth.map(|d| d+1)
|
||||
).unwrap();
|
||||
|
||||
node = node.morph(dst_typ);
|
||||
|
||||
Some(node)
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
ctx.add_typename("Date".into());
|
||||
ctx.add_typename("ISO-8601".into());
|
||||
ctx.add_typename("TimeSince".into());
|
||||
ctx.add_typename("UnixEpoch".into());
|
||||
ctx.add_typename("AnnoDomini".into());
|
||||
ctx.add_typename("Epoch".into());
|
||||
ctx.add_typename("Duration".into());
|
||||
ctx.add_typename("Seconds".into());
|
||||
ctx.add_typename("ℕ".into());
|
||||
}
|
||||
|
|
@ -1,239 +0,0 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{
|
||||
OuterViewPort,
|
||||
singleton::*,
|
||||
},
|
||||
buffer::{
|
||||
singleton::*,
|
||||
vec::*,
|
||||
index_hashmap::*
|
||||
}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context, ReprTree},
|
||||
editors::list::{ListCmd, PTYListController, PTYListStyle},
|
||||
terminal::{
|
||||
TerminalAtom, TerminalStyle, make_label
|
||||
},
|
||||
diagnostics::{Message},
|
||||
tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
|
||||
commander::ObjCommander
|
||||
},
|
||||
std::sync::Arc,
|
||||
std::sync::RwLock,
|
||||
std::iter::FromIterator,
|
||||
cgmath::{Point2}
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub struct DigitEditor {
|
||||
ctx: Arc<RwLock<Context>>,
|
||||
radix: u32,
|
||||
data: SingletonBuffer<Option<char>>,
|
||||
msg: VecBuffer<Message>,
|
||||
}
|
||||
|
||||
impl ObjCommander for DigitEditor {
|
||||
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
|
||||
let cmd_obj = cmd_obj.read().unwrap();
|
||||
let cmd_type = cmd_obj.get_type().clone();
|
||||
|
||||
if cmd_type == Context::parse(&self.ctx, "Char") {
|
||||
if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
|
||||
let c = cmd_view.get();
|
||||
|
||||
self.msg.clear();
|
||||
|
||||
if self.ctx.read().unwrap().meta_chars.contains(&c) {
|
||||
eprintln!("digitedit: meta char");
|
||||
return TreeNavResult::Exit;
|
||||
|
||||
} else if c.to_digit(self.radix).is_none() {
|
||||
/* in case the character c is not in the range of digit-chars,
|
||||
add a message to the diagnostics view
|
||||
*/
|
||||
|
||||
let message = IndexBuffer::from_iter(vec![
|
||||
(Point2::new(1, 0), make_label("invalid digit '")),
|
||||
(Point2::new(2, 0), make_label(&format!("{}", c))
|
||||
.map_item(|_p,a| a.add_style_back(TerminalStyle::fg_color((140,140,250))))),
|
||||
(Point2::new(3, 0), make_label("'"))
|
||||
]);
|
||||
|
||||
self.msg.push(crate::diagnostics::make_error(message.get_port().flatten()));
|
||||
self.data.set(Some(c));
|
||||
} else {
|
||||
self.data.set(Some(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
}
|
||||
|
||||
impl DigitEditor {
|
||||
pub fn new(ctx: Arc<RwLock<Context>>, radix: u32) -> Self {
|
||||
DigitEditor {
|
||||
ctx,
|
||||
radix,
|
||||
data: SingletonBuffer::new(None),
|
||||
msg: VecBuffer::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_node(self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode {
|
||||
let data = self.get_data();
|
||||
let editor = Arc::new(RwLock::new(self));
|
||||
let ed = editor.write().unwrap();
|
||||
let r = ed.radix;
|
||||
|
||||
NestedNode::new(ed.ctx.clone(), data, depth)
|
||||
.set_cmd(editor.clone())
|
||||
.set_view(
|
||||
ed.data
|
||||
.get_port()
|
||||
.map(move |c| {
|
||||
TerminalAtom::new(
|
||||
c.unwrap_or('?'),
|
||||
if c.unwrap_or('?').to_digit(r).is_some() {
|
||||
TerminalStyle::fg_color((90, 160, 90))
|
||||
} else {
|
||||
//TerminalStyle::bg_color((90, 10, 10))
|
||||
TerminalStyle::fg_color((200, 40, 40))
|
||||
},
|
||||
)
|
||||
})
|
||||
.to_grid()
|
||||
)
|
||||
.set_diag(
|
||||
ed.msg.get_port().to_sequence()
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_data_port(&self) -> OuterViewPort<dyn SingletonView<Item = Option<u32>>> {
|
||||
let radix = self.radix;
|
||||
self.data.get_port().map(move |c| c?.to_digit(radix))
|
||||
}
|
||||
|
||||
pub fn get_type(&self) -> TypeTerm {
|
||||
TypeTerm::TypeID(self.ctx.read().unwrap().get_typeid("Digit").unwrap())
|
||||
}
|
||||
|
||||
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
|
||||
ReprTree::ascend(
|
||||
&ReprTree::new_leaf(
|
||||
self.ctx.read().unwrap().type_term_from_str("<Seq u32>").unwrap(),
|
||||
self.get_data_port().into()
|
||||
),
|
||||
self.get_type()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct PosIntEditor {
|
||||
radix: u32,
|
||||
digits: NestedNode,
|
||||
|
||||
// todo: endianness
|
||||
}
|
||||
|
||||
impl PosIntEditor {
|
||||
pub fn new(ctx: Arc<RwLock<Context>>, radix: u32) -> Self {
|
||||
let mut node = Context::make_node(
|
||||
&ctx,
|
||||
Context::parse(&ctx, format!("<List <Digit {}>>", radix).as_str()),
|
||||
r3vi::buffer::singleton::SingletonBuffer::new(0).get_port()
|
||||
).unwrap();
|
||||
|
||||
// Set Type
|
||||
node.data = ReprTree::ascend(
|
||||
&node.data.clone(),
|
||||
TypeTerm::App(vec![
|
||||
TypeTerm::TypeID(ctx.read().unwrap().get_typeid("PosInt").unwrap()),
|
||||
TypeTerm::Num(radix as i64).into(),
|
||||
TypeTerm::TypeID(ctx.read().unwrap().get_typeid("BigEndian").unwrap())
|
||||
]
|
||||
));
|
||||
|
||||
PTYListController::for_node( &mut node, Some(' '), None );
|
||||
PTYListStyle::for_node( &mut node,
|
||||
(
|
||||
match radix {
|
||||
2 => "0b".into(),
|
||||
8 => "0o".into(),
|
||||
10 => "0d".into(),
|
||||
16 => "0x".into(),
|
||||
_ => "".into()
|
||||
},
|
||||
"".into(),
|
||||
"".into()
|
||||
)
|
||||
);
|
||||
|
||||
PosIntEditor {
|
||||
radix,
|
||||
digits: node
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_u64(ctx: Arc<RwLock<Context>>, radix: u32, value: u64) -> Self {
|
||||
let mut edit = PosIntEditor::new(ctx, radix);
|
||||
edit.set_value_u64( value );
|
||||
edit
|
||||
}
|
||||
|
||||
pub fn set_value_u64(&mut self, mut value: u64) {
|
||||
self.digits.send_cmd_obj(ListCmd::Clear.into_repr_tree(&self.digits.ctx));
|
||||
|
||||
while value > 0 {
|
||||
let digit_val = (value % self.radix as u64) as u32;
|
||||
value /= self.radix as u64;
|
||||
|
||||
// if BigEndian
|
||||
self.digits.goto(TreeCursor::home());
|
||||
|
||||
self.digits.send_cmd_obj(ReprTree::from_char(&self.digits.ctx, char::from_digit(digit_val, self.radix).expect("invalid digit")));
|
||||
}
|
||||
self.digits.goto(TreeCursor::none());
|
||||
}
|
||||
|
||||
pub fn into_node(self) -> NestedNode {
|
||||
self.digits
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = u32>> {
|
||||
let radix = self.radix;
|
||||
self.digits
|
||||
.get_data_port()
|
||||
.filter_map(move |digit_editor| {
|
||||
digit_editor.read().unwrap().data.get()?.to_digit(radix)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_value(&self) -> u32 {
|
||||
let mut value = 0;
|
||||
let mut weight = 1;
|
||||
for digit_value in self
|
||||
.get_data_port()
|
||||
.get_view()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.rev()
|
||||
{
|
||||
value += digit_value * weight;
|
||||
weight *= self.radix;
|
||||
}
|
||||
|
||||
value
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
pub mod add;
|
||||
pub mod editor;
|
||||
pub mod radix;
|
||||
pub mod ctx;
|
||||
|
||||
pub use {
|
||||
add::Add,
|
||||
editor::{DigitEditor, PosIntEditor},
|
||||
radix::RadixProjection,
|
||||
ctx::init_ctx
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue