Compare commits

...

56 commits
dev ... wip

Author SHA1 Message Date
10cbeb52a3
wip 2024-08-10 13:18:25 +02:00
0bcfd7a65a
call edittree_hook in morphisms already, add edittree() getter in ReprTreeExt to further simplify application code 2024-08-09 23:00:31 +02:00
7762fa4b12
simplify posint example
remove setup_hex_master() / setup_dec_master() functions and instead directly call apply_morphism()
2024-08-09 02:33:48 +02:00
786866746c
integer radix convert: insert one zero digit in case value is zero 2024-08-09 02:31:26 +02:00
8d637a6f32
add ReprTree::from_str() to simplify creation of initial representation nodes 2024-08-06 16:29:28 +02:00
6e2b82585e
in context.apply_morphism() now use find_morphism_path() to automatically find chained morphisms to create projections in ReprTree 2024-08-06 16:20:02 +02:00
ffeb4b8e73
repr tree: create new VecBuffer in case attach_to() is called on Vec<EditTree> 2024-08-06 15:40:05 +02:00
508e716a6a
repr tree: split leaf & node into separate files 2024-08-04 19:27:36 +02:00
4c0e9da2d3
fixup examples
also fix behaviour of insert_leaf() & attach_leaf_to() when type of current repr-node occurs inside the type of the leaf
2024-08-03 15:44:04 +02:00
830ce613ea
example: two editors with different radices 2024-08-02 22:43:00 +02:00
a3c701ce88
automatically generate list-map morphisms in find_morphism()
this allows us to now to create <List EditTree> from <List Char>
with apply_morphism()
2024-08-02 21:58:14 +02:00
6e8bb0aeb5
apply_list_map_morphism 2024-08-01 18:35:57 +02:00
e86070da50
fixes to make dual-editor with big/little endian projection work 2024-07-21 18:16:43 +02:00
bb846afc7c
ReprTree: add detach functions & attach_to helpers for Arc<ReprTree> 2024-06-06 15:21:52 +02:00
ab51ea5d3d
rename pty&tty servers 2024-06-05 02:16:09 +02:00
cdf03c9aae
improve morphisms for integer example 2024-06-03 17:10:52 +02:00
d02f33ee17
ReprTree: add halo type 2024-05-31 00:07:25 +02:00
fdecc29e80
clean up posint example & use u64 instead of usize in PositionalUInt trait 2024-05-30 23:11:50 +02:00
40a5da4512
int example & testing out more int projections 2024-05-25 00:39:47 +02:00
91e56d876d
digit editor: create char repr if not available 2024-03-23 21:32:12 +01:00
edf088b853
add vec-access to ReprTree and morphism to collect <List Char> to <Vec Char> 2024-03-23 20:57:07 +01:00
473dd5f4dc
add short READMEs for examples 2024-03-21 18:17:04 +01:00
33e97ed5e3
cleanup examples
- move initialization of edittree-hook into lib-nested-tty
- split examples into separate digit/string examples
2024-03-21 13:27:09 +01:00
ecaa74ccfd
add morphism to extract value-list from ListEditor 2024-03-21 10:37:24 +01:00
658f5c1000
refactor ReprTree
- ReprLeaf with In- & Out-Ports
- Optional Buffers
2024-03-15 18:54:45 +01:00
03dc9f1133
add ReprTreeExt trait for Arc<Rwlock<>> 2024-03-10 19:27:51 +01:00
d7d0a46c7b
move digit into separate module 2024-03-10 16:17:24 +01:00
77d9e64531
add notes, formatting, shallow simplifications 2024-03-10 14:04:08 +01:00
73d457ba24
fix dependencies in pty-server & display-server-tty 2024-02-10 23:21:22 +01:00
647a5d77b6
list: reactivate item creation on split 2024-01-23 22:00:38 +01:00
e46c143dec
test different style for <List Char>, add meta-chars to ctx globally to avoid deadlock 2024-01-18 19:44:14 +01:00
0ac4a34743
example wip: create display for edit tree 2024-01-18 19:44:11 +01:00
863fe95848
example wip 2024-01-18 19:44:08 +01:00
fdf2d60b35
MorphismBase: fix deadlock 2024-01-18 19:44:04 +01:00
8471c7a90f
move morphism to editors/char mod 2024-01-18 19:44:02 +01:00
caa0c9a5c0
define char-editor constructor as morphism 2024-01-18 19:43:59 +01:00
668b0b8b96
rename NestedNode to EditTree 2024-01-18 19:43:57 +01:00
47a35f22b7
some work on repr tree example 2024-01-18 19:43:54 +01:00
97a5b580df
wip: deactivate code to make it compileable 2024-01-18 19:43:45 +01:00
193b8c8cac
implement MorphismBase, remove data from NestedNode 2024-01-18 19:32:49 +01:00
834bb49b5e
add tty/pty server as separate crates 2024-01-18 19:05:25 +01:00
be3eefc3a5
edit tree: split node struct into sub structs 2023-11-29 18:12:04 +01:00
bee1b43ddc
tty displaySegment: shorten error labels 2023-11-29 17:44:37 +01:00
6a3afde29c
tty application: set shorter update interval 2023-11-29 17:38:30 +01:00
39fbae7740
remove debug prints 2023-11-29 17:37:47 +01:00
d15077aca0
add TreeNavCmd and keymap functions 2023-11-29 02:22:44 +01:00
25d8acdb72
first steps in reactivating pty-list editor 2023-11-29 01:23:41 +01:00
85b614a9bb
further restructuring 2023-11-28 20:52:25 +01:00
f151f9c5d2
add second example with TTYApplication & Char-View 2023-11-28 17:31:37 +01:00
57cb1ee3ff
add TTYApplication 2023-11-28 17:16:51 +01:00
9b9ea77cb0
add lib-nested-tty::DisplaySegment trait for Node 2023-11-28 17:16:23 +01:00
f3ad5c78d7
rename submodules to reprTree & editTree 2023-11-27 04:18:46 +01:00
b1c17da75f
remove bimap (no longer needed since it is in lib-laddertypes now) 2023-11-26 22:16:54 +01:00
ea38b0f9b0
add hello world example 2023-11-26 22:09:03 +01:00
f8e872acda
Cargo.toml remove unneccesary dependencies 2023-11-26 22:08:43 +01:00
4bf03c356d
wip refactor crates 2023-11-26 03:26:00 +01:00
111 changed files with 4869 additions and 2440 deletions

View file

@ -1,10 +1,16 @@
[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-color"
]

View file

@ -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"]

View 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.

View 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!");
}

View 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"]

View 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.

View 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>
* / | \
* / | \
* / | \
* u32 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!");
}

View 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"]

View 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.

View file

@ -0,0 +1,168 @@
//! 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"
);
/* 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 = 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()
.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);
}

View 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"]

View 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

View file

@ -0,0 +1,248 @@
//! 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().apply_morphism(
&rt_int,
&nested::repr_tree::morphism::MorphismType {
src_type: Context::parse(&ctx, " ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char> ~ <Vec Char>"),
dst_type: Context::parse(&ctx, " ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16>> ~ EditTree")
});
return;
/* set Hex-editor to be master
*/
rt_int.write().unwrap().detach( &ctx );
ctx.read().unwrap().apply_morphism(
&rt_int,
&laddertypes::MorphismType {
src_type: Context::parse(&ctx, " ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char> ~ EditTree"),
dst_type: Context::parse(&ctx, " ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ EditTree >")
// dst_type: Context::parse(&ctx, " ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ EditTree")
}
);
return;
/*
ctx.read().unwrap().apply_morphism(
&rt_int,
&laddertypes::MorphismType {
src_type: Context::parse(&ctx, " ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16> ~ Char> ~ EditTree"),
dst_type: Context::parse(&ctx, " ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ EditTree")
}
);
*/
let edittree_hex_be_list =
rt_int
.descend(Context::parse(&ctx, "
<PosInt 16 BigEndian>
~ <Seq~List <Digit 16>>
")).unwrap()
.edittree( &ctx );
/*
let edittree_dec_be_list =
rt_int
.descend(Context::parse(&ctx, "
<PosInt 10 BigEndian>
~ <Seq~List <Digit 10>~Char>
")).unwrap()
.edittree( &ctx );
let hex_digits_view = rt_int.descend(Context::parse(&ctx, "
<PosInt 16 LittleEndian>
~ <Seq <Digit 16> >
~ <List <Digit 16>
~ _2^64
~ machine.UInt64 >
")).expect("descend")
.view_list::<u64>()
.map(|v| TerminalAtom::from(char::from_digit(*v as u32, 16)))
.to_sequence()
.to_grid_horizontal();
let dec_digits_view = rt_int.descend(Context::parse(&ctx, "
<PosInt 10 LittleEndian>
~ <Seq <Digit 10>>
~ <List <Digit 10>
~ _2^64
~ machine.UInt64 >
")).expect("descend")
.view_list::<u64>()
.map(|v| TerminalAtom::from(char::from_digit(*v as u32, 10)))
.to_sequence()
.to_grid_horizontal();
*/
/* list of both editors
*/
let mut list_editor = nested::editors::list::ListEditor::new(ctx.clone(), Context::parse(&ctx, "<Seq Char>"));
list_editor.data.push( edittree_hex_be_list.get() );
//list_editor.data.push( edittree_dec_be_list.get() );
let mut edittree = list_editor.into_node(SingletonBuffer::new(0).get_port());
/* cursors are a bit screwed initially so fix them up
* TODO: how to fix this generally?
*/
edittree_hex_be_list.get().write().unwrap().goto(TreeCursor::none());
//edittree_dec_be_list.get().write().unwrap().goto(TreeCursor::none());
edittree.goto(TreeCursor{
leaf_mode: nested::editors::list::ListCursorMode::Insert,
tree_addr: vec![0,0]
});
let edittree = Arc::new(RwLock::new(edittree));
/* setup terminal
*/
let app = TTYApplication::new({
/* event handler
*/
let ctx = ctx.clone();
let rt_int = rt_int.clone();
let last_idx = RwLock::new(1);
move |ev| {
let cur = edittree.read().unwrap().get_cursor();
if cur.tree_addr.len() > 0 {
match cur.tree_addr[0] {
0 => {
let mut li = last_idx.write().unwrap();
if *li != 0 {
rt_int.write().unwrap().detach( &ctx );
ctx.read().unwrap().apply_morphism(&rt_int, &laddertypes::MorphismType {
src_type: Context::parse(&ctx, " ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char> ~ EditTree"),
dst_type: Context::parse(&ctx, " ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10> ~ Char> ~ EditTree")
});
*li = 0;
}
}
1 => {
let mut li = last_idx.write().unwrap();
if *li != 1 {
rt_int.write().unwrap().detach( &ctx );
ctx.read().unwrap().apply_morphism(&rt_int, &laddertypes::MorphismType {
src_type: Context::parse(&ctx, " ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10> ~ Char> ~ EditTree"),
dst_type: Context::parse(&ctx, " ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char> ~ EditTree")
});
*li = 1;
}
}
_=>{}
}
}
edittree.write().unwrap().send_cmd_obj(ev.to_repr_tree(&ctx));
}
});
/* Setup the compositor to serve as root-view
* by routing it to the `app.port` Viewport,
* so it will be displayed on TTY-output.
*/
let compositor = TerminalCompositor::new(app.port.inner());
/* Now add some views to our compositor
*/
{
let mut comp = compositor.write().unwrap();
fn show_edit_tree( ctx: &Arc<RwLock<Context>>, comp: &mut TerminalCompositor, rt: &Arc<RwLock<ReprTree>>, y: i16 )
{
let rt_edittree = rt.descend(Context::parse(&ctx, "EditTree")).expect("descend");
let halo_type = rt_edittree.read().unwrap().get_halo_type().clone();
let edittree = rt_edittree.read().unwrap().get_view::<dyn r3vi::view::singleton::SingletonView<Item = Arc<RwLock<EditTree>>>>().unwrap().get().read().unwrap().clone();
comp.push( nested_tty::make_label( &ctx.read().unwrap().type_term_to_str(&halo_type) )
.map_item(|_pt, atom| atom.add_style_front(TerminalStyle::fg_color((90,90,90))))
.offset(Vector2::new(1,y)));
comp.push( edittree.display_view()
.offset(Vector2::new(1,y+1)));
}
show_edit_tree(&ctx, &mut comp, &rt_int.descend(Context::parse(&ctx, "<PosInt 16 BigEndian> ~ <Seq~List <Digit 16>~Char>")).expect(""), 1);
//show_edit_tree(&ctx, &mut comp, &rt_int.descend(Context::parse(&ctx, "<PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char>")).expect(""), 4);
/* project the seq of u64 representations to a view
*/
/*
comp.push(nested_tty::make_label("dec: ").offset(Vector2::new(3,7)));
comp.push(dec_digits_view.offset(Vector2::new(8,7)).map_item(|_,a| {
a.add_style_back(TerminalStyle::fg_color((30,90,200)))
}));
comp.push(nested_tty::make_label("hex: ").offset(Vector2::new(3,8)));
comp.push(hex_digits_view.offset(Vector2::new(8,8)).map_item(|_,a| {
a.add_style_back(TerminalStyle::fg_color((200, 200, 30)))
}));
*/
}
/* write the changes in the view of `term_port` to the terminal
*/
app.show().await.expect("output error!");
}

View 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"]

View file

@ -0,0 +1,175 @@
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);
let dict = Arc::new(RwLock::new(std::collections::HashMap::<String, u64>::new()));
dict.write().unwrap().insert( "red".into(), 0 );
dict.write().unwrap().insert( "green".into(), 1 );
dict.write().unwrap().insert( "blue".into(), 2 );
let symbol_morph_str_to_u64 = nested::repr_tree::GenericReprTreeMorphism::new(
Context::parse(&ctx, "Symbol ~ <Seq~List~Vec Char>"),
Context::parse(&ctx, "Symbol ~ ~ machine.UInt64"),
{
let ctx = ctx.clone();
let dict = dict.clone();
move |rt, σ| {
let str_view = rt
.descend(Context::parse(&ctx, "Symbol ~ <Seq~List~Vec Char>")).unwrap()
.vec_buffer::<char>()
.get_port();
let u64_view = str_view
.to_singleton()
.map({
let dict = dict.clone();
let old_value = Arc::new(RwLock::new(0));
move |chars| {
let str_val = chars.iter().collect::<String>();
let dict = dict.read().unwrap();
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, "~ machine.UInt64"),
u64_view
);
}
}
);
ctx.write().unwrap().morphisms.add_morphism( symbol_morph_str_to_u64 );
let mut symbol_rt = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, "
Symbol ~ <Seq~List~Vec Char>
"),
"red"
);
// this is required to initialize the <Vec EditTree> representation,
// and to take the value from <Vec Char>
ctx.read().unwrap().apply_morphism( &symbol_rt,
&laddertypes::MorphismType {
src_type: Context::parse(&ctx, "Symbol ~ <Seq~List~Vec Char>"),
dst_type: Context::parse(&ctx, "Symbol ~ <Seq~List Char> ~ EditTree")
});
symbol_rt.write().unwrap().detach( &ctx );
ctx.read().unwrap().apply_morphism( &symbol_rt,
&laddertypes::MorphismType {
dst_type: Context::parse(&ctx, "Symbol ~ <Seq~List~Vec Char>"),
src_type: Context::parse(&ctx, "Symbol ~ <Seq~List Char> ~ EditTree")
});
ctx.read().unwrap().apply_morphism( &symbol_rt,
&laddertypes::MorphismType {
src_type: Context::parse(&ctx, "Symbol ~ <Seq~List~Vec Char>"),
dst_type: Context::parse(&ctx, "Symbol ~ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char> ~ EditTree")
});
let symbol1_str_edit = symbol_rt.descend(Context::parse(&ctx, "
Symbol ~ <Seq~List Char>
")).unwrap().edittree( &ctx );
let symbol1_nat_edit = symbol_rt.descend(Context::parse(&ctx, "
Symbol ~ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char>
")).unwrap().edittree( &ctx );
symbol1_nat_edit.get().write().unwrap().goto(TreeCursor::none());
/* setup terminal
*/
let app = TTYApplication::new({
/* event handler
*/
let ctx = ctx.clone();
let edit = symbol1_str_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, &symbol_rt.descend(Context::parse(&ctx, "Symbol ~ <Seq~List Char>")).unwrap(), 1 );
show_edit_tree( &ctx, &mut comp, &symbol_rt.descend(Context::parse(&ctx, "Symbol ~ ~ <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!");
}

View 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"]

View 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!");
}

View 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"] }

View file

@ -4,6 +4,14 @@ use {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
enum GravityMode {
// tries to maintain a set distance from bottom
Gravity(usize),
// keeps equal distance from root
Floating
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct TreeCursor {
pub leaf_mode: ListCursorMode,

View 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()
}
}

View file

@ -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
};

View file

@ -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()
}
}

View file

@ -0,0 +1,228 @@
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, 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< Arc<RwLock< EditTree >> >
>>,
/// 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()
}
}

View file

@ -2,7 +2,7 @@
use {
laddertypes::{TypeTerm, TypeID},
crate::{
tree::{TreeAddr}
edit_tree::{TreeAddr}
}
};

View file

@ -0,0 +1,159 @@
use {
r3vi::{
view::{
OuterViewPort,
singleton::*,
port::UpdateTask
},
buffer::singleton::*
},
laddertypes::{TypeTerm},
crate::{
repr_tree::{Context, ReprTree, ReprLeaf, ReprTreeExt, GenericReprTreeMorphism},
edit_tree::{EditTree, TreeNavResult},
editors::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
// SingletonBuffer::new(0).get_port()
);
}
}
);
let char_morph_from_edittree = GenericReprTreeMorphism::new(
Context::parse(&ctx, "Char~EditTree"),
Context::parse(&ctx, "Char"),
{
let ctx = ctx.clone();
move |rt, σ|
{
/*
let mut b = rt
.descend(Context::parse(&ctx, "EditTree")).unwrap()
.view_singleton::<Arc<RwLock<EditTree>>>();
rt.attach_leaf_to(
Context::parse(&ctx, "Char"),
b.map(|x|
x.read().unwrap()
.get_edit::<CharEditor>().unwrap()
.read().unwrap()
.get())
);
*/
}
});
ctx.write().unwrap().morphisms.add_morphism( char_morph_to_edittree );
ctx.write().unwrap().morphisms.add_morphism( char_morph_from_edittree );
}
pub struct CharEditor {
ctx: Arc<RwLock<Context>>,
data: SingletonBuffer<char>
}
impl ObjCommander for CharEditor {
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 value = cmd_view.get();
if self.ctx.read().unwrap().meta_chars.contains(&value) {
TreeNavResult::Exit
} else {
self.data.set(value);
TreeNavResult::Continue
}
} else {
TreeNavResult::Exit
}
} else {
TreeNavResult::Exit
}
}
}
impl CharEditor {
pub fn new(ctx: Arc<RwLock<Context>>) -> Self {
CharEditor {
ctx,
data: SingletonBuffer::new('\0')
}
}
pub fn get_port(&self) -> OuterViewPort<dyn SingletonView<Item = char>> {
self.data.get_port()
}
pub fn get(&self) -> char {
self.get_port().get_view().unwrap().get()
}
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() }));
EditTree::new(
ctx0.clone(),
depth
)
.set_cmd( editor.clone() )
.set_editor( editor.clone() )
}
}

View 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
}
}

View file

@ -0,0 +1,142 @@
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_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_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_morph_char_to_edittree );
ctx.write().unwrap().morphisms.add_morphism( digit_morph_char_to_u64 );
ctx.write().unwrap().morphisms.add_morphism( digit_morph_u64_to_char );
}

View file

@ -0,0 +1,94 @@
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_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()
)
}
*/
}

View file

@ -0,0 +1,8 @@
pub mod ctx;
pub mod cmd;
pub mod editor;
pub use editor::DigitEditor;
pub use ctx::init_ctx;

View file

@ -0,0 +1,223 @@
use {
r3vi::{
view::{OuterViewPort, singleton::*, list::*}
},
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>"),
Context::parse(&ctx, " ~ machine.UInt64"),
{
let ctx = ctx.clone();
move |rt, σ| {
/*
let u64_view = rt
.descend(Context::parse(&ctx, "~ <PosInt 2^64 LittleEndian> ~ <Seq~List <Digit 2^64>~_2^64~machine.UInt64>"),
.view_list()
.to_singleton()
.map(||{
})
rt.attach_leaf_to(
Context::parse(&ctx, " ~ machine.UInt64")).unwrap()
u64_view
);
*/
}
}
);
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 );
}

View 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
}
*/
}

View file

@ -0,0 +1,148 @@
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) {
val += r * self.get(&i).unwrap();
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);
}
}

View 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
}
*/
}
}

View file

@ -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,7 +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>>() {
if let Some(view) = cmd_repr.get_view::<dyn SingletonView<Item = EditTree>>() {
let node = view.get();
let cur = self.cursor.get();
@ -58,7 +57,6 @@ impl ObjCommander for ListEditor {
}
else if let Some(cmd) = cmd_repr.get_view::<dyn SingletonView<Item = ListCmd>>() {
eprintln!("pty-list-editor some list cmmd");
let cur = self.cursor.get();
drop(cmd_repr);
@ -77,7 +75,6 @@ impl ObjCommander for ListEditor {
match cmd.get() {
ListCmd::DeletePxev => {
eprintln!("SELECT: delete pxev");
if idx > 0
&& item_cur.tree_addr.iter().fold(
true,
@ -119,7 +116,6 @@ impl ObjCommander for ListEditor {
}
}
} else {
eprintln!("ptylist: no item");
TreeNavResult::Exit
}
},
@ -127,7 +123,6 @@ impl ObjCommander for ListEditor {
ListCursorMode::Insert => {
match cmd.get() {
ListCmd::DeletePxev => {
eprintln!("INSERT: delete pxev");
self.delete_pxev();
TreeNavResult::Continue
}
@ -150,7 +145,6 @@ impl ObjCommander for ListEditor {
}
}
} else {
eprintln!("ptylist: cursor has no idx");
TreeNavResult::Exit
}
}

View 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, 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~EditTree>~<Vec EditTree>")
.apply_substitution(&|id| σ.get(id).cloned()).clone()
)
.expect("cant descend src repr");
let item_vec_buffer = item_vec_rt.vec_buffer::< Arc<RwLock<EditTree>> >();
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_editsetup2 = GenericReprTreeMorphism::new(
Context::parse(&ctx, "<List Char>~EditTree"),
Context::parse(&ctx, "<List Char>"),
{
let ctx = ctx.clone();
move |src_rt, σ| {
let edittree =
src_rt
.descend(Context::parse(&ctx, "<List Char>~EditTree")).unwrap()
.singleton_buffer::<Arc<RwLock<EditTree>>>();
let list_edit = edittree.get().read().unwrap().get_edit::< ListEditor >().unwrap();
let edittree_items = list_edit.read().unwrap().data.get_port().to_list();
src_rt.insert_leaf(
Context::parse(&ctx, "<List Char>"),
ReprLeaf::from_view(
edittree_items
.map(|edittree_char|
edittree_char
.read().unwrap()
.get_edit::<CharEditor>().unwrap()
.read().unwrap()
.get()
)
)
);
}
}
);
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
.descend(
Context::parse(&ctx, "<List Item>~EditTree")
.apply_substitution(&|x| σ.get(x).cloned()).clone()
).unwrap()
.singleton_buffer::<Arc<RwLock<EditTree>>>();
let list_edit = edittree.get().read().unwrap().get_edit::< ListEditor >().unwrap();
let edittree_items = list_edit.read().unwrap().data.get_port().to_list();
src_rt.attach_leaf_to(
Context::parse(&ctx, "<List Item> ~ <List EditTree>")
.apply_substitution(&|x| σ.get(x).cloned()).clone(),
edittree_items
);
}
}
);
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 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 p =
src_rt
.descend(Context::parse(&ctx, "<List EditTree>")).expect("descend")
.get_port::<dyn ListView< Arc<RwLock<EditTree>> >>().unwrap();
src_rt.attach_leaf_to(
Context::parse(&ctx, "<List EditTree> ~ <Vec EditTree>"),
p
);
}
}
);
ctx.write().unwrap().morphisms.add_morphism( list_morph_editsetup1 );
ctx.write().unwrap().morphisms.add_morphism( list_morph_editsetup2 );
ctx.write().unwrap().morphisms.add_morphism( list_morph_from_vec_char );
ctx.write().unwrap().morphisms.add_morphism( list_morph_to_vec_char );
ctx.write().unwrap().morphisms.add_morphism( list_morph_to_vec_edittree );
}

View file

@ -1,15 +1,13 @@
use {
r3vi::{
view::{ViewPort, OuterViewPort, singleton::*, sequence::*},
view::{OuterViewPort, singleton::*, sequence::*},
buffer::{singleton::*, vec::*}
},
laddertypes::{TypeTerm},
crate::{
type_system::{Context, ReprTree},
editors::list::{ListCursor, ListCursorMode, ListCmd},
tree::{NestedNode, TreeNav, TreeCursor},
diagnostics::Diagnostics,
commander::ObjCommander
repr_tree::{Context, ReprTree},
edit_tree::{EditTree, TreeNav, TreeCursor, diagnostics::Diagnostics},
editors::{list::{ListCursor, ListCursorMode, ListCmd}, ObjCommander},
},
std::sync::{Arc, RwLock}
};
@ -17,31 +15,41 @@ use {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct ListEditor {
pub(super) cursor: SingletonBuffer<ListCursor>,
pub cursor: SingletonBuffer<ListCursor>,
pub data: VecBuffer< Arc<RwLock<EditTree>> >,
// todo: (?) remove RwLock<..> around NestedNode ??
pub data: VecBuffer< Arc<RwLock<NestedNode>> >,
pub spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
pub spillbuf: Arc<RwLock<Vec<Arc<RwLock<EditTree>>>>>,
pub(super) addr_port: OuterViewPort<dyn SequenceView<Item = isize>>,
pub(super) mode_port: OuterViewPort<dyn SingletonView<Item = ListCursorMode>>,
// pub(super) grav_port: OuterViewPort<dyn SingletonView<Item = isize>>,
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<Arc<RwLock<EditTree>>>
) -> Self {
let cursor = SingletonBuffer::new(ListCursor::default());
let data : VecBuffer<Arc<RwLock<NestedNode>>> = VecBuffer::new();
ListEditor {
mode_port: cursor
@ -57,7 +65,6 @@ impl ListEditor {
if idx >= 0 && idx < data.len() as isize {
data.get(idx as usize).read().unwrap().get_mode_view()
} else {
eprintln!("ListEditor::mode_port invalid cursor idx");
ip
}
} else {
@ -103,8 +110,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,15 +118,14 @@ 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()
.enumerate()
.map(
|(idx, item_editor)| {
.map(|(idx, item_editor)| {
let idx = *idx;
item_editor
.get_msg_port()
@ -131,12 +136,11 @@ impl ListEditor {
msg
}
)
}
)
})
.flatten()
);
node.spillbuf = e.spillbuf.clone();
node.ctrl.spillbuf = e.spillbuf.clone();
node
}
@ -155,12 +159,12 @@ impl ListEditor {
self.cursor.get_port()
}
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = NestedNode>> {
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = EditTree>> {
self.data.get_port().to_sequence().map(
|x| x.read().unwrap().clone()
)
}
/*
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
let data_view = self.get_data_port();
ReprTree::new_leaf(
@ -168,8 +172,8 @@ impl ListEditor {
data_view.into()
)
}
pub fn get_item(&self) -> Option<NestedNode> {
*/
pub fn get_item(&self) -> Option<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() {
@ -180,9 +184,9 @@ impl ListEditor {
} else {
None
}
}
}
pub fn get_item_mut(&mut self) -> Option<MutableVecAccess<Arc<RwLock<NestedNode>>>> {
pub fn get_item_mut(&mut self) -> Option<MutableVecAccess<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() {
@ -233,10 +237,8 @@ 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: Arc<RwLock<EditTree>>) {
item.read().unwrap().disp.depth.0.set_view(
self.depth.map(|d| d+1).get_view()
);
@ -248,7 +250,6 @@ 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());
cur.idx = Some(idx + 1);
}
@ -264,13 +265,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,7 +304,6 @@ 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() {
@ -317,22 +315,33 @@ impl ListEditor {
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();
let mut b = item.ctrl.spillbuf.write().unwrap();
let rt = ReprTree::new_arc(self.typ.clone());
let mut et = self.ctx.read().unwrap()
.setup_edittree(
&rt
// , self.depth.map(|d| d+1)
);
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 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(
ReprTree::from_singleton_buffer(
Context::parse(&self.ctx, "EditTree"),
SingletonBuffer::<EditTree>::new(
node.read().unwrap().clone()
).get_port().into()
)
)
);
}
b.clear();
drop(b);
drop(item);
@ -341,11 +350,14 @@ impl ListEditor {
if cur.tree_addr.len() > 1 {
tail_node.dn();
}
drop(tail_node);
self.insert(
Arc::new(RwLock::new(tail_node))
edittree.value.read().unwrap().clone()
);
}
} else {
self.up();
self.listlist_split();
@ -376,14 +388,14 @@ 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(
ReprTree::from_singleton_buffer(
Context::parse(&self.ctx, "EditTree"),
SingletonBuffer::<EditTree>::new(
x.read().unwrap().clone()
).get_port().into()
)
)
);
}
@ -434,15 +446,15 @@ 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(
ReprTree::from_singleton_buffer(
Context::parse(&self.ctx, "EditTree"),
SingletonBuffer::<EditTree>::new(
x.read().unwrap().clone()
).get_port().into()
)
)
);
}

View file

@ -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
};

View file

@ -11,7 +11,7 @@ use {
ListCursor, ListCursorMode,
editor::ListEditor
},
tree::{TreeCursor, TreeNav, TreeNavResult, TreeHeightOp}
edit_tree::{TreeCursor, TreeNav, TreeNavResult, TreeHeightOp}
},
cgmath::Vector2
};
@ -195,7 +195,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)
@ -367,7 +366,6 @@ 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 );
@ -387,7 +385,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 +393,6 @@ impl TreeNav for ListEditor {
drop(cur_item);
eprintln!("CROSS: goto {:?}", new_addr);
cur.tree_addr = new_addr;
self.goto(cur)
} else {

View file

@ -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,
@ -124,7 +88,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());

View file

@ -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;
}

View file

@ -12,10 +12,6 @@ use {
laddertypes::{TypeTerm},
crate::{
type_system::{Context},
terminal::{
TerminalEditor, TerminalEditorResult,
TerminalEvent, TerminalView
},
editors::{
list::ListCursorMode,
product::{

View file

@ -19,7 +19,10 @@ use {
#[derive(Clone)]
pub enum ProductEditorSegment {
/// Terminal Node, i.e. literal, immutable string
T( String, usize ),
/// Nonterminal Node, i.e. sub-editor for type t
N {
t: TypeTerm,
editor: Option<NestedNode>,

View file

@ -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 )

View file

@ -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 );

View file

@ -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))
}));
*/
}

View file

@ -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 );

View file

@ -7,7 +7,7 @@ use {
}
},
crate::{
tree::{TreeNav, TreeCursor, TreeNavResult, TreeHeightOp},
edit_tree::{TreeNav, TreeCursor, TreeNavResult, TreeHeightOp},
editors::{typeterm::TypeTermEditor, list::ListCursorMode}
},
cgmath::Vector2

View file

@ -0,0 +1,8 @@
#![feature(trait_upcasting)]
pub mod repr_tree;
pub mod edit_tree;
pub mod editors;
pub mod utils;

View file

@ -0,0 +1,233 @@
use {
r3vi::{view::{OuterViewPort, singleton::*}, buffer::{singleton::*}},
laddertypes::{TypeDict, TypeTerm, TypeID, MorphismType, MorphismBase, Morphism},
crate::{
repr_tree::{ReprTree, ReprTreeExt, GenericReprTreeMorphism},
edit_tree::EditTree
},
std::{
collections::HashMap,
sync::{Arc, RwLock},
}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
#[derive(Clone)]
pub struct Context {
/// assigns a name to every type
pub type_dict: Arc<RwLock<TypeDict>>,
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 {
let mut dict = TypeDict::new();
let list_typeid = dict.add_typename("List".into());
Context {
type_dict: match parent.as_ref() {
Some(p) => p.read().unwrap().type_dict.clone(),
None => Arc::new(RwLock::new(dict))
},
morphisms: MorphismBase::new( list_typeid ),
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 make_repr(ctx: &Arc<RwLock<Self>>, t: &TypeTerm) -> Arc<RwLock<ReprTree>> {
let rt = Arc::new(RwLock::new(ReprTree::new( TypeTerm::unit() )));
ctx.read().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< Arc<RwLock<ReprTree>> > {
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>>
// depth: OuterViewPort<dyn SingletonView<Item = usize>>
) -> 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
}
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>

View 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())
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>

View file

@ -0,0 +1,145 @@
pub mod node;
pub mod leaf;
pub mod context;
pub mod morphism;
#[cfg(test)]
mod tests;
pub use {
context::{Context},
leaf::ReprLeaf,
node::ReprTree,
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<Arc<RwLock<ReprTree>>>;
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(Context::parse(&ctx, "EditTree")).unwrap()
.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<Arc<RwLock<ReprTree>>> {
ReprTree::descend( 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("")
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>

View file

@ -0,0 +1,210 @@
use {
laddertypes::{TypeTerm, TypeID, morphism::Morphism},
r3vi::view::{AnyOuterViewPort, port::*, list::*},
crate::{
repr_tree::{ReprTree, ReprTreeExt, ReprLeaf},
},
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 typeid_list = TypeID::Fun(0);
let typeid_char = TypeID::Fun(1);
let typeid_u64 = TypeID::Fun(5);
let typeid_edittree = TypeID::Fun(2);
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();
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
}
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>

View file

@ -0,0 +1,395 @@
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}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
#[derive(Clone)]
pub struct ReprTree {
halo: TypeTerm,
type_tag: TypeTerm,
branches: HashMap<TypeTerm, Arc<RwLock<ReprTree>>>,
leaf: Option< ReprLeaf >
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
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(type_tag: impl Into<TypeTerm>) -> Self {
let type_tag = type_tag.into();
assert!(type_tag.is_flat());
ReprTree {
halo: TypeTerm::unit(),
type_tag: type_tag.clone(),
branches: HashMap::new(),
leaf: None
}
}
pub fn new_arc(type_tag: impl Into<TypeTerm>) -> Arc<RwLock<Self>> {
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: Arc<RwLock<ReprTree>>) {
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 ) -> Arc<RwLock<Self>> {
ReprTree::from_singleton_buffer(
Context::parse(ctx, "Char"),
SingletonBuffer::new(c)
)
}
pub fn from_view<V>( type_tag: impl Into<TypeTerm>, view: OuterViewPort<V> ) -> Arc<RwLock<Self>>
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> ) -> Arc<RwLock<Self>>
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
) -> Arc<RwLock<Self>> {
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> ) -> Arc<RwLock<Self>>
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::Fun(11)),
TypeTerm::TypeID(TypeID::Fun(2))
]) {
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::Fun(11)),
TypeTerm::TypeID(TypeID::Fun(1))
]) {
let mut leaf = ReprLeaf::from_vec_buffer(
VecBuffer::<char>::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 == Context::parse(&ctx, "Char") {
leaf.detach::<dyn SingletonView<Item = char>>();
}
if self.type_tag == Context::parse(&ctx, "<Vec Char>") {
leaf.detach_vec::<char>();
}
if self.type_tag == Context::parse(&ctx, "<List Char>") {
leaf.detach::<dyn ListView<char>>();
}
}
for (t,b) in self.branches.iter_mut() {
b.write().unwrap().detach(&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<Arc<RwLock<ReprTree>>> {
let dst_type = dst_type.into();
assert!( dst_type.is_flat() );
self.branches.get(&dst_type).cloned()
}
pub fn descend_ladder(rt: &Arc<RwLock<Self>>, mut repr_ladder: impl Iterator<Item = TypeTerm>) -> Option<Arc<RwLock<ReprTree>>> {
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<Arc<RwLock<ReprTree>>> {
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 ascend(rt: &Arc<RwLock<Self>>, type_term: impl Into<TypeTerm>) -> Arc<RwLock<ReprTree>> {
let mut n = Self::new(type_term);
n.insert_branch(rt.clone());
Arc::new(RwLock::new(n))
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
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
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
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")
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>

View 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' );
}

View file

@ -0,0 +1,2 @@
pub mod modulo;
pub use modulo::modulo;

View file

@ -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"]

View file

@ -10,7 +10,8 @@ use {
projection::projection_helper::ProjectionHelper,
},
crate::{
terminal::{TerminalAtom, TerminalStyle, TerminalView},
atom::{TerminalAtom, TerminalStyle},
TerminalView,
},
cgmath::{Point2, Vector2},
std::io::Read,

View file

@ -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 {

View file

@ -6,7 +6,7 @@ use {
},
projection::projection_helper::*,
},
crate::{terminal::{TerminalAtom, TerminalView}},
crate::{TerminalAtom, TerminalView},
cgmath::Point2,
std::sync::Arc,
std::sync::RwLock,

View file

@ -1,5 +1,5 @@
use {
crate::terminal::TerminalStyle,
crate::atom::TerminalStyle,
};
pub fn bg_style_from_depth(depth: usize) -> TerminalStyle {

View file

@ -0,0 +1,33 @@
impl 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()
}
}

View file

@ -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();

View 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())
)
}
}
}
}

View file

@ -0,0 +1,4 @@
pub mod color;
pub mod keymap;

View file

View 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)
}
@ -34,7 +73,7 @@ impl PTYListStyle {
editor.get_data_port()
);
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> {
@ -42,24 +81,28 @@ impl PTYListStyle {
editor.get_cursor_port(),
editor.get_data_port()
);
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,15 +153,15 @@ 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>> {
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = EditTree>> {
self.editor.read().unwrap().get_data_port()
}
@ -125,23 +169,30 @@ impl PTYListController {
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()) {
let 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: rt.get_type(),
dst_type: ladder
}
);
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 => {
e.insert(Arc::new(RwLock::new(new_edit.clone())));
drop(ne);
e.insert(new_edittree.value.read().unwrap().clone());
TreeNavResult::Continue
}
TreeNavResult::Exit => {
TreeNavResult::Exit
}
}
} else {
panic!("cant get edit tree");
TreeNavResult::Continue
}
},
ListCursorMode::Select => {
if let Some(item) = e.get_item_mut() {
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 {

View 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
}
*/

View file

View file

View file

@ -0,0 +1,8 @@
impl PtySegment for SumEditor {
fn pty_view(&self) -> OuterViewPort<dyn TerminalView> {
self.port.outer()
}
}

170
lib-nested-tty/src/lib.rs Normal file
View file

@ -0,0 +1,170 @@
#![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_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(',');
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_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());
}
}
)
);
}

View file

@ -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),

View 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
}
}

View file

@ -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" }

View file

@ -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("");
}

View file

@ -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" }

View file

@ -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));
}

View file

@ -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);
}

View file

@ -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" }

View file

@ -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("");
}

View file

@ -1,102 +0,0 @@
use {
r3vi::{
view::{
OuterViewPort,
singleton::*,
},
buffer::singleton::*
},
laddertypes::{TypeTerm},
crate::{
type_system::{Context, ReprTree},
terminal::{TerminalAtom},
tree::{NestedNode, TreeNavResult},
commander::{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 struct CharEditor {
ctx: Arc<RwLock<Context>>,
data: SingletonBuffer<char>
}
impl ObjCommander for CharEditor {
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 value = cmd_view.get();
if self.ctx.read().unwrap().meta_chars.contains(&value) {
TreeNavResult::Exit
} else {
self.data.set(value);
TreeNavResult::Continue
}
} else {
TreeNavResult::Exit
}
} else {
TreeNavResult::Exit
}
}
}
impl CharEditor {
pub fn new(ctx: Arc<RwLock<Context>>) -> Self {
CharEditor {
ctx,
data: SingletonBuffer::new('\0')
}
}
pub fn get_port(&self) -> OuterViewPort<dyn SingletonView<Item = char>> {
self.data.get_port()
}
pub fn get(&self) -> char {
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');
let ctx = ctx0.clone();
let editor = Arc::new(RwLock::new(CharEditor{ ctx, data: data.clone() }));
NestedNode::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())
}
}
*/

View file

@ -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());
}

View file

@ -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
}
*/
}

View file

@ -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
};

View file

@ -1,101 +0,0 @@
use {
r3vi::{
view::{
InnerViewPort, Observer, OuterViewPort,
sequence::*,
},
buffer::{vec::*}
},
std::sync::{Arc, RwLock},
};
pub struct RadixProjection {
src_radix: usize,
dst_radix: usize,
src_digits: Option<Arc<dyn SequenceView<Item = usize>>>,
dst_digits: RwLock<VecBuffer<usize>>,
}
impl RadixProjection {
pub fn new(
// static parameters
//---
src_radix: usize,
dst_radix: usize,
//---
// dynamic parameters
//---
// input
src_digits: OuterViewPort<dyn SequenceView<Item = usize>>,
// output
dst_digits: InnerViewPort<RwLock<Vec<usize>>>,
//---
) -> Arc<RwLock<Self>> {
dst_digits.0.add_update_hook(Arc::new(src_digits.0.clone()));
let proj = Arc::new(RwLock::new(RadixProjection {
src_radix,
dst_radix,
src_digits: None,
dst_digits: RwLock::new(VecBuffer::with_port(dst_digits)),
}));
src_digits.add_observer(proj.clone());
proj
}
fn machine_int(&self) -> usize {
let mut val = 0;
let mut r = 1;
for i in 0..self.src_digits.len().unwrap_or(0) {
val += r * self.src_digits.get(&i).unwrap();
r *= self.src_radix;
}
val
}
// recalculate everything
fn update(&self) {
let mut dst = self.dst_digits.write().unwrap();
dst.clear();
let mut val = self.machine_int();
while val > 0 {
dst.push(val % self.dst_radix);
val /= self.dst_radix;
}
}
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
}
*/
}
}
impl Observer<dyn SequenceView<Item = usize>> for RadixProjection {
fn reset(&mut self, view: Option<Arc<dyn SequenceView<Item = usize>>>) {
self.src_digits = view;
}
fn notify(&mut self, _idx: &usize) {
// todo:
// src digit i changed.
// which dst-digits does it affect?
// update dst-digit j:
// ...but for now the easy way
self.update();
}
}

View file

@ -1,41 +0,0 @@
use {
r3vi::{view::{OuterViewPort, singleton::*}},
laddertypes::{TypeTerm},
crate::{
type_system::{Context},
editors::list::{ListEditor, PTYListController, PTYListStyle}
},
std::sync::{Arc, RwLock}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub fn init_ctx(ctx: &mut Context) {
ctx.add_typename("ListCmd".into());
ctx.add_list_typename("List".into());
ctx.add_node_ctor(
"List", Arc::new(
|ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
match ty {
TypeTerm::App(args) => {
if args.len() > 1 {
let typ = args[1].clone();
let mut node = ListEditor::new(ctx.clone(), typ).into_node(depth);
PTYListController::for_node( &mut node, Some(','), Some('}') );
PTYListStyle::for_node( &mut node, ("{",", ","}") );
Some(node)
} else {
None
}
}
_ => None
}
}
)
);
}

View file

@ -1,9 +0,0 @@
pub mod list;
pub mod product;
pub mod sum;
pub mod char;
pub mod integer;
pub mod typeterm;

View file

@ -1,34 +0,0 @@
#![feature(trait_alias)]
pub mod terminal;
pub mod utils;
pub mod editors;
pub mod tree;
pub mod type_system;
pub mod diagnostics;
pub mod commander;
//pub mod product;
//pub mod sum;
//pub mod list;
pub fn magic_header() {
eprintln!("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>");
}
/*
pub trait StringGen {
fn get_string(&self) -> String;
}
use crate::{tree::{TreeNav}, diagnostics::Diagnostics, terminal::TerminalView, core::{OuterViewPort}};
*/
use r3vi::view::OuterViewPort;
use crate::terminal::TerminalView;
pub trait PtySegment {
fn pty_view(&self) -> OuterViewPort<dyn TerminalView>;
}

Some files were not shown because too many files have changed in this diff Show more