fix warnings & format

This commit is contained in:
Michael Sippel 2021-11-19 12:19:52 +01:00
parent bf8a949cdd
commit 411b773ab5
Signed by: senvas
GPG key ID: F96CF119C34B64A6
61 changed files with 2759 additions and 2741 deletions

View file

@ -1,8 +1,7 @@
use std::{ use std::{
fs::File, fs::File,
io::{Read, Write}, io::{Read, Write},
os::unix::io::FromRawFd os::unix::io::FromRawFd,
}; };
fn fib(n: u64) -> u64 { fn fib(n: u64) -> u64 {
@ -10,7 +9,7 @@ fn fib(n: u64) -> u64 {
let mut y1 = 1; let mut y1 = 1;
let mut y2 = 0; let mut y2 = 0;
for _ in 0 .. n { for _ in 0..n {
y = y1 + y2; y = y1 + y2;
y2 = y1; y2 = y1;
y1 = y; y1 = y;
@ -26,26 +25,32 @@ fn main() {
nested::magic_header(); nested::magic_header();
eprintln!(" eprintln!(
interface (Sequence ) 0 1"); "
interface (Sequence ) 0 1"
);
let mut f0 = unsafe { File::from_raw_fd(0) }; let mut f0 = unsafe { File::from_raw_fd(0) };
eprintln!(" eprintln!(
"
>0: n >0: n
( ) ( )
( MachineInt ) ( MachineInt )
( MachineWord ) ( MachineWord )
( Stream MachineSyllab ) ( Stream MachineSyllab )
"); "
);
let mut f1 = unsafe { File::from_raw_fd(1) }; let mut f1 = unsafe { File::from_raw_fd(1) };
eprintln!(" eprintln!(
"
<1: n'th fibonacci number <1: n'th fibonacci number
( ) ( )
( MachineInt ) ( MachineInt )
( MachineWord ) ( MachineWord )
( Stream MachineSyllab ) ( Stream MachineSyllab )
"); "
);
nested::magic_header(); nested::magic_header();
@ -55,4 +60,3 @@ interface (Sequence ) 0 1");
bytes = fib(n).to_le_bytes(); bytes = fib(n).to_le_bytes();
f1.write(&bytes).expect(""); f1.write(&bytes).expect("");
} }

View file

@ -1,9 +1,4 @@
use std::{fs::File, io::Read, os::unix::io::FromRawFd};
use std::{
fs::File,
io::{Read},
os::unix::io::FromRawFd
};
fn main() { fn main() {
nested::magic_header(); nested::magic_header();
@ -11,15 +6,18 @@ fn main() {
nested::magic_header(); nested::magic_header();
let mut f0 = unsafe { File::from_raw_fd(0) }; let mut f0 = unsafe { File::from_raw_fd(0) };
eprintln!(" eprintln!(
"
>0: >0:
( ) ( )
( MachineInt ) ( MachineInt )
( MachineWord ) ( MachineWord )
( Stream MachineSyllab ) ( Stream MachineSyllab )
"); "
);
eprintln!(" eprintln!(
"
<1: <1:
( ) ( )
( PositionalInt 10 BigEndian ) ( PositionalInt 10 BigEndian )
@ -27,7 +25,8 @@ fn main() {
( Sequence UTF-8-Char ) ( Sequence UTF-8-Char )
( Stream UTF-8-Char ) ( Stream UTF-8-Char )
( Stream MachineSyllab ) ( Stream MachineSyllab )
"); "
);
nested::magic_header(); nested::magic_header();
@ -35,4 +34,3 @@ fn main() {
f0.read_exact(&mut bytes).expect(""); f0.read_exact(&mut bytes).expect("");
println!("{}", u64::from_le_bytes(bytes)); println!("{}", u64::from_le_bytes(bytes));
} }

View file

@ -1,55 +1,68 @@
use nested::{
use { core::{TypeDict, ViewPort},
nested::{ integer::RadixProjection,
core::{ vec::VecBuffer,
ViewPort,
TypeDict
},
vec::{VecBuffer},
integer::{RadixProjection}
}
}; };
#[async_std::main] #[async_std::main]
async fn main() { async fn main() {
let mut td = TypeDict::new(); let mut td = TypeDict::new();
for tn in vec![ for tn in vec![
"MachineWord", "MachineInt", "MachineSyllab", "MachineWord",
"Vec", "Stream", "Json", "MachineInt",
"Sequence", "UTF-8-Char", "MachineSyllab",
"PositionalInt", "Digit", "LittleEndian", "BigEndian", "Vec",
"DiffStream", "", "Stream",
"$src_radix", "$dst_radix" "Json",
] { td.add_typename(tn.into()); } "Sequence",
"UTF-8-Char",
"PositionalInt",
"Digit",
"LittleEndian",
"BigEndian",
"DiffStream",
"",
"$src_radix",
"$dst_radix",
] {
td.add_typename(tn.into());
}
let radix_types = vec![ let radix_types = vec![
td.type_term_from_str("( )").unwrap(), td.type_term_from_str("( )").unwrap(),
td.type_term_from_str("( PositionalInt 10 LittleEndian )").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 ( Digit 10 ) )").unwrap(),
td.type_term_from_str("( Sequence UTF-8-Char )").unwrap(), td.type_term_from_str("( Sequence UTF-8-Char )").unwrap(),
td.type_term_from_str("( Sequence MachineSyllab )").unwrap() td.type_term_from_str("( Sequence MachineSyllab )").unwrap(),
]; ];
let src_types = vec![ let src_types = vec![
td.type_term_from_str("( )").unwrap(), td.type_term_from_str("( )").unwrap(),
td.type_term_from_str("( PositionalInt $src_radix LittleEndian )").unwrap(), td.type_term_from_str("( PositionalInt $src_radix LittleEndian )")
td.type_term_from_str("( Sequence ( Digit $src_radix ) )").unwrap(), .unwrap(),
td.type_term_from_str("( Sequence ( Digit $src_radix ) )")
.unwrap(),
td.type_term_from_str("( Sequence MachineInt )").unwrap(), td.type_term_from_str("( Sequence MachineInt )").unwrap(),
td.type_term_from_str("( DiffStream ( Vec MachineInt ) )").unwrap(), td.type_term_from_str("( DiffStream ( Vec MachineInt ) )")
.unwrap(),
td.type_term_from_str("( Json )").unwrap(), td.type_term_from_str("( Json )").unwrap(),
td.type_term_from_str("( Stream UTF-8-Char )").unwrap(), td.type_term_from_str("( Stream UTF-8-Char )").unwrap(),
td.type_term_from_str("( Stream MachineSyllab )").unwrap() td.type_term_from_str("( Stream MachineSyllab )").unwrap(),
]; ];
let dst_types = vec![ let dst_types = vec![
td.type_term_from_str("( )").unwrap(), td.type_term_from_str("( )").unwrap(),
td.type_term_from_str("( PositionalInt $dst_radix LittleEndian )").unwrap(), td.type_term_from_str("( PositionalInt $dst_radix LittleEndian )")
td.type_term_from_str("( Sequence ( Digit $dst_radix ) )").unwrap(), .unwrap(),
td.type_term_from_str("( Sequence ( Digit $dst_radix ) )")
.unwrap(),
td.type_term_from_str("( Sequence MachineInt )").unwrap(), td.type_term_from_str("( Sequence MachineInt )").unwrap(),
td.type_term_from_str("( DiffStream ( Vec MachineInt ) )").unwrap(), td.type_term_from_str("( DiffStream ( Vec MachineInt ) )")
.unwrap(),
td.type_term_from_str("( Json )").unwrap(), td.type_term_from_str("( Json )").unwrap(),
td.type_term_from_str("( Stream UTF-8-Char )").unwrap(), td.type_term_from_str("( Stream UTF-8-Char )").unwrap(),
td.type_term_from_str("( Stream MachineSyllab )").unwrap() td.type_term_from_str("( Stream MachineSyllab )").unwrap(),
]; ];
nested::magic_header(); nested::magic_header();
@ -99,27 +112,26 @@ async fn main() {
src_radix, src_radix,
dst_radix, dst_radix,
src_digits_port.outer().to_sequence(), src_digits_port.outer().to_sequence(),
dst_digits_port.inner() dst_digits_port.inner(),
); );
// output dst digits // output dst digits
let writer = { let writer = {
use std::{ use std::os::unix::io::FromRawFd;
os::unix::io::FromRawFd
};
dst_digits_port.outer().serialize_json(unsafe { std::fs::File::from_raw_fd(1) }) dst_digits_port
.outer()
.serialize_json(unsafe { std::fs::File::from_raw_fd(1) })
}; };
// start reading src digits // start reading src digits
{ {
use async_std::{ use async_std::os::unix::io::FromRawFd;
os::unix::io::FromRawFd
};
src_digits.from_json(unsafe { async_std::fs::File::from_raw_fd(0) }).await; src_digits
.from_json(unsafe { async_std::fs::File::from_raw_fd(0) })
.await;
} }
drop(writer); drop(writer);
} }

View file

@ -1,8 +1,7 @@
use std::{ use std::{
fs::File, fs::File,
io::{Read, Write}, io::{Read, Write},
os::unix::io::FromRawFd os::unix::io::FromRawFd,
}; };
fn main() { fn main() {
@ -10,16 +9,19 @@ fn main() {
eprintln!(" Parse MachineInt from String"); eprintln!(" Parse MachineInt from String");
nested::magic_header(); nested::magic_header();
eprintln!(" eprintln!(
"
$1: radix $1: radix
( ) ( )
( PositionalInt 10 BigEndian ) ( PositionalInt 10 BigEndian )
( Sequence ( Digit 10 ) ) ( Sequence ( Digit 10 ) )
( Sequence UTF-8-Char ) ( Sequence UTF-8-Char )
( Sequence MachineSyllab ) ( Sequence MachineSyllab )
"); "
);
eprintln!(" eprintln!(
"
>0: n >0: n
( ) ( )
( PositionalInt $radix BigEndian ) ( PositionalInt $radix BigEndian )
@ -27,15 +29,18 @@ $1: radix
( Sequence UTF-8-Char ) ( Sequence UTF-8-Char )
( Stream UTF-8-Char ) ( Stream UTF-8-Char )
( Stream MachineSyllab ) ( Stream MachineSyllab )
"); "
);
eprintln!(" eprintln!(
"
<1: n <1: n
( ) ( )
( MachineInt ) ( MachineInt )
( MachineWord ) ( MachineWord )
( Stream MachineSyllab ) ( Stream MachineSyllab )
"); "
);
nested::magic_header(); nested::magic_header();
@ -55,6 +60,10 @@ $1: radix
let mut chars = Vec::new(); let mut chars = Vec::new();
f0.read_to_end(&mut chars).expect(""); f0.read_to_end(&mut chars).expect("");
chars.retain(|c| (*c as char).is_alphanumeric()); 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(""); f1.write(
&u64::from_str_radix(&String::from_utf8_lossy(&chars), radix)
.unwrap()
.to_le_bytes(),
)
.expect("");
} }

View file

@ -1,20 +1,17 @@
use std::{ use std::{collections::HashMap, hash::Hash};
collections::HashMap,
hash::Hash
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct Bimap<V: Eq + Hash, Λ: Eq + Hash> { pub struct Bimap<V: Eq + Hash, Λ: Eq + Hash> {
pub : HashMap::<V, Λ>, pub : HashMap<V, Λ>,
pub my: HashMap::<Λ, V> pub my: HashMap<Λ, V>,
} }
impl<V: Eq + Hash + Clone, Λ: Eq + Hash + Clone> Bimap<V, Λ> { impl<V: Eq + Hash + Clone, Λ: Eq + Hash + Clone> Bimap<V, Λ> {
pub fn new() -> Self { pub fn new() -> Self {
Bimap { Bimap {
: HashMap::new(), : HashMap::new(),
my: HashMap::new() my: HashMap::new(),
} }
} }
@ -25,4 +22,3 @@ impl<V: Eq + Hash + Clone, Λ: Eq + Hash + Clone> Bimap<V, Λ> {
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>

View file

@ -1,70 +1,69 @@
use { use {
crate::core::Observer,
async_std::stream::Stream,
core::{ core::{
task::{Poll, Context, Waker}, pin::Pin,
pin::Pin task::{Context, Poll, Waker},
}, },
std::{ std::{
sync::{Arc, Mutex},
collections::HashSet, collections::HashSet,
hash::Hash hash::Hash,
sync::{Arc, Mutex},
}, },
async_std::{
stream::Stream
},
crate::{
core::{Observer}
}
}; };
/*\
/*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Traits Traits
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/ \*/
pub trait ChannelData : Default + IntoIterator + Send + Sync { pub trait ChannelData: Default + IntoIterator + Send + Sync {
fn channel_insert(&mut self, x: Self::Item); fn channel_insert(&mut self, x: Self::Item);
} }
/*\
/*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Queue Channel Queue Channel
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/ \*/
impl<T> ChannelData for Vec<T> impl<T> ChannelData for Vec<T>
where T: Send + Sync { where
T: Send + Sync,
{
fn channel_insert(&mut self, x: T) { fn channel_insert(&mut self, x: T) {
self.push(x); self.push(x);
} }
} }
/*\ /*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Set Channel Set Channel
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/ \*/
impl<T> ChannelData for HashSet<T> impl<T> ChannelData for HashSet<T>
where T: Eq + Hash + Send + Sync { where
T: Eq + Hash + Send + Sync,
{
fn channel_insert(&mut self, x: T) { fn channel_insert(&mut self, x: T) {
self.insert(x); self.insert(x);
} }
} }
/*\ /*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Singleton Channel Singleton Channel
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/ \*/
impl<T> ChannelData for Option<T> impl<T> ChannelData for Option<T>
where T: Send + Sync { where
T: Send + Sync,
{
fn channel_insert(&mut self, x: T) { fn channel_insert(&mut self, x: T) {
*self = Some(x); *self = Some(x);
} }
} }
/*\ /*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Channel Channel
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -73,7 +72,7 @@ struct ChannelState<Data: ChannelData> {
send_buf: Option<Data>, send_buf: Option<Data>,
recv_iter: Option<Data::IntoIter>, recv_iter: Option<Data::IntoIter>,
num_senders: usize, num_senders: usize,
waker: Option<Waker> waker: Option<Waker>,
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -84,7 +83,9 @@ pub struct ChannelReceiver<Data: ChannelData>(Arc<Mutex<ChannelState<Data>>>);
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<Data: ChannelData> ChannelSender<Data> impl<Data: ChannelData> ChannelSender<Data>
where Data::IntoIter: Send + Sync { where
Data::IntoIter: Send + Sync,
{
pub fn send(&self, msg: Data::Item) { pub fn send(&self, msg: Data::Item) {
let mut state = self.0.lock().unwrap(); let mut state = self.0.lock().unwrap();
@ -102,7 +103,10 @@ where Data::IntoIter: Send + Sync {
use crate::core::View; use crate::core::View;
impl<V: View + ?Sized, Data: ChannelData<Item = V::Msg>> Observer<V> for ChannelSender<Data> impl<V: View + ?Sized, Data: ChannelData<Item = V::Msg>> Observer<V> for ChannelSender<Data>
where V::Msg: Clone, Data::IntoIter: Send + Sync { where
V::Msg: Clone,
Data::IntoIter: Send + Sync,
{
fn notify(&mut self, msg: &V::Msg) { fn notify(&mut self, msg: &V::Msg) {
self.send(msg.clone()); self.send(msg.clone());
} }
@ -164,15 +168,12 @@ impl<Data: ChannelData> std::future::Future for ChannelRead<Data> {
impl<Data: ChannelData> Stream for ChannelReceiver<Data> { impl<Data: ChannelData> Stream for ChannelReceiver<Data> {
type Item = Data::Item; type Item = Data::Item;
fn poll_next( fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self: Pin<&mut Self>,
cx: &mut Context<'_>
) -> Poll<Option<Self::Item>> {
let mut state = self.0.lock().unwrap(); let mut state = self.0.lock().unwrap();
if let Some(recv_iter) = state.recv_iter.as_mut() { if let Some(recv_iter) = state.recv_iter.as_mut() {
if let Some(val) = recv_iter.next() { if let Some(val) = recv_iter.next() {
return Poll::Ready(Some(val)) return Poll::Ready(Some(val));
} else { } else {
state.recv_iter = None state.recv_iter = None
} }
@ -191,23 +192,24 @@ impl<Data: ChannelData> Stream for ChannelReceiver<Data> {
} }
} }
/*\ /*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Factory Functions Factory Functions
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/ \*/
pub fn channel<Data: ChannelData>() -> (ChannelSender<Data>, ChannelReceiver<Data>) { pub fn channel<Data: ChannelData>() -> (ChannelSender<Data>, ChannelReceiver<Data>) {
let state = Arc::new(Mutex::new(ChannelState{ let state = Arc::new(Mutex::new(ChannelState {
send_buf: None, send_buf: None,
recv_iter: None, recv_iter: None,
num_senders: 1, num_senders: 1,
waker: None waker: None,
})); }));
(ChannelSender(state.clone()), ChannelReceiver(state)) (ChannelSender(state.clone()), ChannelReceiver(state))
} }
pub fn set_channel<T: Eq + Hash + Send + Sync>() -> (ChannelSender<HashSet<T>>, ChannelReceiver<HashSet<T>>) { pub fn set_channel<T: Eq + Hash + Send + Sync>(
) -> (ChannelSender<HashSet<T>>, ChannelReceiver<HashSet<T>>) {
channel::<HashSet<T>>() channel::<HashSet<T>>()
} }
@ -215,7 +217,7 @@ pub fn queue_channel<T: Send + Sync>() -> (ChannelSender<Vec<T>>, ChannelReceive
channel::<Vec<T>>() channel::<Vec<T>>()
} }
pub fn singleton_channel<T: Send + Sync>() -> (ChannelSender<Option<T>>, ChannelReceiver<Option<T>>) { pub fn singleton_channel<T: Send + Sync>() -> (ChannelSender<Option<T>>, ChannelReceiver<Option<T>>)
{
channel::<Option<T>>() channel::<Option<T>>()
} }

View file

@ -1,19 +1,12 @@
use { use {
crate::core::{
type_term::{TypeDict, TypeTerm},
AnyOuterViewPort, OuterViewPort, View,
},
std::{ std::{
collections::HashMap, collections::HashMap,
sync::{Arc, RwLock} sync::{Arc, RwLock},
}, },
crate::{
core::{
type_term::{
TypeTerm,
TypeDict
},
View,
OuterViewPort,
AnyOuterViewPort
}
}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -21,37 +14,31 @@ use {
#[derive(Clone)] #[derive(Clone)]
pub struct ReprTree { pub struct ReprTree {
port: Option<AnyOuterViewPort>, port: Option<AnyOuterViewPort>,
branches: HashMap<TypeTerm, Arc<RwLock<ReprTree>>> branches: HashMap<TypeTerm, Arc<RwLock<ReprTree>>>,
} }
impl ReprTree { impl ReprTree {
pub fn new() -> Self { pub fn new() -> Self {
ReprTree { ReprTree {
port: None, port: None,
branches: HashMap::new() branches: HashMap::new(),
} }
} }
pub fn new_leaf( pub fn new_leaf(port: AnyOuterViewPort) -> Arc<RwLock<Self>> {
port: AnyOuterViewPort
) -> Arc<RwLock<Self>> {
let mut tree = ReprTree::new(); let mut tree = ReprTree::new();
tree.insert_leaf(vec![].into_iter(), port); tree.insert_leaf(vec![].into_iter(), port);
Arc::new(RwLock::new(tree)) Arc::new(RwLock::new(tree))
} }
pub fn insert_branch( pub fn insert_branch(&mut self, type_tag: TypeTerm, repr: Arc<RwLock<ReprTree>>) {
&mut self,
type_tag: TypeTerm,
repr: Arc<RwLock<ReprTree>>
) {
self.branches.insert(type_tag, repr); self.branches.insert(type_tag, repr);
} }
pub fn insert_leaf( pub fn insert_leaf(
&mut self, &mut self,
mut type_ladder: impl Iterator<Item = TypeTerm>, mut type_ladder: impl Iterator<Item = TypeTerm>,
port: AnyOuterViewPort port: AnyOuterViewPort,
) { ) {
if let Some(type_term) = type_ladder.next() { if let Some(type_term) = type_ladder.next() {
if let Some(next_repr) = self.branches.get(&type_term) { if let Some(next_repr) = self.branches.get(&type_term) {
@ -72,39 +59,45 @@ impl ReprTree {
#[derive(Clone)] #[derive(Clone)]
pub struct Object { pub struct Object {
pub type_tag: TypeTerm, pub type_tag: TypeTerm,
pub repr: Arc<RwLock<ReprTree>> pub repr: Arc<RwLock<ReprTree>>,
} }
impl Object { impl Object {
pub fn get_port<V: View + ?Sized + 'static>(&self) -> Option<OuterViewPort<V>> where V::Msg: Clone { pub fn get_port<V: View + ?Sized + 'static>(&self) -> Option<OuterViewPort<V>>
Some(self.repr.read().unwrap().port.clone()?.downcast::<V>().ok().unwrap()) where
V::Msg: Clone,
{
Some(
self.repr
.read()
.unwrap()
.port
.clone()?
.downcast::<V>()
.ok()
.unwrap(),
)
} }
pub fn downcast(&self, dst_type: TypeTerm) -> Option<Object> { pub fn downcast(&self, dst_type: TypeTerm) -> Option<Object> {
if let Some(repr) = self.repr.read().unwrap().branches.get(&dst_type) { if let Some(repr) = self.repr.read().unwrap().branches.get(&dst_type) {
Some(Object { Some(Object {
type_tag: dst_type, type_tag: dst_type,
repr: repr.clone() repr: repr.clone(),
}) })
} else { } else {
None None
} }
} }
fn downcast_ladder( fn downcast_ladder(&self, repr_ladder: impl Iterator<Item = TypeTerm>) -> Option<Object> {
&self, repr_ladder.fold(Some(self.clone()), |s, t| s?.downcast(t.clone()))
repr_ladder: impl Iterator<Item = TypeTerm>
) -> Option<Object> {
repr_ladder.fold(
Some(self.clone()),
|s, t| s?.downcast(t.clone())
)
} }
pub fn add_iso_repr( pub fn add_iso_repr(
&self, &self,
type_ladder: impl Iterator<Item = TypeTerm>, type_ladder: impl Iterator<Item = TypeTerm>,
morphism_constructors: &HashMap<MorphismType, Box<dyn Fn(Object) -> Object>> morphism_constructors: &HashMap<MorphismType, Box<dyn Fn(Object) -> Object>>,
) { ) {
let mut cur_repr = self.repr.clone(); let mut cur_repr = self.repr.clone();
@ -117,21 +110,21 @@ impl Object {
let mut obj = None; let mut obj = None;
for src_type in cur_repr.read().unwrap().branches.keys() { for src_type in cur_repr.read().unwrap().branches.keys() {
if let Some(ctor) = morphism_constructors.get( if let Some(ctor) = morphism_constructors.get(&MorphismType {
&MorphismType {
mode: MorphismMode::Iso, mode: MorphismMode::Iso,
src_type: src_type.clone(), src_type: src_type.clone(),
dst_type: dst_type.clone() dst_type: dst_type.clone(),
} }) {
) { let new_obj = ctor(Object {
let new_obj = ctor(
Object {
type_tag: src_type.clone(), type_tag: src_type.clone(),
repr: cur_repr.read().unwrap() repr: cur_repr
.read()
.unwrap()
.branches .branches
.get(&src_type).unwrap().clone() .get(&src_type)
} .unwrap()
); .clone(),
});
assert!(new_obj.type_tag == dst_type); assert!(new_obj.type_tag == dst_type);
@ -141,7 +134,10 @@ impl Object {
} }
if let Some(obj) = obj { if let Some(obj) = obj {
cur_repr.write().unwrap().insert_branch(obj.type_tag, obj.repr); cur_repr
.write()
.unwrap()
.insert_branch(obj.type_tag, obj.repr);
} else { } else {
panic!("could not find matching isomorphism!"); panic!("could not find matching isomorphism!");
} }
@ -152,7 +148,7 @@ impl Object {
pub fn add_mono_repr<'a>( pub fn add_mono_repr<'a>(
&self, &self,
type_ladder: impl Iterator<Item = TypeTerm>, type_ladder: impl Iterator<Item = TypeTerm>,
morphism_constructors: &HashMap<MorphismType, Box<dyn Fn(Object) -> Object>> morphism_constructors: &HashMap<MorphismType, Box<dyn Fn(Object) -> Object>>,
) { ) {
let mut cur_type = self.type_tag.clone(); let mut cur_type = self.type_tag.clone();
let mut cur_repr = self.repr.clone(); let mut cur_repr = self.repr.clone();
@ -163,24 +159,27 @@ impl Object {
cur_type = dst_type; cur_type = dst_type;
cur_repr = next_repr.clone(); cur_repr = next_repr.clone();
} else { } else {
if let Some(constructor) = morphism_constructors.get( if let Some(constructor) = morphism_constructors.get(&MorphismType {
&MorphismType {
mode: MorphismMode::Mono, mode: MorphismMode::Mono,
src_type: cur_type.clone(), src_type: cur_type.clone(),
dst_type: dst_type.clone() dst_type: dst_type.clone(),
} }) {
) { let new_obj = constructor(Object {
let new_obj = constructor(
Object {
type_tag: cur_type.clone(), type_tag: cur_type.clone(),
repr: cur_repr.read().unwrap() repr: cur_repr
.read()
.unwrap()
.branches .branches
.get(&cur_type).unwrap().clone() .get(&cur_type)
} .unwrap()
); .clone(),
});
assert!(new_obj.type_tag == dst_type); assert!(new_obj.type_tag == dst_type);
cur_repr.write().unwrap().insert_branch(new_obj.type_tag.clone(), new_obj.repr.clone()); cur_repr
.write()
.unwrap()
.insert_branch(new_obj.type_tag.clone(), new_obj.repr.clone());
cur_type = new_obj.type_tag; cur_type = new_obj.type_tag;
cur_repr = new_obj.repr; cur_repr = new_obj.repr;
@ -193,7 +192,7 @@ impl Object {
pub fn epi_cast<'a>( pub fn epi_cast<'a>(
&self, &self,
_type_ladder: impl Iterator<Item = TypeTerm>, _type_ladder: impl Iterator<Item = TypeTerm>,
_morphism_constructors: &HashMap<MorphismType, Box<dyn Fn(Object) -> Object>> _morphism_constructors: &HashMap<MorphismType, Box<dyn Fn(Object) -> Object>>,
) { ) {
// todo // todo
} }
@ -220,14 +219,14 @@ pub enum MorphismMode {
Epi, Epi,
/// Any other function /// Any other function
Any Any,
} }
#[derive(Clone, Hash, PartialEq, Eq)] #[derive(Clone, Hash, PartialEq, Eq)]
pub struct MorphismType { pub struct MorphismType {
pub mode: MorphismMode, pub mode: MorphismMode,
pub src_type: TypeTerm, pub src_type: TypeTerm,
pub dst_type: TypeTerm pub dst_type: TypeTerm,
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -237,7 +236,7 @@ pub struct Context {
default_constructors: HashMap<TypeTerm, Box<dyn Fn() -> Object + Send + Sync>>, default_constructors: HashMap<TypeTerm, Box<dyn Fn() -> Object + Send + Sync>>,
morphism_constructors: HashMap<MorphismType, Box<dyn Fn(Object) -> Object + Send + Sync>>, morphism_constructors: HashMap<MorphismType, Box<dyn Fn(Object) -> Object + Send + Sync>>,
objects: HashMap<String, Object>, objects: HashMap<String, Object>,
parent: Option<Arc<RwLock<Context>>> parent: Option<Arc<RwLock<Context>>>,
} }
impl Context { impl Context {
@ -247,7 +246,7 @@ impl Context {
default_constructors: HashMap::new(), default_constructors: HashMap::new(),
morphism_constructors: HashMap::new(), morphism_constructors: HashMap::new(),
objects: HashMap::new(), objects: HashMap::new(),
parent parent,
} }
} }
@ -266,17 +265,13 @@ impl Context {
pub fn add_morphism( pub fn add_morphism(
&mut self, &mut self,
morph_type: MorphismType, morph_type: MorphismType,
morph_fn: Box<dyn Fn(Object) -> Object + Send + Sync> morph_fn: Box<dyn Fn(Object) -> Object + Send + Sync>,
) { ) {
self.morphism_constructors.insert(morph_type, morph_fn); self.morphism_constructors.insert(morph_type, morph_fn);
} }
/// adds an object without any representations /// adds an object without any representations
pub fn add_obj( pub fn add_obj(&mut self, name: String, typename: &str) {
&mut self,
name: String,
typename: &str
) {
let type_tag = self.type_dict.type_term_from_str(typename).unwrap(); let type_tag = self.type_dict.type_term_from_str(typename).unwrap();
self.objects.insert( self.objects.insert(
@ -286,16 +281,13 @@ impl Context {
} else { } else {
Object { Object {
type_tag, type_tag,
repr: Arc::new(RwLock::new(ReprTree::new())) repr: Arc::new(RwLock::new(ReprTree::new())),
}
} }
},
); );
} }
pub fn get_obj( pub fn get_obj(&self, name: &String) -> Option<Object> {
&self,
name: &String
) -> Option<Object> {
if let Some(obj) = self.objects.get(name) { if let Some(obj) = self.objects.get(name) {
Some(obj.clone()) Some(obj.clone())
} else if let Some(parent) = self.parent.as_ref() { } else if let Some(parent) = self.parent.as_ref() {
@ -305,19 +297,16 @@ impl Context {
} }
} }
pub fn get_obj_port< pub fn get_obj_port<'a, V: View + ?Sized + 'static>(
'a,
V: View + ?Sized + 'static
>(
&self, &self,
name: &str, name: &str,
type_ladder: impl Iterator<Item = &'a str> type_ladder: impl Iterator<Item = &'a str>,
) -> Option<OuterViewPort<V>> ) -> Option<OuterViewPort<V>>
where V::Msg: Clone { where
V::Msg: Clone,
{
self.get_obj(&name.into())? self.get_obj(&name.into())?
.downcast_ladder( .downcast_ladder(type_ladder.map(|tn| self.type_dict.type_term_from_str(tn).unwrap()))?
type_ladder.map(|tn| self.type_dict.type_term_from_str(tn).unwrap())
)?
.get_port() .get_port()
} }
@ -325,43 +314,40 @@ impl Context {
&mut self, &mut self,
name: &str, name: &str,
type_ladder: impl Iterator<Item = &'a str>, type_ladder: impl Iterator<Item = &'a str>,
port: AnyOuterViewPort port: AnyOuterViewPort,
) { ) {
self.get_obj(&name.to_string()).unwrap() self.get_obj(&name.to_string())
.repr.write().unwrap() .unwrap()
.repr
.write()
.unwrap()
.insert_leaf( .insert_leaf(
type_ladder.map(|tn| self.type_dict.type_term_from_str(tn).unwrap()), type_ladder.map(|tn| self.type_dict.type_term_from_str(tn).unwrap()),
port port,
); );
} }
pub fn epi_cast( pub fn epi_cast(&mut self, name: &str, typename: &str) {
&mut self,
name: &str,
typename: &str
) {
let dst_type = self.type_dict.type_term_from_str(typename).unwrap(); let dst_type = self.type_dict.type_term_from_str(typename).unwrap();
let old_obj = self.objects.get(&name.to_string()).unwrap().clone(); let old_obj = self.objects.get(&name.to_string()).unwrap().clone();
let new_obj = let new_obj = if let Some(ctor) = self.morphism_constructors.get(&MorphismType {
if let Some(ctor) = self.morphism_constructors.get(
&MorphismType {
mode: MorphismMode::Epi, mode: MorphismMode::Epi,
src_type: old_obj.type_tag.clone(), src_type: old_obj.type_tag.clone(),
dst_type: dst_type.clone() dst_type: dst_type.clone(),
} }) {
) {
ctor(old_obj.clone()) ctor(old_obj.clone())
} else { } else {
Object { Object {
type_tag: dst_type, type_tag: dst_type,
repr: Arc::new(RwLock::new(ReprTree::new())) repr: Arc::new(RwLock::new(ReprTree::new())),
} }
}; };
new_obj.repr.write().unwrap().insert_branch( new_obj
old_obj.type_tag, .repr
old_obj.repr .write()
); .unwrap()
.insert_branch(old_obj.type_tag, old_obj.repr);
self.objects.insert(name.to_string(), new_obj); self.objects.insert(name.to_string(), new_obj);
} }
@ -369,9 +355,11 @@ impl Context {
pub fn mono_view<'a, V: View + ?Sized + 'static>( pub fn mono_view<'a, V: View + ?Sized + 'static>(
&mut self, &mut self,
name: &str, name: &str,
type_ladder: impl Iterator<Item = &'a str> type_ladder: impl Iterator<Item = &'a str>,
) -> Option<OuterViewPort<V>> ) -> Option<OuterViewPort<V>>
where V::Msg: Clone { where
V::Msg: Clone,
{
if let Some(p) = self.get_obj_port(name, type_ladder) { if let Some(p) = self.get_obj_port(name, type_ladder) {
Some(p) Some(p)
} else { } else {
@ -391,4 +379,3 @@ impl Context {
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>

View file

@ -1,47 +1,17 @@
pub mod view;
pub mod observer;
pub mod channel; pub mod channel;
pub mod context;
pub mod observer;
pub mod port; pub mod port;
pub mod type_term; pub mod type_term;
pub mod context; pub mod view;
pub use { pub use {
view::{View}, channel::{queue_channel, set_channel, singleton_channel, ChannelReceiver, ChannelSender},
observer::{ context::{Context, MorphismMode, MorphismType, Object, ReprTree},
Observer, observer::{NotifyFnObserver, Observer, ObserverBroadcast, ObserverExt, ResetFnObserver},
ObserverExt,
ObserverBroadcast,
NotifyFnObserver,
ResetFnObserver
},
channel::{
ChannelReceiver,
ChannelSender,
set_channel,
queue_channel,
singleton_channel
},
port::{ port::{
ViewPort, AnyInnerViewPort, AnyOuterViewPort, AnyViewPort, InnerViewPort, OuterViewPort, ViewPort,
InnerViewPort,
OuterViewPort,
AnyViewPort,
AnyOuterViewPort,
AnyInnerViewPort,
}, },
type_term::{ type_term::{TypeDict, TypeID, TypeTerm},
TypeID, view::View,
TypeTerm,
TypeDict,
},
context::{
ReprTree,
Object,
Context,
MorphismMode,
MorphismType
}
}; };

View file

@ -1,22 +1,18 @@
use { use {
crate::{ crate::core::{
core::{ channel::{channel, ChannelReceiver, ChannelSender},
View, View,
channel::{channel, ChannelSender, ChannelReceiver}
}
}, },
std::{ std::sync::RwLock,
sync::{Arc, Weak} std::sync::{Arc, Weak},
},
std::sync::RwLock
}; };
/*\ /*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Observer Observer
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/ \*/
pub trait Observer<V: View + ?Sized> : Send + Sync { pub trait Observer<V: View + ?Sized>: Send + Sync {
fn reset(&mut self, _view: Option<Arc<V>>) {} fn reset(&mut self, _view: Option<Arc<V>>) {}
fn notify(&mut self, msg: &V::Msg); fn notify(&mut self, msg: &V::Msg);
} }
@ -35,7 +31,7 @@ impl<V: View + ?Sized, O: Observer<V>> Observer<V> for Arc<RwLock<O>> {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub trait ObserverExt<V: View + ?Sized> : Observer<V> { pub trait ObserverExt<V: View + ?Sized>: Observer<V> {
fn notify_each(&mut self, it: impl IntoIterator<Item = V::Msg>); fn notify_each(&mut self, it: impl IntoIterator<Item = V::Msg>);
} }
@ -47,25 +43,30 @@ impl<V: View + ?Sized, T: Observer<V>> ObserverExt<V> for T {
} }
} }
/*\ /*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Broadcast Broadcast
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/ \*/
pub struct ObserverBroadcast<V: View + ?Sized> pub struct ObserverBroadcast<V: View + ?Sized>
where V::Msg : Send + Sync { where
V::Msg: Send + Sync,
{
rx: ChannelReceiver<Vec<V::Msg>>, rx: ChannelReceiver<Vec<V::Msg>>,
tx: ChannelSender<Vec<V::Msg>>, tx: ChannelSender<Vec<V::Msg>>,
observers: Vec<Weak<RwLock<dyn Observer<V>>>> observers: Vec<Weak<RwLock<dyn Observer<V>>>>,
} }
impl<V: View + ?Sized> ObserverBroadcast<V> impl<V: View + ?Sized> ObserverBroadcast<V>
where V::Msg : Clone + Send + Sync { where
V::Msg: Clone + Send + Sync,
{
pub fn new() -> Self { pub fn new() -> Self {
let (tx, rx) = channel::<Vec<V::Msg>>(); let (tx, rx) = channel::<Vec<V::Msg>>();
ObserverBroadcast { ObserverBroadcast {
rx, tx, rx,
observers: Vec::new() tx,
observers: Vec::new(),
} }
} }
@ -94,7 +95,9 @@ where V::Msg : Clone + Send + Sync {
} }
impl<V: View + ?Sized> Observer<V> for ObserverBroadcast<V> impl<V: View + ?Sized> Observer<V> for ObserverBroadcast<V>
where V::Msg: Clone { where
V::Msg: Clone,
{
fn reset(&mut self, view: Option<Arc<V>>) { fn reset(&mut self, view: Option<Arc<V>>) {
for o in self.iter() { for o in self.iter() {
o.write().unwrap().reset(view.clone()); o.write().unwrap().reset(view.clone());
@ -109,26 +112,32 @@ where V::Msg: Clone {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct NotifyFnObserver<V, F> pub struct NotifyFnObserver<V, F>
where V: View + ?Sized, where
F: Fn(&V::Msg) + Send + Sync { V: View + ?Sized,
F: Fn(&V::Msg) + Send + Sync,
{
f: F, f: F,
_phantom: std::marker::PhantomData<V> _phantom: std::marker::PhantomData<V>,
} }
impl<V, F> NotifyFnObserver<V, F> impl<V, F> NotifyFnObserver<V, F>
where V: View + ?Sized, where
F: Fn(&V::Msg) + Send + Sync { V: View + ?Sized,
F: Fn(&V::Msg) + Send + Sync,
{
pub fn new(f: F) -> Self { pub fn new(f: F) -> Self {
NotifyFnObserver { NotifyFnObserver {
f, f,
_phantom: std::marker::PhantomData _phantom: std::marker::PhantomData,
} }
} }
} }
impl<V, F> Observer<V> for NotifyFnObserver<V, F> impl<V, F> Observer<V> for NotifyFnObserver<V, F>
where V: View + ?Sized, where
F: Fn(&V::Msg) + Send + Sync { V: View + ?Sized,
F: Fn(&V::Msg) + Send + Sync,
{
fn notify(&mut self, msg: &V::Msg) { fn notify(&mut self, msg: &V::Msg) {
(self.f)(msg); (self.f)(msg);
} }
@ -137,30 +146,34 @@ where V: View + ?Sized,
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct ResetFnObserver<V, F> pub struct ResetFnObserver<V, F>
where V: View + ?Sized, where
F: Fn(Option<Arc<V>>) + Send + Sync { V: View + ?Sized,
F: Fn(Option<Arc<V>>) + Send + Sync,
{
f: F, f: F,
_phantom: std::marker::PhantomData<V> _phantom: std::marker::PhantomData<V>,
} }
impl<V, F> ResetFnObserver<V, F> impl<V, F> ResetFnObserver<V, F>
where V: View + ?Sized, where
F: Fn(Option<Arc<V>>) + Send + Sync { V: View + ?Sized,
F: Fn(Option<Arc<V>>) + Send + Sync,
{
pub fn new(f: F) -> Self { pub fn new(f: F) -> Self {
ResetFnObserver { ResetFnObserver {
f, f,
_phantom: std::marker::PhantomData _phantom: std::marker::PhantomData,
} }
} }
} }
impl<V, F> Observer<V> for ResetFnObserver<V, F> impl<V, F> Observer<V> for ResetFnObserver<V, F>
where V: View + ?Sized, where
F: Fn(Option<Arc<V>>) + Send + Sync { V: View + ?Sized,
F: Fn(Option<Arc<V>>) + Send + Sync,
{
fn notify(&mut self, _msg: &V::Msg) {} fn notify(&mut self, _msg: &V::Msg) {}
fn reset(&mut self, view: Option<Arc<V>>) { fn reset(&mut self, view: Option<Arc<V>>) {
(self.f)(view); (self.f)(view);
} }
} }

View file

@ -1,22 +1,15 @@
use { use {
std::sync::Arc, crate::core::{NotifyFnObserver, Observer, ObserverBroadcast, ResetFnObserver, View},
std::any::Any, std::any::Any,
std::sync::Arc,
std::sync::RwLock, std::sync::RwLock,
crate::core::{
View,
Observer,
ObserverBroadcast,
NotifyFnObserver,
ResetFnObserver
}
}; };
pub trait UpdateTask: Send + Sync {
pub trait UpdateTask : Send + Sync {
fn update(&self); fn update(&self);
} }
/*\ /*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
View Port View Port
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -24,16 +17,18 @@ pub trait UpdateTask : Send + Sync {
pub struct ViewPort<V: View + ?Sized> { pub struct ViewPort<V: View + ?Sized> {
view: Arc<RwLock<Option<Arc<V>>>>, view: Arc<RwLock<Option<Arc<V>>>>,
cast: Arc<RwLock<ObserverBroadcast<V>>>, cast: Arc<RwLock<ObserverBroadcast<V>>>,
pub update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>> pub update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>>,
} }
impl<V: View + ?Sized> ViewPort<V> impl<V: View + ?Sized> ViewPort<V>
where V::Msg: Clone { where
V::Msg: Clone,
{
pub fn new() -> Self { pub fn new() -> Self {
ViewPort { ViewPort {
view: Arc::new(RwLock::new(None)), view: Arc::new(RwLock::new(None)),
cast: Arc::new(RwLock::new(ObserverBroadcast::new())), cast: Arc::new(RwLock::new(ObserverBroadcast::new())),
update_hooks: Arc::new(RwLock::new(Vec::new())) update_hooks: Arc::new(RwLock::new(Vec::new())),
} }
} }
@ -51,8 +46,14 @@ where V::Msg: Clone {
pub fn add_observer(&self, observer: Arc<RwLock<dyn Observer<V>>>) { pub fn add_observer(&self, observer: Arc<RwLock<dyn Observer<V>>>) {
self.update(); self.update();
self.cast.write().unwrap().add_observer(Arc::downgrade(&observer)); self.cast
observer.write().unwrap().reset(self.view.read().unwrap().clone()); .write()
.unwrap()
.add_observer(Arc::downgrade(&observer));
observer
.write()
.unwrap()
.reset(self.view.read().unwrap().clone());
} }
pub fn add_update_hook(&self, hook_cast: Arc<dyn UpdateTask>) { pub fn add_update_hook(&self, hook_cast: Arc<dyn UpdateTask>) {
@ -60,47 +61,42 @@ where V::Msg: Clone {
} }
pub fn inner(&self) -> InnerViewPort<V> { pub fn inner(&self) -> InnerViewPort<V> {
InnerViewPort( InnerViewPort(ViewPort {
ViewPort{
view: self.view.clone(), view: self.view.clone(),
cast: self.cast.clone(), cast: self.cast.clone(),
update_hooks: self.update_hooks.clone() update_hooks: self.update_hooks.clone(),
} })
)
} }
pub fn outer(&self) -> OuterViewPort<V> { pub fn outer(&self) -> OuterViewPort<V> {
OuterViewPort( OuterViewPort(ViewPort {
ViewPort{
view: self.view.clone(), view: self.view.clone(),
cast: self.cast.clone(), cast: self.cast.clone(),
update_hooks: self.update_hooks.clone() update_hooks: self.update_hooks.clone(),
} })
)
} }
pub fn into_inner(self) -> InnerViewPort<V> { pub fn into_inner(self) -> InnerViewPort<V> {
InnerViewPort( InnerViewPort(ViewPort {
ViewPort{
view: self.view, view: self.view,
cast: self.cast, cast: self.cast,
update_hooks: self.update_hooks update_hooks: self.update_hooks,
} })
)
} }
pub fn into_outer(self) -> OuterViewPort<V> { pub fn into_outer(self) -> OuterViewPort<V> {
OuterViewPort( OuterViewPort(ViewPort {
ViewPort{
view: self.view, view: self.view,
cast: self.cast, cast: self.cast,
update_hooks: self.update_hooks update_hooks: self.update_hooks,
} })
)
} }
} }
impl<V: View + ?Sized> UpdateTask for ViewPort<V> where V::Msg: Clone + Send + Sync{ impl<V: View + ?Sized> UpdateTask for ViewPort<V>
where
V::Msg: Clone + Send + Sync,
{
fn update(&self) { fn update(&self) {
let v = { let v = {
let t = self.update_hooks.read().unwrap(); let t = self.update_hooks.read().unwrap();
@ -115,26 +111,34 @@ impl<V: View + ?Sized> UpdateTask for ViewPort<V> where V::Msg: Clone + Send + S
} }
} }
impl<V: View + ?Sized> Clone for ViewPort<V> impl<V: View + ?Sized> Clone for ViewPort<V>
where V::Msg: Clone { where
V::Msg: Clone,
{
fn clone(&self) -> Self { fn clone(&self) -> Self {
ViewPort { ViewPort {
view: self.view.clone(), view: self.view.clone(),
cast: self.cast.clone(), cast: self.cast.clone(),
update_hooks: self.update_hooks.clone() update_hooks: self.update_hooks.clone(),
} }
} }
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct InnerViewPort<V: View + ?Sized>(pub ViewPort<V>) where V::Msg: Clone; pub struct InnerViewPort<V: View + ?Sized>(pub ViewPort<V>)
pub struct OuterViewPort<V: View + ?Sized>(pub ViewPort<V>) where V::Msg: Clone; where
V::Msg: Clone;
pub struct OuterViewPort<V: View + ?Sized>(pub ViewPort<V>)
where
V::Msg: Clone;
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<V: View + ?Sized> InnerViewPort<V> where V::Msg: Clone { impl<V: View + ?Sized> InnerViewPort<V>
where
V::Msg: Clone,
{
pub fn get_broadcast(&self) -> Arc<RwLock<ObserverBroadcast<V>>> { pub fn get_broadcast(&self) -> Arc<RwLock<ObserverBroadcast<V>>> {
self.0.cast.clone() self.0.cast.clone()
} }
@ -154,7 +158,9 @@ impl<V: View + ?Sized> InnerViewPort<V> where V::Msg: Clone {
} }
impl<V: View + ?Sized> Clone for InnerViewPort<V> impl<V: View + ?Sized> Clone for InnerViewPort<V>
where V::Msg: Clone { where
V::Msg: Clone,
{
fn clone(&self) -> Self { fn clone(&self) -> Self {
InnerViewPort(self.0.clone()) InnerViewPort(self.0.clone())
} }
@ -163,7 +169,9 @@ where V::Msg: Clone {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<V: View + ?Sized + 'static> OuterViewPort<V> impl<V: View + ?Sized + 'static> OuterViewPort<V>
where V::Msg: Clone { where
V::Msg: Clone,
{
pub fn get_view(&self) -> Option<Arc<V>> { pub fn get_view(&self) -> Option<Arc<V>> {
self.0.view.read().unwrap().clone() self.0.view.read().unwrap().clone()
} }
@ -172,18 +180,27 @@ where V::Msg: Clone {
self.0.view.clone() self.0.view.clone()
} }
pub fn add_observer(&self, observer: Arc<RwLock<dyn Observer<V>>>) -> Arc<RwLock<Option<Arc<V>>>> { pub fn add_observer(
&self,
observer: Arc<RwLock<dyn Observer<V>>>,
) -> Arc<RwLock<Option<Arc<V>>>> {
self.0.add_observer(observer); self.0.add_observer(observer);
self.get_view_arc() self.get_view_arc()
} }
pub fn add_reset_fn<F: Fn(Option<Arc<V>>) + Send + Sync + 'static>(&self, reset: F) -> Arc<RwLock<ResetFnObserver<V, F>>> { pub fn add_reset_fn<F: Fn(Option<Arc<V>>) + Send + Sync + 'static>(
&self,
reset: F,
) -> Arc<RwLock<ResetFnObserver<V, F>>> {
let obs = Arc::new(RwLock::new(ResetFnObserver::new(reset))); let obs = Arc::new(RwLock::new(ResetFnObserver::new(reset)));
self.add_observer(obs.clone()); self.add_observer(obs.clone());
obs obs
} }
pub fn add_notify_fn<F: Fn(&V::Msg) + Send + Sync + 'static>(&self, notify: F) -> Arc<RwLock<NotifyFnObserver<V, F>>> { pub fn add_notify_fn<F: Fn(&V::Msg) + Send + Sync + 'static>(
&self,
notify: F,
) -> Arc<RwLock<NotifyFnObserver<V, F>>> {
let obs = Arc::new(RwLock::new(NotifyFnObserver::new(notify))); let obs = Arc::new(RwLock::new(NotifyFnObserver::new(notify)));
self.add_observer(obs.clone()); self.add_observer(obs.clone());
obs obs
@ -191,7 +208,9 @@ where V::Msg: Clone {
} }
impl<V: View + ?Sized> Clone for OuterViewPort<V> impl<V: View + ?Sized> Clone for OuterViewPort<V>
where V::Msg: Clone { where
V::Msg: Clone,
{
fn clone(&self) -> Self { fn clone(&self) -> Self {
OuterViewPort(self.0.clone()) OuterViewPort(self.0.clone())
} }
@ -223,7 +242,7 @@ where V::Msg: Clone {
pub struct AnyViewPort { pub struct AnyViewPort {
view: Arc<dyn Any + Send + Sync + 'static>, view: Arc<dyn Any + Send + Sync + 'static>,
cast: Arc<dyn Any + Send + Sync + 'static>, cast: Arc<dyn Any + Send + Sync + 'static>,
update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>> update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>>,
} }
impl AnyViewPort { impl AnyViewPort {
@ -231,10 +250,14 @@ impl AnyViewPort {
match ( match (
self.view.clone().downcast::<RwLock<Option<Arc<V>>>>(), self.view.clone().downcast::<RwLock<Option<Arc<V>>>>(),
self.cast.clone().downcast::<RwLock<ObserverBroadcast<V>>>(), self.cast.clone().downcast::<RwLock<ObserverBroadcast<V>>>(),
self.update_hooks.clone() self.update_hooks.clone(),
) { ) {
(Ok(view), Ok(cast), update_hooks) => Ok(ViewPort{view, cast, update_hooks}), (Ok(view), Ok(cast), update_hooks) => Ok(ViewPort {
_ => Err(self) view,
cast,
update_hooks,
}),
_ => Err(self),
} }
} }
} }
@ -244,7 +267,7 @@ impl<V: View + ?Sized + 'static> From<ViewPort<V>> for AnyViewPort {
AnyViewPort { AnyViewPort {
view: port.view as Arc<dyn Any + Send + Sync + 'static>, view: port.view as Arc<dyn Any + Send + Sync + 'static>,
cast: port.cast as Arc<dyn Any + Send + Sync + 'static>, cast: port.cast as Arc<dyn Any + Send + Sync + 'static>,
update_hooks: port.update_hooks update_hooks: port.update_hooks,
} }
} }
} }
@ -258,38 +281,47 @@ pub struct AnyOuterViewPort(AnyViewPort);
pub struct AnyInnerViewPort(AnyViewPort); pub struct AnyInnerViewPort(AnyViewPort);
impl AnyOuterViewPort { impl AnyOuterViewPort {
pub fn downcast<V: View + ?Sized + 'static>(self) -> Result<OuterViewPort<V>, AnyViewPort> where V::Msg: Clone { pub fn downcast<V: View + ?Sized + 'static>(self) -> Result<OuterViewPort<V>, AnyViewPort>
where
V::Msg: Clone,
{
Ok(OuterViewPort(self.0.downcast::<V>()?)) Ok(OuterViewPort(self.0.downcast::<V>()?))
} }
} }
impl<V: View + ?Sized + 'static> From<OuterViewPort<V>> for AnyOuterViewPort impl<V: View + ?Sized + 'static> From<OuterViewPort<V>> for AnyOuterViewPort
where V::Msg: Clone { where
V::Msg: Clone,
{
fn from(port: OuterViewPort<V>) -> Self { fn from(port: OuterViewPort<V>) -> Self {
AnyOuterViewPort(AnyViewPort{ AnyOuterViewPort(AnyViewPort {
view: port.0.view as Arc<dyn Any + Send + Sync + 'static>, view: port.0.view as Arc<dyn Any + Send + Sync + 'static>,
cast: port.0.cast as Arc<dyn Any + Send + Sync + 'static>, cast: port.0.cast as Arc<dyn Any + Send + Sync + 'static>,
update_hooks: port.0.update_hooks update_hooks: port.0.update_hooks,
}) })
} }
} }
impl AnyInnerViewPort { impl AnyInnerViewPort {
pub fn downcast<V: View + ?Sized + 'static>(self) -> Result<InnerViewPort<V>, AnyViewPort> where V::Msg: Clone { pub fn downcast<V: View + ?Sized + 'static>(self) -> Result<InnerViewPort<V>, AnyViewPort>
where
V::Msg: Clone,
{
Ok(InnerViewPort(self.0.downcast::<V>()?)) Ok(InnerViewPort(self.0.downcast::<V>()?))
} }
} }
impl<V: View + ?Sized + 'static> From<InnerViewPort<V>> for AnyInnerViewPort impl<V: View + ?Sized + 'static> From<InnerViewPort<V>> for AnyInnerViewPort
where V::Msg: Clone { where
V::Msg: Clone,
{
fn from(port: InnerViewPort<V>) -> Self { fn from(port: InnerViewPort<V>) -> Self {
AnyInnerViewPort(AnyViewPort{ AnyInnerViewPort(AnyViewPort {
view: port.0.view as Arc<dyn Any + Send + Sync + 'static>, view: port.0.view as Arc<dyn Any + Send + Sync + 'static>,
cast: port.0.cast as Arc<dyn Any + Send + Sync + 'static>, cast: port.0.cast as Arc<dyn Any + Send + Sync + 'static>,
update_hooks: port.0.update_hooks update_hooks: port.0.update_hooks,
}) })
} }
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>

View file

@ -1,11 +1,4 @@
use { use {crate::bimap::Bimap, std::collections::HashMap};
std::{
collections::HashMap
},
crate::{
bimap::Bimap,
}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -15,20 +8,17 @@ pub type TypeID = u64;
#[derive(Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
pub enum TypeTerm { pub enum TypeTerm {
Type { Type { id: TypeID, args: Vec<TypeTerm> },
id: TypeID, Num(i64),
args: Vec<TypeTerm>
},
Num(i64)
} }
impl TypeTerm { impl TypeTerm {
pub fn new(id: TypeID) -> Self { pub fn new(id: TypeID) -> Self {
TypeTerm::Type{ id, args: vec![] } TypeTerm::Type { id, args: vec![] }
} }
pub fn arg(&mut self, t: TypeTerm) -> &mut Self { pub fn arg(&mut self, t: TypeTerm) -> &mut Self {
if let TypeTerm::Type{ id: _, args } = self { if let TypeTerm::Type { id: _, args } = self {
args.push(t); args.push(t);
} }
@ -46,7 +36,7 @@ impl TypeTerm {
match token { match token {
"(" => { "(" => {
term_stack.push(None); term_stack.push(None);
}, }
")" => { ")" => {
let t = term_stack.pop().unwrap(); let t = term_stack.pop().unwrap();
if term_stack.len() > 0 { if term_stack.len() > 0 {
@ -59,19 +49,24 @@ impl TypeTerm {
} else { } else {
return t; return t;
} }
}, }
atom => { atom => {
let f = term_stack.last_mut().unwrap(); let f = term_stack.last_mut().unwrap();
match f { match f {
Some(f) => Some(f) => {
if atom.chars().nth(0).unwrap().is_numeric() { if atom.chars().nth(0).unwrap().is_numeric() {
f.num_arg(i64::from_str_radix(atom, 10).unwrap()); f.num_arg(i64::from_str_radix(atom, 10).unwrap());
} else { } else {
f.arg(TypeTerm::new(*names.get(atom).expect(&format!("invalid atom {}", atom)))); f.arg(TypeTerm::new(
*names.get(atom).expect(&format!("invalid atom {}", atom)),
));
}
} }
None => { None => {
*f = Some(TypeTerm::new(*names.get(atom).expect(&format!("invalid atom {}", atom)))); *f = Some(TypeTerm::new(
*names.get(atom).expect(&format!("invalid atom {}", atom)),
));
} }
} }
} }
@ -84,64 +79,60 @@ impl TypeTerm {
// only adds parenthesis where args.len > 0 // only adds parenthesis where args.len > 0
pub fn to_str1(&self, names: &HashMap<u64, String>) -> String { pub fn to_str1(&self, names: &HashMap<u64, String>) -> String {
match self { match self {
TypeTerm::Type{ id, args } => TypeTerm::Type { id, args } => {
if args.len() > 0 { if args.len() > 0 {
format!( format!(
"( {} {})", "( {} {})",
names[id], names[id],
if args.len() > 0 { if args.len() > 0 {
args.iter().fold( args.iter().fold(String::new(), |str, term| {
String::new(), format!("{}{} ", str, term.to_str1(names))
|str, term| format!("{}{} ", str, term.to_str1(names) ) })
)
} else { } else {
String::new() String::new()
} }
) )
} else { } else {
names[id].clone() names[id].clone()
}, }
}
TypeTerm::Num(n) => TypeTerm::Num(n) => format!("{}", n),
format!("{}", n)
} }
} }
// always adds an enclosing pair of parenthesis // always adds an enclosing pair of parenthesis
pub fn to_str(&self, names: &HashMap<u64, String>) -> String { pub fn to_str(&self, names: &HashMap<u64, String>) -> String {
match self { match self {
TypeTerm::Type{ id, args } => TypeTerm::Type { id, args } => format!(
format!(
"( {} {})", "( {} {})",
names[id], names[id],
if args.len() > 0 { if args.len() > 0 {
args.iter().fold( args.iter().fold(String::new(), |str, term| {
String::new(), format!("{}{} ", str, term.to_str1(names))
|str, term| format!("{}{} ", str, term.to_str1(names) ) })
)
} else { } else {
String::new() String::new()
}), }
),
TypeTerm::Num(n) => TypeTerm::Num(n) => format!("{}", n),
format!("{}", n)
} }
} }
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct TypeDict { pub struct TypeDict {
typenames: Bimap::<String, u64>, typenames: Bimap<String, u64>,
type_id_counter: u64 type_id_counter: u64,
} }
impl TypeDict { impl TypeDict {
pub fn new() -> Self { pub fn new() -> Self {
TypeDict { TypeDict {
typenames: Bimap::new(), typenames: Bimap::new(),
type_id_counter: 0 type_id_counter: 0,
} }
} }
@ -160,4 +151,3 @@ impl TypeDict {
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>

View file

@ -1,12 +1,11 @@
/*\
/*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
View View
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/ \*/
pub trait View : Send + Sync { pub trait View: Send + Sync {
/// Notification message for the observers /// Notification message for the observers
type Msg : Send + Sync; type Msg: Send + Sync;
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -25,4 +24,3 @@ impl<V: View + ?Sized> View for Arc<V> {
impl<V: View> View for Option<V> { impl<V: View> View for Option<V> {
type Msg = V::Msg; type Msg = V::Msg;
} }

View file

@ -1,25 +1,19 @@
use { use {
std::{
sync::Arc,
cmp::max,
collections::HashMap
},
std::sync::RwLock,
cgmath::{Point2, Vector2},
crate::{ crate::{
core::{ core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View, ViewPort},
View, Observer, ObserverBroadcast,
ViewPort, InnerViewPort, OuterViewPort,
port::UpdateTask
},
grid::{GridView, GridWindowIterator}, grid::{GridView, GridWindowIterator},
index::{IndexArea, IndexView}, index::{IndexArea, IndexView},
projection::ProjectionHelper projection::ProjectionHelper,
} },
cgmath::{Point2, Vector2},
std::sync::RwLock,
std::{cmp::max, collections::HashMap, sync::Arc},
}; };
impl<Item> OuterViewPort<dyn GridView<Item = OuterViewPort<dyn GridView<Item = Item>>>> impl<Item> OuterViewPort<dyn GridView<Item = OuterViewPort<dyn GridView<Item = Item>>>>
where Item: 'static{ where
Item: 'static,
{
pub fn flatten(&self) -> OuterViewPort<dyn GridView<Item = Item>> { pub fn flatten(&self) -> OuterViewPort<dyn GridView<Item = Item>> {
let port = ViewPort::new(); let port = ViewPort::new();
port.add_update_hook(Arc::new(self.0.clone())); port.add_update_hook(Arc::new(self.0.clone()));
@ -29,31 +23,35 @@ where Item: 'static{
} }
pub struct Chunk<Item> pub struct Chunk<Item>
where Item: 'static where
Item: 'static,
{ {
offset: Vector2<i16>, offset: Vector2<i16>,
limit: Point2<i16>, limit: Point2<i16>,
view: Arc<dyn GridView<Item = Item>> view: Arc<dyn GridView<Item = Item>>,
} }
pub struct Flatten<Item> pub struct Flatten<Item>
where Item: 'static where
Item: 'static,
{ {
limit: Point2<i16>, limit: Point2<i16>,
top: Arc<dyn GridView<Item = OuterViewPort<dyn GridView<Item = Item>>>>, top: Arc<dyn GridView<Item = OuterViewPort<dyn GridView<Item = Item>>>>,
chunks: HashMap<Point2<i16>, Chunk<Item>>, chunks: HashMap<Point2<i16>, Chunk<Item>>,
cast: Arc<RwLock<ObserverBroadcast<dyn GridView<Item = Item>>>>, cast: Arc<RwLock<ObserverBroadcast<dyn GridView<Item = Item>>>>,
proj_helper: ProjectionHelper<Point2<i16>, Self> proj_helper: ProjectionHelper<Point2<i16>, Self>,
} }
impl<Item> View for Flatten<Item> impl<Item> View for Flatten<Item>
where Item: 'static where
Item: 'static,
{ {
type Msg = IndexArea<Point2<i16>>; type Msg = IndexArea<Point2<i16>>;
} }
impl<Item> IndexView<Point2<i16>> for Flatten<Item> impl<Item> IndexView<Point2<i16>> for Flatten<Item>
where Item: 'static where
Item: 'static,
{ {
type Item = Item; type Item = Item;
@ -64,24 +62,22 @@ where Item: 'static
} }
fn area(&self) -> IndexArea<Point2<i16>> { fn area(&self) -> IndexArea<Point2<i16>> {
IndexArea::Range( IndexArea::Range(Point2::new(0, 0)..=self.limit)
Point2::new(0, 0) ..= self.limit
)
} }
} }
/* TODO: remove unused projection args (bot-views) if they get replaced by a new viewport */ /* TODO: remove unused projection args (bot-views) if they get replaced by a new viewport */
impl<Item> Flatten<Item> impl<Item> Flatten<Item>
where Item: 'static where
Item: 'static,
{ {
pub fn new( pub fn new(
top_port: OuterViewPort<dyn GridView<Item = OuterViewPort<dyn GridView<Item = Item>>>>, top_port: OuterViewPort<dyn GridView<Item = OuterViewPort<dyn GridView<Item = Item>>>>,
out_port: InnerViewPort<dyn GridView<Item = Item>> out_port: InnerViewPort<dyn GridView<Item = Item>>,
) -> Arc<RwLock<Self>> { ) -> Arc<RwLock<Self>> {
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone()); let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
let flat = Arc::new(RwLock::new( let flat = Arc::new(RwLock::new(Flatten {
Flatten {
limit: Point2::new(0, 0), limit: Point2::new(0, 0),
top: proj_helper.new_index_arg( top: proj_helper.new_index_arg(
Point2::new(-1, -1), Point2::new(-1, -1),
@ -90,11 +86,11 @@ where Item: 'static
for chunk_idx in chunk_area.iter() { for chunk_idx in chunk_area.iter() {
s.update_chunk(chunk_idx); s.update_chunk(chunk_idx);
} }
} },
), ),
chunks: HashMap::new(), chunks: HashMap::new(),
cast: out_port.get_broadcast(), cast: out_port.get_broadcast(),
proj_helper proj_helper,
})); }));
flat.write().unwrap().proj_helper.set_proj(&flat); flat.write().unwrap().proj_helper.set_proj(&flat);
@ -117,26 +113,23 @@ where Item: 'static
} }
if let Some(chunk) = s.chunks.get(&chunk_idx) { if let Some(chunk) = s.chunks.get(&chunk_idx) {
s.cast.notify( s.cast.notify(&area.map(|pt| pt + chunk.offset));
&area.map(|pt| pt + chunk.offset)
);
}
} }
},
); );
if let Some(chunk) = self.chunks.get_mut(&chunk_idx) { if let Some(chunk) = self.chunks.get_mut(&chunk_idx) {
chunk.view = view; chunk.view = view;
self.cast.notify( self.cast
&chunk.view.area().map(|pt| pt + chunk.offset) .notify(&chunk.view.area().map(|pt| pt + chunk.offset));
);
} else { } else {
self.chunks.insert( self.chunks.insert(
chunk_idx, chunk_idx,
Chunk { Chunk {
offset: Vector2::new(-1, -1), offset: Vector2::new(-1, -1),
limit: Point2::new(-1, -1), limit: Point2::new(-1, -1),
view view,
} },
); );
} }
@ -144,7 +137,7 @@ where Item: 'static
} else { } else {
self.proj_helper.remove_arg(&chunk_idx); self.proj_helper.remove_arg(&chunk_idx);
if let Some(chunk) = self.chunks.remove(&chunk_idx) { if let Some(_chunk) = self.chunks.remove(&chunk_idx) {
self.update_all_offsets(); self.update_all_offsets();
} }
} }
@ -154,38 +147,36 @@ where Item: 'static
/// and update size of flattened grid /// and update size of flattened grid
fn update_all_offsets(&mut self) { fn update_all_offsets(&mut self) {
let top_range = self.top.area().range(); let top_range = self.top.area().range();
let mut col_widths = vec![0 as i16; (top_range.end().x+1) as usize]; let mut col_widths = vec![0 as i16; (top_range.end().x + 1) as usize];
let mut row_heights = vec![0 as i16; (top_range.end().y+1) as usize]; let mut row_heights = vec![0 as i16; (top_range.end().y + 1) as usize];
for chunk_idx in GridWindowIterator::from(top_range.clone()) { for chunk_idx in GridWindowIterator::from(top_range.clone()) {
if let Some(chunk) = self.chunks.get_mut(&chunk_idx) { if let Some(chunk) = self.chunks.get_mut(&chunk_idx) {
let chunk_range = chunk.view.area().range(); let chunk_range = chunk.view.area().range();
let lim = *chunk_range.end(); let lim = *chunk_range.end();
col_widths[chunk_idx.x as usize] = col_widths[chunk_idx.x as usize] = max(
max(
col_widths[chunk_idx.x as usize], col_widths[chunk_idx.x as usize],
if lim.x < 0 { 0 } else { lim.x+1 } if lim.x < 0 { 0 } else { lim.x + 1 },
); );
row_heights[chunk_idx.y as usize] = row_heights[chunk_idx.y as usize] = max(
max(
row_heights[chunk_idx.y as usize], row_heights[chunk_idx.y as usize],
if lim.y < 0 { 0 } else { lim.y+1 } if lim.y < 0 { 0 } else { lim.y + 1 },
); );
} }
} }
for chunk_idx in GridWindowIterator::from(top_range.clone()) { for chunk_idx in GridWindowIterator::from(top_range.clone()) {
if let Some(chunk) = self.chunks.get_mut(&chunk_idx) { if let Some(chunk) = self.chunks.get_mut(&chunk_idx) {
let old_offset = chunk.offset; let _old_offset = chunk.offset;
let old_limit = chunk.limit; let _old_limit = chunk.limit;
chunk.limit = *chunk.view.area().range().end(); chunk.limit = *chunk.view.area().range().end();
chunk.offset = Vector2::new( chunk.offset = Vector2::new(
(0 .. chunk_idx.x as usize).map(|x| col_widths[x]).sum(), (0..chunk_idx.x as usize).map(|x| col_widths[x]).sum(),
(0 .. chunk_idx.y as usize).map(|y| row_heights[y]).sum() (0..chunk_idx.y as usize).map(|y| row_heights[y]).sum(),
); );
/* /*
if old_offset != chunk.offset { if old_offset != chunk.offset {
self.cast.notify( self.cast.notify(
&IndexArea::Range( &IndexArea::Range(
@ -200,21 +191,29 @@ where Item: 'static
) )
); );
} }
*/ */
} }
} }
let old_limit = self.limit; let old_limit = self.limit;
self.limit = Point2::new( self.limit = Point2::new(
(0 ..= top_range.end().x as usize).map(|x| col_widths[x]).sum::<i16>() - 1, (0..=top_range.end().x as usize)
(0 ..= top_range.end().y as usize).map(|y| row_heights[y]).sum::<i16>() - 1, .map(|x| col_widths[x])
.sum::<i16>()
- 1,
(0..=top_range.end().y as usize)
.map(|y| row_heights[y])
.sum::<i16>()
- 1,
); );
self.cast.notify( self.cast.notify(&IndexArea::Range(
&IndexArea::Range( Point2::new(0, 0)
Point2::new(0, 0) ..= Point2::new(max(self.limit.x, old_limit.x), max(self.limit.y, old_limit.y)) ..=Point2::new(
) max(self.limit.x, old_limit.x),
); max(self.limit.y, old_limit.y),
),
));
} }
/// given an index in the flattened sequence, /// given an index in the flattened sequence,
@ -233,4 +232,3 @@ where Item: 'static
None None
} }
} }

View file

@ -1,11 +1,10 @@
use { use {
crate::index::{IndexArea, IndexView},
cgmath::Point2,
std::{ std::{
cmp::{max, min},
ops::RangeInclusive, ops::RangeInclusive,
cmp::{min, max}
}, },
cgmath::{Point2},
crate::index::{IndexArea, IndexView}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -14,8 +13,8 @@ pub trait GridView = IndexView<Point2<i16>>;
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub mod offset;
pub mod flatten; pub mod flatten;
pub mod offset;
pub mod window_iterator; pub mod window_iterator;
pub use window_iterator::GridWindowIterator; pub use window_iterator::GridWindowIterator;
@ -23,7 +22,6 @@ pub use window_iterator::GridWindowIterator;
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl IndexArea<Point2<i16>> { impl IndexArea<Point2<i16>> {
// todo: this is not perfect (e.g. diagonals are inefficient) // todo: this is not perfect (e.g. diagonals are inefficient)
pub fn iter(&self) -> GridWindowIterator { pub fn iter(&self) -> GridWindowIterator {
GridWindowIterator::from(self.range()) GridWindowIterator::from(self.range())
@ -31,52 +29,46 @@ impl IndexArea<Point2<i16>> {
pub fn range(&self) -> RangeInclusive<Point2<i16>> { pub fn range(&self) -> RangeInclusive<Point2<i16>> {
match self { match self {
IndexArea::Empty => Point2::new(i16::MAX, i16::MAX) ..= Point2::new(i16::MIN, i16::MIN), IndexArea::Empty => Point2::new(i16::MAX, i16::MAX)..=Point2::new(i16::MIN, i16::MIN),
IndexArea::Full => panic!("range from full grid area"), IndexArea::Full => panic!("range from full grid area"),
IndexArea::Set(v) => IndexArea::Set(v) => {
Point2::new( Point2::new(
v.iter().map(|p| p.x).min().unwrap_or(0), v.iter().map(|p| p.x).min().unwrap_or(0),
v.iter().map(|p| p.y).min().unwrap_or(0) v.iter().map(|p| p.y).min().unwrap_or(0),
) ..= )
Point2::new( ..=Point2::new(
v.iter().map(|p| p.x).max().unwrap_or(0), v.iter().map(|p| p.x).max().unwrap_or(0),
v.iter().map(|p| p.y).max().unwrap_or(0) v.iter().map(|p| p.y).max().unwrap_or(0),
), )
IndexArea::Range(r) => r.clone() }
IndexArea::Range(r) => r.clone(),
} }
} }
pub fn union(self, other: IndexArea<Point2<i16>>) -> IndexArea<Point2<i16>> { pub fn union(self, other: IndexArea<Point2<i16>>) -> IndexArea<Point2<i16>> {
match (self, other) { match (self, other) {
(IndexArea::Empty, a) | (IndexArea::Empty, a) | (a, IndexArea::Empty) => a,
(a, IndexArea::Empty) => a,
(IndexArea::Full, _) | (IndexArea::Full, _) | (_, IndexArea::Full) => IndexArea::Full,
(_, IndexArea::Full) => IndexArea::Full,
(IndexArea::Set(mut va), IndexArea::Set(mut vb)) => { (IndexArea::Set(mut va), IndexArea::Set(vb)) => {
va.extend(vb.into_iter()); va.extend(vb.into_iter());
IndexArea::Set(va) IndexArea::Set(va)
}, }
(IndexArea::Range(r), IndexArea::Set(mut v)) | (IndexArea::Range(r), IndexArea::Set(mut v))
(IndexArea::Set(mut v), IndexArea::Range(r)) => { | (IndexArea::Set(mut v), IndexArea::Range(r)) => {
v.extend(GridWindowIterator::from(r)); v.extend(GridWindowIterator::from(r));
IndexArea::Set(v) IndexArea::Set(v)
}, }
(IndexArea::Range(ra), IndexArea::Range(rb)) => IndexArea::Range( (IndexArea::Range(ra), IndexArea::Range(rb)) => IndexArea::Range(
Point2::new( Point2::new(
min(ra.start().x, rb.start().x), min(ra.start().x, rb.start().x),
min(ra.start().y, rb.start().y) min(ra.start().y, rb.start().y),
)
..=
Point2::new(
max(ra.end().x, rb.end().x),
max(ra.end().y, rb.end().y)
)
) )
..=Point2::new(max(ra.end().x, rb.end().x), max(ra.end().y, rb.end().y)),
),
} }
} }
} }

View file

@ -1,20 +1,15 @@
use { use {
crate::{core::OuterViewPort, grid::GridView},
cgmath::Vector2, cgmath::Vector2,
crate::{
core::OuterViewPort,
grid::GridView
}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<Item> OuterViewPort<dyn GridView<Item = Item>> impl<Item> OuterViewPort<dyn GridView<Item = Item>>
where Item: 'static { where
Item: 'static,
{
pub fn offset(&self, offset: Vector2<i16>) -> OuterViewPort<dyn GridView<Item = Item>> { pub fn offset(&self, offset: Vector2<i16>) -> OuterViewPort<dyn GridView<Item = Item>> {
self.map_key( self.map_key(move |pt| pt + offset, move |pt| Some(pt - offset))
move |pt| pt + offset,
move |pt| Some(pt - offset)
)
} }
} }

View file

@ -1,14 +1,13 @@
use { use {
cgmath::Point2,
std::ops::{Range, RangeInclusive}, std::ops::{Range, RangeInclusive},
cgmath::{Point2}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct GridWindowIterator { pub struct GridWindowIterator {
next: Point2<i16>, next: Point2<i16>,
range: Range<Point2<i16>> range: Range<Point2<i16>>,
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -17,7 +16,7 @@ impl From<Range<Point2<i16>>> for GridWindowIterator {
fn from(range: Range<Point2<i16>>) -> Self { fn from(range: Range<Point2<i16>>) -> Self {
GridWindowIterator { GridWindowIterator {
next: range.start, next: range.start,
range range,
} }
} }
} }
@ -26,7 +25,7 @@ impl From<RangeInclusive<Point2<i16>>> for GridWindowIterator {
fn from(range: RangeInclusive<Point2<i16>>) -> Self { fn from(range: RangeInclusive<Point2<i16>>) -> Self {
GridWindowIterator { GridWindowIterator {
next: *range.start(), next: *range.start(),
range: *range.start() .. Point2::new(range.end().x+1, range.end().y+1) range: *range.start()..Point2::new(range.end().x + 1, range.end().y + 1),
} }
} }
} }
@ -41,7 +40,7 @@ impl Iterator for GridWindowIterator {
if self.next.x < self.range.end.x { if self.next.x < self.range.end.x {
let next = self.next; let next = self.next;
if self.next.x+1 < self.range.end.x { if self.next.x + 1 < self.range.end.x {
self.next.x += 1; self.next.x += 1;
} else { } else {
self.next.x = self.range.start.x; self.next.x = self.range.start.x;
@ -57,4 +56,3 @@ impl Iterator for GridWindowIterator {
} }
} }
} }

View file

@ -1,36 +1,29 @@
use { use {
std::{ crate::{
sync::Arc, core::{InnerViewPort, Observer, ObserverBroadcast, View},
collections::HashMap, index::{IndexArea, IndexView},
hash::Hash
}, },
std::sync::RwLock, std::sync::RwLock,
crate::{ std::{collections::HashMap, hash::Hash, sync::Arc},
core::{
Observer,
ObserverBroadcast,
View,
InnerViewPort
},
index::{IndexArea, IndexView}
}
}; };
pub struct IndexBufferView<Key, Item>(Arc<RwLock<HashMap<Key, Item>>>) pub struct IndexBufferView<Key, Item>(Arc<RwLock<HashMap<Key, Item>>>)
where Key: Clone + Hash + Eq + Send + Sync + 'static, where
Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static; Item: Clone + Send + Sync + 'static;
impl<Key, Item> View for IndexBufferView<Key, Item> impl<Key, Item> View for IndexBufferView<Key, Item>
where Key: Clone + Hash + Eq + Send + Sync + 'static, where
Item: Clone + Send + Sync + 'static Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static,
{ {
type Msg = IndexArea<Key>; type Msg = IndexArea<Key>;
} }
impl<Key, Item> IndexView<Key> for IndexBufferView<Key, Item> impl<Key, Item> IndexView<Key> for IndexBufferView<Key, Item>
where Key: Clone + Hash + Eq + Send + Sync + 'static, where
Item: Clone + Send + Sync + 'static Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static,
{ {
type Item = Item; type Item = Item;
@ -44,16 +37,18 @@ where Key: Clone + Hash + Eq + Send + Sync + 'static,
} }
pub struct IndexBuffer<Key, Item> pub struct IndexBuffer<Key, Item>
where Key: Clone + Hash + Eq + Send + Sync + 'static, where
Item: Clone + Send + Sync + 'static Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static,
{ {
data: Arc<RwLock<HashMap<Key, Item>>>, data: Arc<RwLock<HashMap<Key, Item>>>,
cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<Key, Item = Item>>>> cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<Key, Item = Item>>>>,
} }
impl<Key, Item> IndexBuffer<Key, Item> impl<Key, Item> IndexBuffer<Key, Item>
where Key: Clone + Hash + Eq + Send + Sync + 'static, where
Item: Clone + Send + Sync + 'static Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static,
{ {
pub fn new(port: InnerViewPort<dyn IndexView<Key, Item = Item>>) -> Self { pub fn new(port: InnerViewPort<dyn IndexView<Key, Item = Item>>) -> Self {
let data = Arc::new(RwLock::new(HashMap::<Key, Item>::new())); let data = Arc::new(RwLock::new(HashMap::<Key, Item>::new()));
@ -61,17 +56,19 @@ where Key: Clone + Hash + Eq + Send + Sync + 'static,
IndexBuffer { IndexBuffer {
data, data,
cast: port.get_broadcast() cast: port.get_broadcast(),
} }
} }
pub fn insert(&mut self, key: Key, item: Item) { pub fn insert(&mut self, key: Key, item: Item) {
self.data.write().unwrap().insert(key.clone(), item); self.data.write().unwrap().insert(key.clone(), item);
self.cast.notify(&IndexArea::Set(vec![ key ])); self.cast.notify(&IndexArea::Set(vec![key]));
} }
pub fn insert_iter<T>(&mut self, iter: T) pub fn insert_iter<T>(&mut self, iter: T)
where T: IntoIterator<Item = (Key, Item)> { where
T: IntoIterator<Item = (Key, Item)>,
{
for (key, item) in iter { for (key, item) in iter {
self.insert(key, item); self.insert(key, item);
} }
@ -79,7 +76,6 @@ where Key: Clone + Hash + Eq + Send + Sync + 'static,
pub fn remove(&mut self, key: Key) { pub fn remove(&mut self, key: Key) {
self.data.write().unwrap().remove(&key); self.data.write().unwrap().remove(&key);
self.cast.notify(&IndexArea::Set(vec![ key ])); self.cast.notify(&IndexArea::Set(vec![key]));
} }
} }

View file

@ -1,33 +1,22 @@
pub use { pub use {
std::{
sync::Arc,
boxed::Box
},
std::sync::RwLock,
crate::{ crate::{
core::{ core::{
View, InnerViewPort, Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View, ViewPort,
Observer,
ObserverExt,
ObserverBroadcast,
ViewPort,
InnerViewPort,
OuterViewPort
}, },
index::{IndexArea, IndexView} index::{IndexArea, IndexView},
} },
std::sync::RwLock,
std::{boxed::Box, sync::Arc},
}; };
impl<Key, Item> OuterViewPort<dyn IndexView<Key, Item = Item>> impl<Key, Item> OuterViewPort<dyn IndexView<Key, Item = Item>>
where Key: Clone + Send + Sync + 'static, where
Item: Send + Sync + 'static Key: Clone + Send + Sync + 'static,
Item: Send + Sync + 'static,
{ {
pub fn map_item< pub fn map_item<DstItem: 'static, F: Fn(&Key, &Item) -> DstItem + Send + Sync + 'static>(
DstItem: 'static,
F: Fn(&Key, &Item) -> DstItem + Send + Sync + 'static
>(
&self, &self,
f: F f: F,
) -> OuterViewPort<dyn IndexView<Key, Item = DstItem>> { ) -> OuterViewPort<dyn IndexView<Key, Item = DstItem>> {
let port = ViewPort::new(); let port = ViewPort::new();
port.add_update_hook(Arc::new(self.0.clone())); port.add_update_hook(Arc::new(self.0.clone()));
@ -39,32 +28,29 @@ where Key: Clone + Send + Sync + 'static,
} }
pub struct MapIndexItem<Key, DstItem, SrcView, F> pub struct MapIndexItem<Key, DstItem, SrcView, F>
where Key: Clone + Send + Sync, where
Key: Clone + Send + Sync,
SrcView: IndexView<Key> + ?Sized, SrcView: IndexView<Key> + ?Sized,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync,
{ {
src_view: Option<Arc<SrcView>>, src_view: Option<Arc<SrcView>>,
f: F, f: F,
cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<Key, Item = DstItem>>>> cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<Key, Item = DstItem>>>>,
} }
impl<Key, DstItem, SrcView, F> MapIndexItem<Key, DstItem, SrcView, F> impl<Key, DstItem, SrcView, F> MapIndexItem<Key, DstItem, SrcView, F>
where Key: Clone + Send + Sync + 'static, where
Key: Clone + Send + Sync + 'static,
DstItem: 'static, DstItem: 'static,
SrcView: IndexView<Key> + ?Sized + 'static, SrcView: IndexView<Key> + ?Sized + 'static,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync + 'static F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync + 'static,
{ {
fn new( fn new(port: InnerViewPort<dyn IndexView<Key, Item = DstItem>>, f: F) -> Arc<RwLock<Self>> {
port: InnerViewPort<dyn IndexView<Key, Item = DstItem>>, let map = Arc::new(RwLock::new(MapIndexItem {
f: F
) -> Arc<RwLock<Self>> {
let map = Arc::new(RwLock::new(
MapIndexItem {
src_view: None, src_view: None,
f, f,
cast: port.get_broadcast() cast: port.get_broadcast(),
} }));
));
port.set_view(Some(map.clone())); port.set_view(Some(map.clone()));
map map
@ -72,22 +58,27 @@ where Key: Clone + Send + Sync + 'static,
} }
impl<Key, DstItem, SrcView, F> View for MapIndexItem<Key, DstItem, SrcView, F> impl<Key, DstItem, SrcView, F> View for MapIndexItem<Key, DstItem, SrcView, F>
where Key: Clone + Send + Sync, where
Key: Clone + Send + Sync,
SrcView: IndexView<Key> + ?Sized, SrcView: IndexView<Key> + ?Sized,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync,
{ {
type Msg = IndexArea<Key>; type Msg = IndexArea<Key>;
} }
impl<Key, DstItem, SrcView, F> IndexView<Key> for MapIndexItem<Key, DstItem, SrcView, F> impl<Key, DstItem, SrcView, F> IndexView<Key> for MapIndexItem<Key, DstItem, SrcView, F>
where Key: Clone + Send + Sync, where
Key: Clone + Send + Sync,
SrcView: IndexView<Key> + ?Sized, SrcView: IndexView<Key> + ?Sized,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync,
{ {
type Item = DstItem; type Item = DstItem;
fn get(&self, key: &Key) -> Option<Self::Item> { fn get(&self, key: &Key) -> Option<Self::Item> {
self.src_view.get(key).as_ref().map(|item| (self.f)(key, item)) self.src_view
.get(key)
.as_ref()
.map(|item| (self.f)(key, item))
} }
fn area(&self) -> IndexArea<Key> { fn area(&self) -> IndexArea<Key> {
@ -96,9 +87,10 @@ where Key: Clone + Send + Sync,
} }
impl<Key, DstItem, SrcView, F> Observer<SrcView> for MapIndexItem<Key, DstItem, SrcView, F> impl<Key, DstItem, SrcView, F> Observer<SrcView> for MapIndexItem<Key, DstItem, SrcView, F>
where Key: Clone + Send + Sync, where
Key: Clone + Send + Sync,
SrcView: IndexView<Key> + ?Sized, SrcView: IndexView<Key> + ?Sized,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync,
{ {
fn reset(&mut self, view: Option<Arc<SrcView>>) { fn reset(&mut self, view: Option<Arc<SrcView>>) {
let old_area = self.area(); let old_area = self.area();
@ -113,4 +105,3 @@ where Key: Clone + Send + Sync,
self.cast.notify(area); self.cast.notify(area);
} }
} }

View file

@ -1,27 +1,19 @@
pub use { pub use {
std::{
sync::Arc,
boxed::Box
},
std::sync::RwLock,
crate::{ crate::{
core::{ core::{
View, InnerViewPort, Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View, ViewPort,
Observer,
ObserverExt,
ObserverBroadcast,
ViewPort,
InnerViewPort,
OuterViewPort
}, },
grid::GridView,
index::{IndexArea, IndexView}, index::{IndexArea, IndexView},
grid::{GridView} },
} std::sync::RwLock,
std::{boxed::Box, sync::Arc},
}; };
impl<SrcKey, Item> OuterViewPort<dyn IndexView<SrcKey, Item = Item>> impl<SrcKey, Item> OuterViewPort<dyn IndexView<SrcKey, Item = Item>>
where SrcKey: Clone + Send + Sync + 'static, where
Item: 'static SrcKey: Clone + Send + Sync + 'static,
Item: 'static,
{ {
pub fn map_key< pub fn map_key<
DstKey: Clone + Send + Sync + 'static, DstKey: Clone + Send + Sync + 'static,
@ -30,7 +22,7 @@ where SrcKey: Clone + Send + Sync + 'static,
>( >(
&self, &self,
f1: F1, f1: F1,
f2: F2 f2: F2,
) -> OuterViewPort<dyn IndexView<DstKey, Item = Item>> { ) -> OuterViewPort<dyn IndexView<DstKey, Item = Item>> {
let port = ViewPort::new(); let port = ViewPort::new();
port.add_update_hook(Arc::new(self.0.clone())); port.add_update_hook(Arc::new(self.0.clone()));
@ -42,25 +34,27 @@ where SrcKey: Clone + Send + Sync + 'static,
} }
impl<Item> OuterViewPort<dyn IndexView<usize, Item = Item>> impl<Item> OuterViewPort<dyn IndexView<usize, Item = Item>>
where Item: 'static where
Item: 'static,
{ {
pub fn to_grid_horizontal(&self) -> OuterViewPort<dyn GridView<Item = Item>> { pub fn to_grid_horizontal(&self) -> OuterViewPort<dyn GridView<Item = Item>> {
self.map_key( self.map_key(
|idx| cgmath::Point2::new(*idx as i16, 0), |idx| cgmath::Point2::new(*idx as i16, 0),
|pt| if pt.y == 0 { Some(pt.x as usize) } else { None } |pt| if pt.y == 0 { Some(pt.x as usize) } else { None },
) )
} }
pub fn to_grid_vertical(&self) -> OuterViewPort<dyn GridView<Item = Item>> { pub fn to_grid_vertical(&self) -> OuterViewPort<dyn GridView<Item = Item>> {
self.map_key( self.map_key(
|idx| cgmath::Point2::new(0, *idx as i16), |idx| cgmath::Point2::new(0, *idx as i16),
|pt| if pt.x == 0 { Some(pt.y as usize) } else { None } |pt| if pt.x == 0 { Some(pt.y as usize) } else { None },
) )
} }
} }
pub struct MapIndexKey<DstKey, SrcKey, SrcView, F1, F2> pub struct MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
where DstKey: Clone + Send + Sync, where
DstKey: Clone + Send + Sync,
SrcKey: Clone + Send + Sync, SrcKey: Clone + Send + Sync,
SrcView: IndexView<SrcKey> + ?Sized, SrcView: IndexView<SrcKey> + ?Sized,
F1: Fn(&SrcKey) -> DstKey + Send + Sync, F1: Fn(&SrcKey) -> DstKey + Send + Sync,
@ -69,11 +63,12 @@ where DstKey: Clone + Send + Sync,
src_view: Option<Arc<SrcView>>, src_view: Option<Arc<SrcView>>,
f1: F1, f1: F1,
f2: F2, f2: F2,
cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<DstKey, Item = SrcView::Item>>>> cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<DstKey, Item = SrcView::Item>>>>,
} }
impl<DstKey, SrcKey, SrcView, F1, F2> MapIndexKey<DstKey, SrcKey, SrcView, F1, F2> impl<DstKey, SrcKey, SrcView, F1, F2> MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
where DstKey: Clone + Send + Sync + 'static, where
DstKey: Clone + Send + Sync + 'static,
SrcKey: Clone + Send + Sync + 'static, SrcKey: Clone + Send + Sync + 'static,
SrcView: IndexView<SrcKey> + ?Sized + 'static, SrcView: IndexView<SrcKey> + ?Sized + 'static,
SrcView::Item: 'static, SrcView::Item: 'static,
@ -83,16 +78,14 @@ where DstKey: Clone + Send + Sync + 'static,
fn new( fn new(
port: InnerViewPort<dyn IndexView<DstKey, Item = SrcView::Item>>, port: InnerViewPort<dyn IndexView<DstKey, Item = SrcView::Item>>,
f1: F1, f1: F1,
f2: F2 f2: F2,
) -> Arc<RwLock<Self>> { ) -> Arc<RwLock<Self>> {
let map = Arc::new(RwLock::new( let map = Arc::new(RwLock::new(MapIndexKey {
MapIndexKey {
src_view: None, src_view: None,
f1, f1,
f2, f2,
cast: port.get_broadcast() cast: port.get_broadcast(),
} }));
));
port.set_view(Some(map.clone())); port.set_view(Some(map.clone()));
map map
@ -100,7 +93,8 @@ where DstKey: Clone + Send + Sync + 'static,
} }
impl<DstKey, SrcKey, SrcView, F1, F2> View for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2> impl<DstKey, SrcKey, SrcView, F1, F2> View for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
where DstKey: Clone + Send + Sync, where
DstKey: Clone + Send + Sync,
SrcKey: Clone + Send + Sync, SrcKey: Clone + Send + Sync,
SrcView: IndexView<SrcKey> + ?Sized, SrcView: IndexView<SrcKey> + ?Sized,
F1: Fn(&SrcKey) -> DstKey + Send + Sync, F1: Fn(&SrcKey) -> DstKey + Send + Sync,
@ -109,8 +103,10 @@ where DstKey: Clone + Send + Sync,
type Msg = IndexArea<DstKey>; type Msg = IndexArea<DstKey>;
} }
impl<DstKey, SrcKey, SrcView, F1, F2> IndexView<DstKey> for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2> impl<DstKey, SrcKey, SrcView, F1, F2> IndexView<DstKey>
where DstKey: Clone + Send + Sync, for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
where
DstKey: Clone + Send + Sync,
SrcKey: Clone + Send + Sync, SrcKey: Clone + Send + Sync,
SrcView: IndexView<SrcKey> + ?Sized, SrcView: IndexView<SrcKey> + ?Sized,
F1: Fn(&SrcKey) -> DstKey + Send + Sync, F1: Fn(&SrcKey) -> DstKey + Send + Sync,
@ -127,8 +123,10 @@ where DstKey: Clone + Send + Sync,
} }
} }
impl<DstKey, SrcKey, SrcView, F1, F2> Observer<SrcView> for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2> impl<DstKey, SrcKey, SrcView, F1, F2> Observer<SrcView>
where DstKey: Clone + Send + Sync, for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
where
DstKey: Clone + Send + Sync,
SrcKey: Clone + Send + Sync, SrcKey: Clone + Send + Sync,
SrcView: IndexView<SrcKey> + ?Sized, SrcView: IndexView<SrcKey> + ?Sized,
F1: Fn(&SrcKey) -> DstKey + Send + Sync, F1: Fn(&SrcKey) -> DstKey + Send + Sync,
@ -145,4 +143,3 @@ where DstKey: Clone + Send + Sync,
self.cast.notify(&msg.map(&self.f1)); self.cast.notify(&msg.map(&self.f1));
} }
} }

View file

@ -1,15 +1,14 @@
pub mod buffer;
pub mod map_item; pub mod map_item;
pub mod map_key; pub mod map_key;
pub mod buffer;
use { use {
std::{ crate::core::View,
sync::Arc,
ops::{Deref, RangeInclusive},
},
std::sync::RwLock, std::sync::RwLock,
crate::core::View std::{
ops::{Deref, RangeInclusive},
sync::Arc,
},
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -29,13 +28,15 @@ impl<Key> IndexArea<Key> {
IndexArea::Empty => IndexArea::Empty, IndexArea::Empty => IndexArea::Empty,
IndexArea::Full => IndexArea::Full, IndexArea::Full => IndexArea::Full,
IndexArea::Set(v) => IndexArea::Set(v.iter().map(&f).collect()), IndexArea::Set(v) => IndexArea::Set(v.iter().map(&f).collect()),
IndexArea::Range(r) => IndexArea::Range(f(&r.start()) ..= f(&r.end())) IndexArea::Range(r) => IndexArea::Range(f(&r.start())..=f(&r.end())),
} }
} }
} }
pub trait IndexView<Key> : View<Msg = IndexArea<Key>> pub trait IndexView<Key>: View<Msg = IndexArea<Key>>
where Key: Send + Sync { where
Key: Send + Sync,
{
type Item; type Item;
fn get(&self, key: &Key) -> Option<Self::Item>; fn get(&self, key: &Key) -> Option<Self::Item>;
@ -48,8 +49,9 @@ where Key: Send + Sync {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<Key, V> IndexView<Key> for RwLock<V> impl<Key, V> IndexView<Key> for RwLock<V>
where Key: Send + Sync, where
V: IndexView<Key> + ?Sized Key: Send + Sync,
V: IndexView<Key> + ?Sized,
{ {
type Item = V::Item; type Item = V::Item;
@ -63,8 +65,9 @@ where Key: Send + Sync,
} }
impl<Key, V> IndexView<Key> for Arc<V> impl<Key, V> IndexView<Key> for Arc<V>
where Key: Send + Sync, where
V: IndexView<Key> + ?Sized Key: Send + Sync,
V: IndexView<Key> + ?Sized,
{ {
type Item = V::Item; type Item = V::Item;
@ -78,8 +81,9 @@ where Key: Send + Sync,
} }
impl<Key, V> IndexView<Key> for Option<V> impl<Key, V> IndexView<Key> for Option<V>
where Key: Send + Sync, where
V: IndexView<Key> Key: Send + Sync,
V: IndexView<Key>,
{ {
type Item = V::Item; type Item = V::Item;

View file

@ -1,35 +1,27 @@
use { use {
std::sync::{Arc, RwLock},
crate::{ crate::{
core::{InnerViewPort, OuterViewPort}, core::{InnerViewPort, OuterViewPort},
projection::ProjectionHelper,
sequence::SequenceView, sequence::SequenceView,
vec::VecBuffer, vec::VecBuffer,
projection::ProjectionHelper },
} std::sync::{Arc, RwLock},
}; };
fn posint_add( fn posint_add(
radix: usize, radix: usize,
a: impl SequenceView<Item = usize>, a: impl SequenceView<Item = usize>,
b: impl SequenceView<Item = usize> b: impl SequenceView<Item = usize>,
) -> Vec<usize> { ) -> Vec<usize> {
let mut carry = 0; let mut carry = 0;
let mut result = Vec::new(); let mut result = Vec::new();
for digit_idx in 0 .. std::cmp::max(a.len().unwrap_or(0), b.len().unwrap_or(0)) { for digit_idx in 0..std::cmp::max(a.len().unwrap_or(0), b.len().unwrap_or(0)) {
let sum = let sum = a.get(&digit_idx).unwrap_or(0) + b.get(&digit_idx).unwrap_or(0) + carry;
a.get(&digit_idx).unwrap_or(0) +
b.get(&digit_idx).unwrap_or(0) +
carry;
result.push(sum % radix); result.push(sum % radix);
carry = carry = if sum > radix { sum - radix } else { 0 };
if sum > radix {
sum - radix
} else {
0
};
} }
if carry > 0 { if carry > 0 {
@ -44,7 +36,7 @@ pub struct Add {
a: Arc<dyn SequenceView<Item = usize>>, // PosInt, Little Endian a: Arc<dyn SequenceView<Item = usize>>, // PosInt, Little Endian
b: Arc<dyn SequenceView<Item = usize>>, // PosInt, Little Endian b: Arc<dyn SequenceView<Item = usize>>, // PosInt, Little Endian
c: VecBuffer<usize>, c: VecBuffer<usize>,
_proj_helper: ProjectionHelper<usize, Self> _proj_helper: ProjectionHelper<usize, Self>,
} }
impl Add { impl Add {
@ -52,18 +44,16 @@ impl Add {
radix: usize, radix: usize,
a: OuterViewPort<dyn SequenceView<Item = usize>>, a: OuterViewPort<dyn SequenceView<Item = usize>>,
b: OuterViewPort<dyn SequenceView<Item = usize>>, b: OuterViewPort<dyn SequenceView<Item = usize>>,
c: InnerViewPort<RwLock<Vec<usize>>>//<dyn SequenceView<Item = usize>> c: InnerViewPort<RwLock<Vec<usize>>>, //<dyn SequenceView<Item = usize>>
) -> Arc<RwLock<Self>> { ) -> Arc<RwLock<Self>> {
let mut proj_helper = ProjectionHelper::new(c.0.update_hooks.clone()); let mut proj_helper = ProjectionHelper::new(c.0.update_hooks.clone());
let add = Arc::new(RwLock::new( let add = Arc::new(RwLock::new(Add {
Add {
radix, radix,
a: proj_helper.new_sequence_arg(0, a, |s: &mut Self, _digit_idx| s.update()), a: proj_helper.new_sequence_arg(0, a, |s: &mut Self, _digit_idx| s.update()),
b: proj_helper.new_sequence_arg(1, b, |s: &mut Self, _digit_idx| s.update()), b: proj_helper.new_sequence_arg(1, b, |s: &mut Self, _digit_idx| s.update()),
c: VecBuffer::new(c), c: VecBuffer::new(c),
_proj_helper: proj_helper _proj_helper: proj_helper,
} }));
));
add add
} }

View file

@ -1,17 +1,18 @@
use { use {
crate::{
core::{OuterViewPort, ViewPort},
list::{sexpr::ListDecoration, ListEditor},
sequence::{SequenceView, SequenceViewExt},
singleton::{SingletonBuffer, SingletonView},
terminal::{
TerminalAtom, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle,
TerminalView,
},
tree_nav::{TerminalTreeEditor, TreeCursor, TreeNav, TreeNavResult},
},
std::sync::Arc, std::sync::Arc,
std::sync::RwLock, std::sync::RwLock,
termion::event::{Key, Event}, termion::event::{Event, Key},
cgmath::Point2,
crate::{
core::{ViewPort, OuterViewPort, Observer},
singleton::{SingletonView, SingletonBuffer},
sequence::{SequenceView, SequenceViewExt},
vec::VecBuffer,
terminal::{TerminalAtom, TerminalStyle, TerminalView, TerminalEvent, TerminalEditor, TerminalEditorResult},
tree_nav::{TreeNav, TreeNavResult, TerminalTreeEditor, TreeCursor},
list::{ListEditor, ListEditorStyle, sexpr::ListDecoration}
}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -24,19 +25,17 @@ pub struct DigitEditor {
impl DigitEditor { impl DigitEditor {
pub fn new(radix: u32) -> Self { pub fn new(radix: u32) -> Self {
let mut data_port = ViewPort::new(); let data_port = ViewPort::new();
DigitEditor { DigitEditor {
radix, radix,
data: SingletonBuffer::new(None, data_port.inner()), data: SingletonBuffer::new(None, data_port.inner()),
data_port data_port,
} }
} }
pub fn get_data_port(&self) -> OuterViewPort<dyn SingletonView<Item = Option<u32>>> { pub fn get_data_port(&self) -> OuterViewPort<dyn SingletonView<Item = Option<u32>>> {
let radix = self.radix; let radix = self.radix;
self.data_port.outer().map( self.data_port.outer().map(move |c| c?.to_digit(radix))
move |c| c?.to_digit(radix)
)
} }
} }
@ -44,42 +43,44 @@ impl TreeNav for DigitEditor {}
impl TerminalEditor for DigitEditor { impl TerminalEditor for DigitEditor {
fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> { fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> {
let radix = self.radix; let radix = self.radix;
self.data_port.outer().map( self.data_port
move |c| TerminalAtom::new( .outer()
.map(move |c| {
TerminalAtom::new(
c.unwrap_or('?'), c.unwrap_or('?'),
if c.unwrap_or('?').to_digit(radix).is_some() { if c.unwrap_or('?').to_digit(radix).is_some() {
TerminalStyle::fg_color((100, 140, 100)) TerminalStyle::fg_color((100, 140, 100))
} else { } else {
//TerminalStyle::bg_color((90, 10, 10)) //TerminalStyle::bg_color((90, 10, 10))
TerminalStyle::fg_color((200, 40, 40)) TerminalStyle::fg_color((200, 40, 40))
} },
) )
).to_grid() })
.to_grid()
} }
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
match event { match event {
TerminalEvent::Input(Event::Key(Key::Char(' '))) | TerminalEvent::Input(Event::Key(Key::Char(' ')))
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => | TerminalEvent::Input(Event::Key(Key::Char('\n'))) => TerminalEditorResult::Exit,
TerminalEditorResult::Exit,
TerminalEvent::Input(Event::Key(Key::Char(c))) => { TerminalEvent::Input(Event::Key(Key::Char(c))) => {
self.data.set(Some(*c)); self.data.set(Some(*c));
TerminalEditorResult::Exit TerminalEditorResult::Exit
} }
TerminalEvent::Input(Event::Key(Key::Backspace)) | TerminalEvent::Input(Event::Key(Key::Backspace))
TerminalEvent::Input(Event::Key(Key::Delete)) => { | TerminalEvent::Input(Event::Key(Key::Delete)) => {
self.data.set(None); self.data.set(None);
TerminalEditorResult::Exit TerminalEditorResult::Exit
} }
_ => TerminalEditorResult::Continue _ => TerminalEditorResult::Continue,
} }
} }
} }
pub struct PosIntEditor { pub struct PosIntEditor {
radix: u32, radix: u32,
digits_editor: ListEditor< DigitEditor, digits_editor:
Box<dyn Fn() -> Arc<RwLock<DigitEditor>> + Send + Sync + 'static> > ListEditor<DigitEditor, Box<dyn Fn() -> Arc<RwLock<DigitEditor>> + Send + Sync + 'static>>,
} }
impl PosIntEditor { impl PosIntEditor {
@ -87,26 +88,33 @@ impl PosIntEditor {
PosIntEditor { PosIntEditor {
radix, radix,
digits_editor: ListEditor::new( digits_editor: ListEditor::new(
Box::new( Box::new(move || Arc::new(RwLock::new(DigitEditor::new(radix)))),
move || { crate::list::ListEditorStyle::Hex,
Arc::new(RwLock::new(DigitEditor::new(radix)))
}
), ),
crate::list::ListEditorStyle::Hex
)
} }
} }
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = u32>> { pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = u32>> {
let radix = self.radix; let radix = self.radix;
self.digits_editor.get_data_port() self.digits_editor
.filter_map(move |digit_editor| digit_editor.read().unwrap().data.get()?.to_digit(radix)) .get_data_port()
.filter_map(move |digit_editor| {
digit_editor.read().unwrap().data.get()?.to_digit(radix)
})
} }
pub fn get_value(&self) -> u32 { pub fn get_value(&self) -> u32 {
let mut value = 0; let mut value = 0;
let mut weight = 1; let mut weight = 1;
for digit_value in self.get_data_port().get_view().unwrap().iter().collect::<Vec<_>>().into_iter().rev() { for digit_value in self
.get_data_port()
.get_view()
.unwrap()
.iter()
.collect::<Vec<_>>()
.into_iter()
.rev()
{
value += digit_value * weight; value += digit_value * weight;
weight *= self.radix; weight *= self.radix;
} }
@ -116,14 +124,30 @@ impl PosIntEditor {
} }
impl TreeNav for PosIntEditor { impl TreeNav for PosIntEditor {
fn get_cursor(&self) -> TreeCursor { self.digits_editor.get_cursor() } fn get_cursor(&self) -> TreeCursor {
fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { self.digits_editor.goto(cur) } self.digits_editor.get_cursor()
fn goto_home(&mut self) -> TreeNavResult { self.digits_editor.goto_home() } }
fn goto_end(&mut self) -> TreeNavResult { self.digits_editor.goto_end() } fn goto(&mut self, cur: TreeCursor) -> TreeNavResult {
fn pxev(&mut self) -> TreeNavResult { self.digits_editor.pxev() } self.digits_editor.goto(cur)
fn nexd(&mut self) -> TreeNavResult { self.digits_editor.nexd() } }
fn up(&mut self) -> TreeNavResult { self.digits_editor.up() } fn goto_home(&mut self) -> TreeNavResult {
fn dn(&mut self) -> TreeNavResult { self.digits_editor.dn() } self.digits_editor.goto_home()
}
fn goto_end(&mut self) -> TreeNavResult {
self.digits_editor.goto_end()
}
fn pxev(&mut self) -> TreeNavResult {
self.digits_editor.pxev()
}
fn nexd(&mut self) -> TreeNavResult {
self.digits_editor.nexd()
}
fn up(&mut self) -> TreeNavResult {
self.digits_editor.up()
}
fn dn(&mut self) -> TreeNavResult {
self.digits_editor.dn()
}
} }
impl TerminalEditor for PosIntEditor { impl TerminalEditor for PosIntEditor {
@ -136,11 +160,11 @@ impl TerminalEditor for PosIntEditor {
8 => "0o", 8 => "0o",
10 => "0d", 10 => "0d",
16 => "0x", 16 => "0x",
_ => "" _ => "",
}, },
"", "",
"", "",
0 0,
) )
.to_grid_horizontal() .to_grid_horizontal()
.flatten() .flatten()
@ -148,14 +172,13 @@ impl TerminalEditor for PosIntEditor {
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
match event { match event {
TerminalEvent::Input(Event::Key(Key::Char(' '))) | TerminalEvent::Input(Event::Key(Key::Char(' ')))
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => { | TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
self.digits_editor.up(); self.digits_editor.up();
TerminalEditorResult::Exit TerminalEditorResult::Exit
} }
event => self.digits_editor.handle_terminal_event(event) event => self.digits_editor.handle_terminal_event(event),
} }
} }
} }

View file

@ -1,11 +1,9 @@
pub mod radix;
pub mod add; pub mod add;
pub mod editor; pub mod editor;
pub mod radix;
pub use { pub use {
radix::RadixProjection,
add::Add, add::Add,
editor::{DigitEditor, PosIntEditor} editor::{DigitEditor, PosIntEditor},
radix::RadixProjection,
}; };

View file

@ -1,21 +1,17 @@
use { use {
std::sync::{Arc, RwLock},
crate::{ crate::{
core::{ core::{InnerViewPort, Observer, OuterViewPort},
Observer,
InnerViewPort,
OuterViewPort
},
sequence::SequenceView, sequence::SequenceView,
vec::VecBuffer vec::VecBuffer,
} },
std::sync::{Arc, RwLock},
}; };
pub struct RadixProjection { pub struct RadixProjection {
src_radix: usize, src_radix: usize,
dst_radix: usize, dst_radix: usize,
src_digits: Option<Arc<dyn SequenceView<Item = usize>>>, src_digits: Option<Arc<dyn SequenceView<Item = usize>>>,
dst_digits: RwLock<VecBuffer<usize>> dst_digits: RwLock<VecBuffer<usize>>,
} }
impl RadixProjection { impl RadixProjection {
@ -23,17 +19,15 @@ impl RadixProjection {
src_radix: usize, src_radix: usize,
dst_radix: usize, dst_radix: usize,
src_digits: OuterViewPort<dyn SequenceView<Item = usize>>, src_digits: OuterViewPort<dyn SequenceView<Item = usize>>,
dst_digits: InnerViewPort<RwLock<Vec<usize>>> dst_digits: InnerViewPort<RwLock<Vec<usize>>>,
) -> Arc<RwLock<Self>> { ) -> Arc<RwLock<Self>> {
dst_digits.0.add_update_hook(Arc::new(src_digits.0.clone())); dst_digits.0.add_update_hook(Arc::new(src_digits.0.clone()));
let proj = Arc::new(RwLock::new( let proj = Arc::new(RwLock::new(RadixProjection {
RadixProjection {
src_radix, src_radix,
dst_radix, dst_radix,
src_digits: None, src_digits: None,
dst_digits: RwLock::new(VecBuffer::new(dst_digits)) dst_digits: RwLock::new(VecBuffer::new(dst_digits)),
} }));
));
src_digits.add_observer(proj.clone()); src_digits.add_observer(proj.clone());
proj proj
} }
@ -41,7 +35,7 @@ impl RadixProjection {
fn machine_int(&self) -> usize { fn machine_int(&self) -> usize {
let mut val = 0; let mut val = 0;
let mut r = 1; let mut r = 1;
for i in 0 .. self.src_digits.len().unwrap_or(0) { for i in 0..self.src_digits.len().unwrap_or(0) {
val += r * self.src_digits.get(&i).unwrap(); val += r * self.src_digits.get(&i).unwrap();
r *= self.src_radix; r *= self.src_radix;
} }
@ -75,7 +69,7 @@ impl RadixProjection {
} else { } else {
// error // error
} }
*/ */
} }
} }

View file

@ -3,14 +3,14 @@
pub mod core; pub mod core;
pub mod projection; pub mod projection;
pub mod singleton;
pub mod index;
pub mod grid; pub mod grid;
pub mod sequence; pub mod index;
pub mod vec;
pub mod terminal;
pub mod integer; pub mod integer;
pub mod list; pub mod list;
pub mod sequence;
pub mod singleton;
pub mod terminal;
pub mod vec;
pub mod tree_nav; pub mod tree_nav;
@ -21,4 +21,3 @@ pub mod bimap;
pub fn magic_header() { pub fn magic_header() {
eprintln!("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>"); eprintln!("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>");
} }

View file

@ -1,22 +1,21 @@
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy, Eq, PartialEq)]
pub enum ListCursorMode { pub enum ListCursorMode {
Insert, Insert,
Select, Select,
Modify Modify,
} }
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy, Eq, PartialEq)]
pub struct ListCursor { pub struct ListCursor {
pub mode: ListCursorMode, pub mode: ListCursorMode,
pub idx: Option<usize> pub idx: Option<usize>,
} }
impl Default for ListCursor { impl Default for ListCursor {
fn default() -> Self { fn default() -> Self {
ListCursor { ListCursor {
mode: ListCursorMode::Select, mode: ListCursorMode::Select,
idx: None idx: None,
} }
} }
} }
@ -32,4 +31,3 @@ pub trait ListNav {
fn get_cursor(&self) -> Option<ListCursor>; fn get_cursor(&self) -> Option<ListCursor>;
} }
*/ */

View file

@ -1,25 +1,21 @@
use { use {
crate::{
core::{OuterViewPort, ViewPort},
list::{
editor_view::{ListEditorView, ListEditorViewSegment},
ListCursor, ListCursorMode, ListDecoration, SExprView,
},
sequence::SequenceView,
singleton::{SingletonBuffer, SingletonView},
terminal::{
make_label, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle,
TerminalView,
},
tree_nav::{TerminalTreeEditor, TreeCursor, TreeNav, TreeNavResult},
vec::VecBuffer,
},
std::sync::{Arc, RwLock}, std::sync::{Arc, RwLock},
termion::event::{Event, Key}, termion::event::{Event, Key},
crate::{
core::{
ViewPort,
OuterViewPort,
},
singleton::{SingletonView, SingletonBuffer},
sequence::{SequenceView},
vec::{VecBuffer},
terminal::{
TerminalView,
TerminalStyle,
TerminalEvent,
TerminalEditor,
TerminalEditorResult,
make_label
},
list::{SExprView, ListDecoration, ListCursor, ListCursorMode, editor_view::{ListEditorView, ListEditorViewSegment}},
tree_nav::{TreeCursor, TreeNav, TreeNavResult, TerminalTreeEditor}
}
}; };
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -30,15 +26,16 @@ pub enum ListEditorStyle {
String, String,
Clist, Clist,
Hex, Hex,
Plain Plain,
} }
pub struct ListEditor<ItemEditor, FnMakeItemEditor> pub struct ListEditor<ItemEditor, FnMakeItemEditor>
where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, where
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>> ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>>,
{ {
cursor: SingletonBuffer<ListCursor>, cursor: SingletonBuffer<ListCursor>,
pub data: VecBuffer<Arc<RwLock<ItemEditor>>>, data: VecBuffer<Arc<RwLock<ItemEditor>>>,
cursor_port: ViewPort<dyn SingletonView<Item = ListCursor>>, cursor_port: ViewPort<dyn SingletonView<Item = ListCursor>>,
data_port: ViewPort<RwLock<Vec<Arc<RwLock<ItemEditor>>>>>, data_port: ViewPort<RwLock<Vec<Arc<RwLock<ItemEditor>>>>>,
@ -46,23 +43,25 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
make_item_editor: FnMakeItemEditor, make_item_editor: FnMakeItemEditor,
style: ListEditorStyle, style: ListEditorStyle,
level: usize, _level: usize,
cur_dist: Arc<RwLock<usize>>, cur_dist: Arc<RwLock<usize>>,
} }
impl<ItemEditor, FnMakeItemEditor> TreeNav for ListEditor<ItemEditor, FnMakeItemEditor> impl<ItemEditor, FnMakeItemEditor> TreeNav for ListEditor<ItemEditor, FnMakeItemEditor>
where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, where
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>> ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>>,
{ {
fn get_cursor(&self) -> TreeCursor { fn get_cursor(&self) -> TreeCursor {
let cur = self.cursor.get(); let cur = self.cursor.get();
match cur.mode { match cur.mode {
ListCursorMode::Insert | ListCursorMode::Insert | ListCursorMode::Select => TreeCursor {
ListCursorMode::Select => {
TreeCursor {
leaf_mode: cur.mode, leaf_mode: cur.mode,
tree_addr: if let Some(i) = cur.idx { vec![ i ] } else { vec![] } tree_addr: if let Some(i) = cur.idx {
} vec![i]
} else {
vec![]
},
}, },
ListCursorMode::Modify => { ListCursorMode::Modify => {
if let Some(i) = cur.idx { if let Some(i) = cur.idx {
@ -74,7 +73,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
TreeCursor { TreeCursor {
leaf_mode: cur.mode, leaf_mode: cur.mode,
tree_addr: vec![] tree_addr: vec![],
} }
} }
} }
@ -91,31 +90,30 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
if new_cur.tree_addr.len() == 1 { if new_cur.tree_addr.len() == 1 {
self.cursor.set(ListCursor{ self.cursor.set(ListCursor {
mode: new_cur.leaf_mode, mode: new_cur.leaf_mode,
idx: Some(new_cur.tree_addr[0]) idx: Some(new_cur.tree_addr[0]),
}); });
TreeNavResult::Continue TreeNavResult::Continue
} else if new_cur.tree_addr.len() > 1 && new_cur.tree_addr[0] < self.data.len() { } else if new_cur.tree_addr.len() > 1 && new_cur.tree_addr[0] < self.data.len() {
self.cursor.set(ListCursor { self.cursor.set(ListCursor {
mode: ListCursorMode::Modify, mode: ListCursorMode::Modify,
idx: Some(new_cur.tree_addr[0]) idx: Some(new_cur.tree_addr[0]),
}); });
let ne = self.data.get_mut(new_cur.tree_addr[0]); let ne = self.data.get_mut(new_cur.tree_addr[0]);
let mut nxt_edit = ne.write().unwrap(); let mut nxt_edit = ne.write().unwrap();
nxt_edit.goto( nxt_edit.goto(TreeCursor {
TreeCursor {
leaf_mode: new_cur.leaf_mode, leaf_mode: new_cur.leaf_mode,
tree_addr: new_cur.tree_addr[1..].iter().cloned().collect() tree_addr: new_cur.tree_addr[1..].iter().cloned().collect(),
}); });
TreeNavResult::Continue TreeNavResult::Continue
} else { } else {
self.cursor.set(ListCursor { self.cursor.set(ListCursor {
mode: new_cur.leaf_mode, mode: new_cur.leaf_mode,
idx: None idx: None,
}); });
TreeNavResult::Continue TreeNavResult::Continue
} }
@ -126,12 +124,10 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
let i = cur.idx.unwrap_or(0); let i = cur.idx.unwrap_or(0);
if self.data.len() == 0 && cur.idx.is_none() { if self.data.len() == 0 && cur.idx.is_none() {
self.cursor.set( self.cursor.set(ListCursor {
ListCursor {
mode: ListCursorMode::Insert, mode: ListCursorMode::Insert,
idx: Some(0) idx: Some(0),
} });
);
return TreeNavResult::Continue; return TreeNavResult::Continue;
} }
@ -149,17 +145,15 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
ListCursorMode::Select => { ListCursorMode::Select => {
if self.data.len() == 0 && cur.idx.is_none() { if self.data.len() == 0 && cur.idx.is_none() {
self.cursor.set( self.cursor.set(ListCursor {
ListCursor {
mode: ListCursorMode::Insert, mode: ListCursorMode::Insert,
idx: Some(0) idx: Some(0),
} });
);
return TreeNavResult::Continue; return TreeNavResult::Continue;
} }
if i+1 < self.data.len() || cur.idx.is_none() { if i + 1 < self.data.len() || cur.idx.is_none() {
cur.idx = Some(self.data.len()-1); cur.idx = Some(self.data.len() - 1);
self.cursor.set(cur); self.cursor.set(cur);
TreeNavResult::Continue TreeNavResult::Continue
} else { } else {
@ -173,19 +167,17 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
let cur_mode = cur_edit.get_cursor().leaf_mode; let cur_mode = cur_edit.get_cursor().leaf_mode;
let depth = cur_edit.get_cursor().tree_addr.len(); let depth = cur_edit.get_cursor().tree_addr.len();
match cur_edit.goto_end() { match cur_edit.goto_end() {
TreeNavResult::Continue => { TreeNavResult::Continue => TreeNavResult::Continue,
TreeNavResult::Continue
}
TreeNavResult::Exit => { TreeNavResult::Exit => {
drop(cur_edit); drop(cur_edit);
self.up(); self.up();
if i+1 < self.data.len() { if i + 1 < self.data.len() {
self.set_mode(ListCursorMode::Select); self.set_mode(ListCursorMode::Select);
self.nexd(); self.nexd();
for x in 1 .. depth { for _x in 1..depth {
self.dn(); self.dn();
self.goto_home(); self.goto_home();
} }
@ -211,25 +203,24 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
fn goto_home(&mut self) -> TreeNavResult { fn goto_home(&mut self) -> TreeNavResult {
let cur = self.cursor.get(); let cur = self.cursor.get();
if self.data.len() == 0 && cur.idx.is_none() { if self.data.len() == 0 && cur.idx.is_none() {
self.cursor.set( self.cursor.set(ListCursor {
ListCursor {
mode: ListCursorMode::Insert, mode: ListCursorMode::Insert,
idx: Some(0) idx: Some(0),
} });
);
return TreeNavResult::Continue; return TreeNavResult::Continue;
} }
match cur.mode { match cur.mode {
ListCursorMode::Insert | ListCursorMode::Insert | ListCursorMode::Select => {
ListCursorMode::Select => {
if cur.idx != Some(0) { if cur.idx != Some(0) {
self.cursor.set( self.cursor.set(ListCursor {
ListCursor { mode: if self.data.len() == 0 {
mode: if self.data.len() == 0 { ListCursorMode::Insert } else { cur.mode }, ListCursorMode::Insert
idx: Some(0) } else {
} cur.mode
); },
idx: Some(0),
});
TreeNavResult::Continue TreeNavResult::Continue
} else { } else {
self.cursor.set(ListCursor::default()); self.cursor.set(ListCursor::default());
@ -253,7 +244,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
self.set_mode(ListCursorMode::Select); self.set_mode(ListCursorMode::Select);
self.pxev(); self.pxev();
for x in 1 .. depth { for _x in 1..depth {
self.dn(); self.dn();
self.goto_end(); self.goto_end();
} }
@ -267,7 +258,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
TreeNavResult::Exit TreeNavResult::Exit
} }
TreeNavResult::Continue => TreeNavResult::Continue TreeNavResult::Continue => TreeNavResult::Continue,
} }
} }
} }
@ -294,7 +285,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
self.cursor.set(ListCursor { self.cursor.set(ListCursor {
mode: cur.mode, mode: cur.mode,
idx: None idx: None,
}); });
TreeNavResult::Exit TreeNavResult::Exit
} }
@ -302,25 +293,20 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
fn dn(&mut self) -> TreeNavResult { fn dn(&mut self) -> TreeNavResult {
let cur = self.cursor.get(); let cur = self.cursor.get();
match cur.mode { match cur.mode {
ListCursorMode::Insert | ListCursorMode::Insert | ListCursorMode::Select => {
ListCursorMode::Select => {
if let Some(i) = cur.idx { if let Some(i) = cur.idx {
if i < self.data.len() { if i < self.data.len() {
self.set_mode(ListCursorMode::Modify); self.set_mode(ListCursorMode::Modify);
self.data.get_mut(i).write().unwrap().goto( self.data.get_mut(i).write().unwrap().goto(TreeCursor {
TreeCursor {
leaf_mode: cur.mode, leaf_mode: cur.mode,
tree_addr: vec![] tree_addr: vec![],
} });
);
*self.cur_dist.write().unwrap() += 1; *self.cur_dist.write().unwrap() += 1;
} }
} }
TreeNavResult::Continue TreeNavResult::Continue
} }
ListCursorMode::Modify => { ListCursorMode::Modify => self.get_item().unwrap().write().unwrap().dn(),
self.get_item().unwrap().write().unwrap().dn()
}
} }
} }
@ -328,8 +314,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
let mut cur = self.cursor.get(); let mut cur = self.cursor.get();
if let Some(i) = cur.idx { if let Some(i) = cur.idx {
match cur.mode { match cur.mode {
ListCursorMode::Insert | ListCursorMode::Insert | ListCursorMode::Select => {
ListCursorMode::Select => {
if i > 0 { if i > 0 {
cur.idx = Some(i - 1); cur.idx = Some(i - 1);
self.cursor.set(cur); self.cursor.set(cur);
@ -355,7 +340,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
self.set_mode(ListCursorMode::Select); self.set_mode(ListCursorMode::Select);
self.pxev(); self.pxev();
for x in 1 .. depth { for _x in 1..depth {
self.dn(); self.dn();
self.goto_end(); self.goto_end();
} }
@ -367,8 +352,8 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} else { } else {
TreeNavResult::Exit TreeNavResult::Exit
} }
}, }
TreeNavResult::Continue => TreeNavResult::Continue TreeNavResult::Continue => TreeNavResult::Continue,
} }
} }
} }
@ -392,7 +377,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
} }
ListCursorMode::Select => { ListCursorMode::Select => {
if i+1 < self.data.len() { if i + 1 < self.data.len() {
cur.idx = Some(i + 1); cur.idx = Some(i + 1);
self.cursor.set(cur); self.cursor.set(cur);
TreeNavResult::Continue TreeNavResult::Continue
@ -414,12 +399,11 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
drop(ce); drop(ce);
self.up(); self.up();
if i+1 < self.data.len() { if i + 1 < self.data.len() {
self.set_mode(ListCursorMode::Select); self.set_mode(ListCursorMode::Select);
self.nexd(); self.nexd();
for x in 1 .. depth { for _x in 1..depth {
self.dn(); self.dn();
self.goto_home(); self.goto_home();
} }
@ -432,7 +416,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
TreeNavResult::Exit TreeNavResult::Exit
} }
} }
TreeNavResult::Continue => TreeNavResult::Continue TreeNavResult::Continue => TreeNavResult::Continue,
} }
} }
} }
@ -443,8 +427,9 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
impl<ItemEditor, FnMakeItemEditor> TerminalEditor for ListEditor<ItemEditor, FnMakeItemEditor> impl<ItemEditor, FnMakeItemEditor> TerminalEditor for ListEditor<ItemEditor, FnMakeItemEditor>
where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, where
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>> ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>>,
{ {
fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> { fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> {
match self.style { match self.style {
@ -454,7 +439,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
ListEditorStyle::String => self.string_view(), ListEditorStyle::String => self.string_view(),
ListEditorStyle::Clist => self.clist_view(), ListEditorStyle::Clist => self.clist_view(),
ListEditorStyle::Hex => self.hex_view(), ListEditorStyle::Hex => self.hex_view(),
ListEditorStyle::Plain => self.plain_view() ListEditorStyle::Plain => self.plain_view(),
} }
} }
@ -462,13 +447,12 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
let mut cur = self.cursor.get(); let mut cur = self.cursor.get();
if let Some(idx) = cur.idx { if let Some(idx) = cur.idx {
match cur.mode { match cur.mode {
ListCursorMode::Insert => { ListCursorMode::Insert => match event {
match event {
TerminalEvent::Input(Event::Key(Key::Backspace)) => { TerminalEvent::Input(Event::Key(Key::Backspace)) => {
if idx > 0 && idx <= self.data.len() { if idx > 0 && idx <= self.data.len() {
cur.idx = Some(idx-1); cur.idx = Some(idx - 1);
self.cursor.set(cur); self.cursor.set(cur);
self.data.remove(idx-1); self.data.remove(idx - 1);
TerminalEditorResult::Continue TerminalEditorResult::Continue
} else { } else {
TerminalEditorResult::Exit TerminalEditorResult::Exit
@ -482,8 +466,8 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
TerminalEditorResult::Exit TerminalEditorResult::Exit
} }
} }
TerminalEvent::Input(Event::Key(Key::Char('\t'))) | TerminalEvent::Input(Event::Key(Key::Char('\t')))
TerminalEvent::Input(Event::Key(Key::Insert)) => { | TerminalEvent::Input(Event::Key(Key::Insert)) => {
self.set_mode(ListCursorMode::Select); self.set_mode(ListCursorMode::Select);
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
@ -497,19 +481,17 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
TerminalEditorResult::Exit => { TerminalEditorResult::Exit => {
self.cursor.set(ListCursor { self.cursor.set(ListCursor {
mode: ListCursorMode::Insert, mode: ListCursorMode::Insert,
idx: Some(idx+1) idx: Some(idx + 1),
}); });
} }
_ => {} _ => {}
} }
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
} },
} ListCursorMode::Select => match event {
ListCursorMode::Select => { TerminalEvent::Input(Event::Key(Key::Char('\t')))
match event { | TerminalEvent::Input(Event::Key(Key::Insert)) => {
TerminalEvent::Input(Event::Key(Key::Char('\t'))) |
TerminalEvent::Input(Event::Key(Key::Insert)) => {
self.set_mode(ListCursorMode::Insert); self.set_mode(ListCursorMode::Insert);
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
@ -521,18 +503,15 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} else if idx == self.data.len() { } else if idx == self.data.len() {
self.cursor.set(ListCursor { self.cursor.set(ListCursor {
mode: ListCursorMode::Select, mode: ListCursorMode::Select,
idx: Some(idx-1) idx: Some(idx - 1),
}); });
} }
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
_ => { _ => TerminalEditorResult::Continue,
TerminalEditorResult::Continue },
}
}
}
ListCursorMode::Modify => { ListCursorMode::Modify => {
let mut ce = self.data.get_mut(idx); let ce = self.data.get_mut(idx);
let mut cur_edit = ce.write().unwrap(); let mut cur_edit = ce.write().unwrap();
match cur_edit.handle_terminal_event(event) { match cur_edit.handle_terminal_event(event) {
@ -546,7 +525,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
// todo: join instead of remove // todo: join instead of remove
self.cursor.set(ListCursor { self.cursor.set(ListCursor {
mode: ListCursorMode::Insert, mode: ListCursorMode::Insert,
idx: Some(idx) idx: Some(idx),
}); });
self.data.remove(idx); self.data.remove(idx);
@ -556,11 +535,11 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
self.cursor.set(ListCursor { self.cursor.set(ListCursor {
mode: ListCursorMode::Insert, mode: ListCursorMode::Insert,
idx: Some(idx+1) idx: Some(idx + 1),
}); });
} }
} }
}, }
TerminalEditorResult::Continue => {} TerminalEditorResult::Continue => {}
} }
@ -574,50 +553,55 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
impl<ItemEditor, FnMakeItemEditor> ListEditor<ItemEditor, FnMakeItemEditor> impl<ItemEditor, FnMakeItemEditor> ListEditor<ItemEditor, FnMakeItemEditor>
where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, where
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>> ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>>,
{ {
pub fn get_seg_seq_view(&self) -> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> { pub fn get_seg_seq_view(
&self,
) -> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> {
let segment_view_port = ViewPort::<dyn SequenceView<Item = ListEditorViewSegment>>::new(); let segment_view_port = ViewPort::<dyn SequenceView<Item = ListEditorViewSegment>>::new();
ListEditorView::new( ListEditorView::new(
self.cursor_port.outer(), self.cursor_port.outer(),
self.data_port.outer().to_sequence().map(|ed| ed.read().unwrap().get_term_view()), self.data_port
segment_view_port.inner() .outer()
.to_sequence()
.map(|ed| ed.read().unwrap().get_term_view()),
segment_view_port.inner(),
); );
segment_view_port.into_outer() segment_view_port.into_outer().map(move |segment| {
.map(
move |segment| {
let cursor_col = (90, 60, 200); let cursor_col = (90, 60, 200);
match segment { match segment {
ListEditorViewSegment::InsertCursor => ListEditorViewSegment::InsertCursor => {
make_label("|") make_label("|").map_item(move |_pt, atom| {
.map_item(
move |_pt, atom|
atom.add_style_back(TerminalStyle::fg_color(cursor_col)) atom.add_style_back(TerminalStyle::fg_color(cursor_col))
.add_style_back(TerminalStyle::bold(true)) .add_style_back(TerminalStyle::bold(true))
), })
ListEditorViewSegment::Select(sub_view) =>
sub_view.map_item(
move |_pt, atom| {
let old_col = atom.style.bg_color.unwrap_or(cursor_col);
atom.add_style_front(TerminalStyle::bg_color(((old_col.0 as f32 * 0.4) as u8, (old_col.1 as f32 * 0.4) as u8, (old_col.2 as f32 * 0.4) as u8)))
} }
), ListEditorViewSegment::Select(sub_view) => sub_view.map_item(move |_pt, atom| {
let old_col = atom.style.bg_color.unwrap_or(cursor_col);
atom.add_style_front(TerminalStyle::bg_color((
(old_col.0 as f32 * 0.4) as u8,
(old_col.1 as f32 * 0.4) as u8,
(old_col.2 as f32 * 0.4) as u8,
)))
}),
ListEditorViewSegment::Modify(sub_view) => { ListEditorViewSegment::Modify(sub_view) => {
sub_view.clone().map_item( sub_view.clone().map_item(
move |_pt, atom| { move |_pt, atom| {
let old_col = atom.style.bg_color.unwrap_or(cursor_col); let old_col = atom.style.bg_color.unwrap_or(cursor_col);
atom.add_style_front(TerminalStyle::bg_color(((old_col.0 as f32 * 0.4) as u8, (old_col.1 as f32 * 0.4) as u8, (old_col.2 as f32 * 0.4) as u8))) atom.add_style_front(TerminalStyle::bg_color((
} (old_col.0 as f32 * 0.4) as u8,
//.add_style_back(TerminalStyle::bold(true)) (old_col.1 as f32 * 0.4) as u8,
(old_col.2 as f32 * 0.4) as u8,
)))
}, //.add_style_back(TerminalStyle::bold(true))
) )
},
ListEditorViewSegment::View(sub_view) =>
sub_view.clone()
} }
ListEditorViewSegment::View(sub_view) => sub_view.clone(),
} }
) })
} }
pub fn horizontal_sexpr_view(&self) -> OuterViewPort<dyn TerminalView> { pub fn horizontal_sexpr_view(&self) -> OuterViewPort<dyn TerminalView> {
@ -639,7 +623,6 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
self.get_seg_seq_view() self.get_seg_seq_view()
.decorate("\"", "\"", "", 1) .decorate("\"", "\"", "", 1)
.to_grid_horizontal() .to_grid_horizontal()
.flatten() .flatten()
} }
@ -658,16 +641,14 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
pub fn plain_view(&self) -> OuterViewPort<dyn TerminalView> { pub fn plain_view(&self) -> OuterViewPort<dyn TerminalView> {
self.get_seg_seq_view() self.get_seg_seq_view().to_grid_horizontal().flatten()
.to_grid_horizontal()
.flatten()
} }
pub fn new(make_item_editor: FnMakeItemEditor, style: ListEditorStyle) -> Self { pub fn new(make_item_editor: FnMakeItemEditor, style: ListEditorStyle) -> Self {
let cursor_port = ViewPort::new(); let cursor_port = ViewPort::new();
let data_port = ViewPort::new(); let data_port = ViewPort::new();
let mut cursor = SingletonBuffer::new(ListCursor::default(), cursor_port.inner()); let cursor = SingletonBuffer::new(ListCursor::default(), cursor_port.inner());
let mut data = VecBuffer::<Arc<RwLock<ItemEditor>>>::new(data_port.inner()); let data = VecBuffer::<Arc<RwLock<ItemEditor>>>::new(data_port.inner());
let mut le = ListEditor { let mut le = ListEditor {
data, data,
@ -677,8 +658,8 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
style, style,
make_item_editor, make_item_editor,
level: 0, _level: 0,
cur_dist: Arc::new(RwLock::new(0)) cur_dist: Arc::new(RwLock::new(0)),
}; };
le.set_style(style); le.set_style(style);
le le
@ -708,6 +689,10 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
} }
pub fn clear(&mut self) {
self.data.clear();
}
fn set_idx(&mut self, idx: isize) { fn set_idx(&mut self, idx: isize) {
let cur = self.cursor.get(); let cur = self.cursor.get();
let mode = cur.mode; let mode = cur.mode;
@ -715,12 +700,12 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
if idx < 0 { if idx < 0 {
self.cursor.set(ListCursor { self.cursor.set(ListCursor {
mode, mode,
idx: Some((self.data.len() as isize + idx) as usize) idx: Some((self.data.len() as isize + idx) as usize),
}); });
} else { } else {
self.cursor.set(ListCursor { self.cursor.set(ListCursor {
mode, mode,
idx: Some(idx as usize) idx: Some(idx as usize),
}); });
} }
} }
@ -728,12 +713,10 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
fn set_mode(&mut self, mode: ListCursorMode) { fn set_mode(&mut self, mode: ListCursorMode) {
let mut cur = self.cursor.get(); let mut cur = self.cursor.get();
if cur.mode == ListCursorMode::Insert && if cur.mode == ListCursorMode::Insert && mode != ListCursorMode::Insert {
mode != ListCursorMode::Insert
{
if let Some(idx) = cur.idx { if let Some(idx) = cur.idx {
if idx == self.data.len() && idx > 0 { if idx == self.data.len() && idx > 0 {
cur.idx = Some(idx-1); cur.idx = Some(idx - 1);
} }
} }
} }
@ -745,8 +728,9 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
impl<ItemEditor, FnMakeItemEditor> ListEditor<ItemEditor, FnMakeItemEditor> impl<ItemEditor, FnMakeItemEditor> ListEditor<ItemEditor, FnMakeItemEditor>
where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, where
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>> ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>>,
{ {
fn set_leaf_mode(&mut self, mode: ListCursorMode) { fn set_leaf_mode(&mut self, mode: ListCursorMode) {
let mut c = self.get_cursor(); let mut c = self.get_cursor();
@ -754,4 +738,3 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
self.goto(c); self.goto(c);
} }
} }

View file

@ -1,30 +1,21 @@
use { use {
crate::{
core::{InnerViewPort, Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View},
list::{ListCursor, ListCursorMode},
projection::ProjectionHelper,
sequence::SequenceView,
singleton::SingletonView,
terminal::TerminalView,
},
std::sync::Arc, std::sync::Arc,
std::sync::RwLock, std::sync::RwLock,
crate::{
core::{
View,
InnerViewPort,
OuterViewPort,
Observer,
ObserverExt,
ObserverBroadcast
},
projection::ProjectionHelper,
singleton::SingletonView,
sequence::SequenceView,
terminal::TerminalView,
list::{ListCursor, ListCursorMode}
}
}; };
pub enum ListEditorViewSegment { pub enum ListEditorViewSegment {
InsertCursor, InsertCursor,
View(OuterViewPort<dyn TerminalView>), View(OuterViewPort<dyn TerminalView>),
Select(OuterViewPort<dyn TerminalView>), Select(OuterViewPort<dyn TerminalView>),
Modify(OuterViewPort<dyn TerminalView>) Modify(OuterViewPort<dyn TerminalView>),
} }
pub struct ListEditorView { pub struct ListEditorView {
@ -33,7 +24,7 @@ pub struct ListEditorView {
cur_cursor: ListCursor, cur_cursor: ListCursor,
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = ListEditorViewSegment>>>>, cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = ListEditorViewSegment>>>>,
proj_helper: ProjectionHelper<usize, Self> proj_helper: ProjectionHelper<usize, Self>,
} }
impl View for ListEditorView { impl View for ListEditorView {
@ -45,14 +36,15 @@ impl SequenceView for ListEditorView {
fn len(&self) -> Option<usize> { fn len(&self) -> Option<usize> {
match self.cursor.get().mode { match self.cursor.get().mode {
ListCursorMode::Insert => Some(self.data.len()? + if self.cur_cursor.idx.is_some() { 1 } else { 0 }), ListCursorMode::Insert => {
_ => self.data.len() Some(self.data.len()? + if self.cur_cursor.idx.is_some() { 1 } else { 0 })
}
_ => self.data.len(),
} }
} }
fn get(&self, idx: &usize) -> Option<Self::Item> { fn get(&self, idx: &usize) -> Option<Self::Item> {
Some( Some(if let Some(cur) = self.cur_cursor.idx {
if let Some(cur) = self.cur_cursor.idx {
match self.cur_cursor.mode { match self.cur_cursor.mode {
ListCursorMode::Select => { ListCursorMode::Select => {
if *idx == cur { if *idx == cur {
@ -67,7 +59,7 @@ impl SequenceView for ListEditorView {
} else if *idx == cur { } else if *idx == cur {
ListEditorViewSegment::InsertCursor ListEditorViewSegment::InsertCursor
} else { } else {
ListEditorViewSegment::View(self.data.get(&(idx-1))?) ListEditorViewSegment::View(self.data.get(&(idx - 1))?)
} }
} }
ListCursorMode::Modify => { ListCursorMode::Modify => {
@ -80,8 +72,7 @@ impl SequenceView for ListEditorView {
} }
} else { } else {
ListEditorViewSegment::View(self.data.get(&idx)?) ListEditorViewSegment::View(self.data.get(&idx)?)
} })
)
} }
} }
@ -89,28 +80,19 @@ impl ListEditorView {
pub fn new( pub fn new(
cursor_port: OuterViewPort<dyn SingletonView<Item = ListCursor>>, cursor_port: OuterViewPort<dyn SingletonView<Item = ListCursor>>,
data_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>, data_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
out_port: InnerViewPort<dyn SequenceView<Item = ListEditorViewSegment>> out_port: InnerViewPort<dyn SequenceView<Item = ListEditorViewSegment>>,
) -> Arc<RwLock<Self>> { ) -> Arc<RwLock<Self>> {
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone()); let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
let proj = Arc::new(RwLock::new( let proj = Arc::new(RwLock::new(ListEditorView {
ListEditorView {
cur_cursor: ListCursor::default(), cur_cursor: ListCursor::default(),
cursor: proj_helper.new_singleton_arg( cursor: proj_helper.new_singleton_arg(0, cursor_port, |s: &mut Self, _msg| {
0, let _old_cursor = s.cur_cursor;
cursor_port,
|s: &mut Self, _msg| {
let old_cursor = s.cur_cursor;
let new_cursor = s.cursor.get(); let new_cursor = s.cursor.get();
s.cur_cursor = new_cursor; s.cur_cursor = new_cursor;
s.cast.notify_each( s.cast.notify_each(0..=s.data.len().unwrap_or(0) + 1);
0 ..= s.data.len().unwrap_or(0)+1
);
}), }),
data: proj_helper.new_sequence_arg( data: proj_helper.new_sequence_arg(1, data_port, |s: &mut Self, idx| {
1,
data_port,
|s: &mut Self, idx| {
if let Some(cur_idx) = s.cur_cursor.idx { if let Some(cur_idx) = s.cur_cursor.idx {
match s.cur_cursor.mode { match s.cur_cursor.mode {
ListCursorMode::Insert => { ListCursorMode::Insert => {
@ -119,7 +101,7 @@ impl ListEditorView {
} else { } else {
s.cast.notify(&(*idx + 1)); s.cast.notify(&(*idx + 1));
} }
}, }
_ => { _ => {
s.cast.notify(idx); s.cast.notify(idx);
} }
@ -129,9 +111,8 @@ impl ListEditorView {
} }
}), }),
cast: out_port.get_broadcast(), cast: out_port.get_broadcast(),
proj_helper proj_helper,
} }));
));
proj.write().unwrap().proj_helper.set_proj(&proj); proj.write().unwrap().proj_helper.set_proj(&proj);
out_port.set_view(Some(proj.clone())); out_port.set_view(Some(proj.clone()));
@ -139,4 +120,3 @@ impl ListEditorView {
proj proj
} }
} }

View file

@ -1,10 +1,8 @@
pub mod sexpr;
pub mod cursor; pub mod cursor;
pub mod editor; pub mod editor;
pub mod editor_view; pub mod editor_view;
pub mod sexpr;
pub use sexpr::{SExprView, ListDecoration}; pub use cursor::{ListCursor, ListCursorMode};
pub use cursor::{ListCursorMode, ListCursor};
pub use editor::{ListEditor, ListEditorStyle}; pub use editor::{ListEditor, ListEditorStyle};
pub use sexpr::{ListDecoration, SExprView};

View file

@ -1,9 +1,9 @@
use { use {
crate::{ crate::{
core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View, ViewPort}, core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View, ViewPort},
index::IndexArea,
projection::ProjectionHelper, projection::ProjectionHelper,
sequence::SequenceView, sequence::SequenceView,
index::{IndexArea},
terminal::{make_label, TerminalStyle, TerminalView}, terminal::{make_label, TerminalStyle, TerminalView},
}, },
cgmath::Point2, cgmath::Point2,
@ -150,7 +150,8 @@ impl IndexView<Point2<i16>> for VerticalSexprDecorator {
fn area(&self) -> IndexArea<Point2<i16>> { fn area(&self) -> IndexArea<Point2<i16>> {
IndexArea::Range( IndexArea::Range(
Point2::new(0, 0) ..= Point2::new(2, std::cmp::max(self.items.len().unwrap() as i16 - 1, 0)) Point2::new(0, 0)
..=Point2::new(2, std::cmp::max(self.items.len().unwrap() as i16 - 1, 0)),
) )
} }
@ -216,11 +217,9 @@ impl VerticalSexprDecorator {
opening_port: make_label(opening), opening_port: make_label(opening),
closing_port: make_label(closing), closing_port: make_label(closing),
items: proj_helper.new_sequence_arg((), items_port, |s: &mut Self, item_idx| { items: proj_helper.new_sequence_arg((), items_port, |s: &mut Self, item_idx| {
s.cast.notify( s.cast.notify(&IndexArea::Range(
&IndexArea::Range( Point2::new(0, *item_idx as i16)..=Point2::new(2, *item_idx as i16),
Point2::new(0, *item_idx as i16) ..= Point2::new(2, *item_idx as i16) ));
)
);
}), }),
list_style: TerminalStyle::fg_color(match level { list_style: TerminalStyle::fg_color(match level {
0 => (200, 120, 10), 0 => (200, 120, 10),

View file

@ -1,51 +1,46 @@
use { use {
std::{
cmp::{max},
any::Any,
sync::{Arc, Weak},
hash::Hash,
collections::HashMap
},
std::sync::RwLock,
crate::{ crate::{
core::{ core::{
View, channel::{queue_channel, set_channel, ChannelData, ChannelReceiver, ChannelSender},
Observer, ObserverExt,
port::UpdateTask, port::UpdateTask,
OuterViewPort, Observer, ObserverExt, OuterViewPort, View,
channel::{ },
ChannelSender, ChannelReceiver, index::{IndexArea, IndexView},
ChannelData, sequence::SequenceView,
set_channel, singleton::SingletonView,
queue_channel },
} std::sync::RwLock,
std::{
any::Any,
cmp::max,
collections::HashMap,
hash::Hash,
sync::{Arc, Weak},
}, },
singleton::{SingletonView},
sequence::{SequenceView},
index::{IndexArea, IndexView}
}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct ProjectionHelper<ArgKey, P> pub struct ProjectionHelper<ArgKey, P>
where ArgKey: Clone + Hash + Eq, where
P: Send + Sync + 'static ArgKey: Clone + Hash + Eq,
P: Send + Sync + 'static,
{ {
keepalive: HashMap<ArgKey, (usize, Arc<dyn Any + Send + Sync>)>, keepalive: HashMap<ArgKey, (usize, Arc<dyn Any + Send + Sync>)>,
proj: Arc<RwLock<Weak<RwLock<P>>>>, proj: Arc<RwLock<Weak<RwLock<P>>>>,
update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>> update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>>,
} }
impl<ArgKey, P> ProjectionHelper<ArgKey, P> impl<ArgKey, P> ProjectionHelper<ArgKey, P>
where ArgKey: Clone + Hash + Eq, where
P: Send + Sync + 'static ArgKey: Clone + Hash + Eq,
P: Send + Sync + 'static,
{ {
pub fn new(update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>>) -> Self { pub fn new(update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>>) -> Self {
ProjectionHelper { ProjectionHelper {
keepalive: HashMap::new(), keepalive: HashMap::new(),
proj: Arc::new(RwLock::new(Weak::new())), proj: Arc::new(RwLock::new(Weak::new())),
update_hooks update_hooks,
} }
} }
@ -60,7 +55,7 @@ where ArgKey: Clone + Hash + Eq,
&mut self, &mut self,
arg_key: ArgKey, arg_key: ArgKey,
port: OuterViewPort<dyn SingletonView<Item = Item>>, port: OuterViewPort<dyn SingletonView<Item = Item>>,
notify: impl Fn(&mut P, &()) + Send + Sync + 'static notify: impl Fn(&mut P, &()) + Send + Sync + 'static,
) -> Arc<RwLock<Option<Arc<dyn SingletonView<Item = Item>>>>> { ) -> Arc<RwLock<Option<Arc<dyn SingletonView<Item = Item>>>>> {
port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, set_channel())); port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, set_channel()));
port.get_view_arc() port.get_view_arc()
@ -70,7 +65,7 @@ where ArgKey: Clone + Hash + Eq,
&mut self, &mut self,
arg_key: ArgKey, arg_key: ArgKey,
port: OuterViewPort<dyn SequenceView<Item = Item>>, port: OuterViewPort<dyn SequenceView<Item = Item>>,
notify: impl Fn(&mut P, &usize) + Send + Sync + 'static notify: impl Fn(&mut P, &usize) + Send + Sync + 'static,
) -> Arc<RwLock<Option<Arc<dyn SequenceView<Item = Item>>>>> { ) -> Arc<RwLock<Option<Arc<dyn SequenceView<Item = Item>>>>> {
port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, set_channel())); port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, set_channel()));
port.get_view_arc() port.get_view_arc()
@ -80,34 +75,31 @@ where ArgKey: Clone + Hash + Eq,
&mut self, &mut self,
arg_key: ArgKey, arg_key: ArgKey,
port: OuterViewPort<dyn IndexView<Key, Item = Item>>, port: OuterViewPort<dyn IndexView<Key, Item = Item>>,
notify: impl Fn(&mut P, &IndexArea<Key>) + Send + Sync + 'static notify: impl Fn(&mut P, &IndexArea<Key>) + Send + Sync + 'static,
) -> Arc<RwLock<Option<Arc<dyn IndexView<Key, Item = Item>>>>> { ) -> Arc<RwLock<Option<Arc<dyn IndexView<Key, Item = Item>>>>> {
port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, queue_channel())); port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, queue_channel()));
port.get_view_arc() port.get_view_arc()
} }
pub fn new_arg< pub fn new_arg<V: View + ?Sized + 'static, D: ChannelData<Item = V::Msg> + 'static>(
V: View + ?Sized + 'static,
D: ChannelData<Item = V::Msg> + 'static
>(
&mut self, &mut self,
arg_key: ArgKey, arg_key: ArgKey,
src_update: Arc<dyn UpdateTask>, src_update: Arc<dyn UpdateTask>,
notify: impl Fn(&mut P, &V::Msg) + Send + Sync + 'static, notify: impl Fn(&mut P, &V::Msg) + Send + Sync + 'static,
(tx, rx): (ChannelSender<D>, ChannelReceiver<D>) (tx, rx): (ChannelSender<D>, ChannelReceiver<D>),
) ) -> Arc<RwLock<ProjectionArg<P, V, D>>>
-> Arc<RwLock<ProjectionArg<P, V, D>>> where
where V::Msg: Send + Sync, V::Msg: Send + Sync,
D::IntoIter: Send + Sync + 'static D::IntoIter: Send + Sync + 'static,
{ {
self.remove_arg(&arg_key); self.remove_arg(&arg_key);
let arg = Arc::new(RwLock::new( let arg = Arc::new(RwLock::new(ProjectionArg {
ProjectionArg {
src: None, src: None,
notify: Box::new(notify), notify: Box::new(notify),
proj: self.proj.clone(), proj: self.proj.clone(),
rx, tx rx,
tx,
})); }));
let mut hooks = self.update_hooks.write().unwrap(); let mut hooks = self.update_hooks.write().unwrap();
@ -121,7 +113,7 @@ where ArgKey: Clone + Hash + Eq,
pub fn remove_arg(&mut self, arg_key: &ArgKey) { pub fn remove_arg(&mut self, arg_key: &ArgKey) {
let mut hooks = self.update_hooks.write().unwrap(); let mut hooks = self.update_hooks.write().unwrap();
if let Some((idx, arg)) = self.keepalive.remove(arg_key) { if let Some((idx, _arg)) = self.keepalive.remove(arg_key) {
hooks.remove(idx); hooks.remove(idx);
hooks.remove(idx); hooks.remove(idx);
for (_, (j, _)) in self.keepalive.iter_mut() { for (_, (j, _)) in self.keepalive.iter_mut() {
@ -136,33 +128,32 @@ where ArgKey: Clone + Hash + Eq,
/// Special Observer which can access the state of the projection on notify /// Special Observer which can access the state of the projection on notify
/// also handles the reset() /// also handles the reset()
pub struct ProjectionArg<P, V, D> pub struct ProjectionArg<P, V, D>
where P: Send + Sync + 'static, where
P: Send + Sync + 'static,
V: View + ?Sized, V: View + ?Sized,
D: ChannelData<Item = V::Msg>, D: ChannelData<Item = V::Msg>,
D::IntoIter: Send + Sync D::IntoIter: Send + Sync,
{ {
src: Option<Arc<V>>, src: Option<Arc<V>>,
notify: Box<dyn Fn(&mut P, &V::Msg) + Send + Sync + 'static>, notify: Box<dyn Fn(&mut P, &V::Msg) + Send + Sync + 'static>,
proj: Arc<RwLock<Weak<RwLock<P>>>>, proj: Arc<RwLock<Weak<RwLock<P>>>>,
rx: ChannelReceiver<D>, rx: ChannelReceiver<D>,
tx: ChannelSender<D> tx: ChannelSender<D>,
} }
impl<P, V, D> UpdateTask for ProjectionArg<P, V, D> impl<P, V, D> UpdateTask for ProjectionArg<P, V, D>
where P: Send + Sync + 'static, where
P: Send + Sync + 'static,
V: View + ?Sized, V: View + ?Sized,
D: ChannelData<Item = V::Msg>, D: ChannelData<Item = V::Msg>,
D::IntoIter: Send + Sync D::IntoIter: Send + Sync,
{ {
fn update(&self) { fn update(&self) {
if let Some(p) = self.proj.read().unwrap().upgrade() { if let Some(p) = self.proj.read().unwrap().upgrade() {
if let Some(data) = self.rx.try_recv() { if let Some(data) = self.rx.try_recv() {
for msg in data { for msg in data {
//eprintln!("proj update {:?}", msg); //eprintln!("proj update {:?}", msg);
(self.notify)( (self.notify)(&mut *p.write().unwrap(), &msg);
&mut *p.write().unwrap(),
&msg
);
} }
} }
} else { } else {
@ -172,10 +163,11 @@ where P: Send + Sync + 'static,
} }
impl<P, V, D> UpdateTask for RwLock<ProjectionArg<P, V, D>> impl<P, V, D> UpdateTask for RwLock<ProjectionArg<P, V, D>>
where P: Send + Sync + 'static, where
P: Send + Sync + 'static,
V: View + ?Sized, V: View + ?Sized,
D: ChannelData<Item = V::Msg>, D: ChannelData<Item = V::Msg>,
D::IntoIter: Send + Sync D::IntoIter: Send + Sync,
{ {
fn update(&self) { fn update(&self) {
self.read().unwrap().update(); self.read().unwrap().update();
@ -184,10 +176,12 @@ where P: Send + Sync + 'static,
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<P, Item, D> Observer<dyn SingletonView<Item = Item>> for ProjectionArg<P, dyn SingletonView<Item = Item>, D> impl<P, Item, D> Observer<dyn SingletonView<Item = Item>>
where P: Send + Sync + 'static, for ProjectionArg<P, dyn SingletonView<Item = Item>, D>
where
P: Send + Sync + 'static,
D: ChannelData<Item = ()>, D: ChannelData<Item = ()>,
D::IntoIter: Send + Sync D::IntoIter: Send + Sync,
{ {
fn reset(&mut self, new_src: Option<Arc<dyn SingletonView<Item = Item>>>) { fn reset(&mut self, new_src: Option<Arc<dyn SingletonView<Item = Item>>>) {
self.src = new_src; self.src = new_src;
@ -201,17 +195,19 @@ where P: Send + Sync + 'static,
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<P, Item, D> Observer<dyn SequenceView<Item = Item>> for ProjectionArg<P, dyn SequenceView<Item = Item>, D> impl<P, Item, D> Observer<dyn SequenceView<Item = Item>>
where P: Send + Sync + 'static, for ProjectionArg<P, dyn SequenceView<Item = Item>, D>
where
P: Send + Sync + 'static,
D: ChannelData<Item = usize>, D: ChannelData<Item = usize>,
D::IntoIter: Send + Sync D::IntoIter: Send + Sync,
{ {
fn reset(&mut self, new_src: Option<Arc<dyn SequenceView<Item = Item>>>) { fn reset(&mut self, new_src: Option<Arc<dyn SequenceView<Item = Item>>>) {
let old_len = self.src.len().unwrap_or(0); let old_len = self.src.len().unwrap_or(0);
self.src = new_src; self.src = new_src;
let new_len = self.src.len().unwrap_or(0); let new_len = self.src.len().unwrap_or(0);
self.notify_each(0 .. max(old_len, new_len)); self.notify_each(0..max(old_len, new_len));
} }
fn notify(&mut self, msg: &usize) { fn notify(&mut self, msg: &usize) {
@ -221,11 +217,13 @@ where P: Send + Sync + 'static,
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<P, Key, Item, D> Observer<dyn IndexView<Key, Item = Item>> for ProjectionArg<P, dyn IndexView<Key, Item = Item>, D> impl<P, Key, Item, D> Observer<dyn IndexView<Key, Item = Item>>
where P: Send + Sync + 'static, for ProjectionArg<P, dyn IndexView<Key, Item = Item>, D>
where
P: Send + Sync + 'static,
Key: Clone + Send + Sync, Key: Clone + Send + Sync,
D: ChannelData<Item = IndexArea<Key>>, D: ChannelData<Item = IndexArea<Key>>,
D::IntoIter: Send + Sync D::IntoIter: Send + Sync,
{ {
fn reset(&mut self, new_src: Option<Arc<dyn IndexView<Key, Item = Item>>>) { fn reset(&mut self, new_src: Option<Arc<dyn IndexView<Key, Item = Item>>>) {
let old_area = self.src.area(); let old_area = self.src.area();
@ -239,4 +237,3 @@ where P: Send + Sync + 'static,
self.tx.send(msg.clone()); self.tx.send(msg.clone());
} }
} }

View file

@ -1,33 +1,28 @@
use { use {
crate::{
core::{Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View, ViewPort},
sequence::SequenceView,
},
std::sync::Arc, std::sync::Arc,
std::sync::RwLock, std::sync::RwLock,
crate::{
sequence::{SequenceView},
core::{
Observer, ObserverExt, ObserverBroadcast,
View, ViewPort, OuterViewPort
}
}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<V: SequenceView + ?Sized + 'static> OuterViewPort<V> impl<V: SequenceView + ?Sized + 'static> OuterViewPort<V> {
{ pub fn filter<P: Fn(&V::Item) -> bool + Send + Sync + 'static>(
pub fn filter< &self,
P: Fn(&V::Item) -> bool + Send + Sync + 'static pred: P,
>(&self, pred: P) -> OuterViewPort<dyn SequenceView<Item = V::Item>> { ) -> OuterViewPort<dyn SequenceView<Item = V::Item>> {
let port = ViewPort::new(); let port = ViewPort::new();
port.add_update_hook(Arc::new(self.0.clone())); port.add_update_hook(Arc::new(self.0.clone()));
let filter = Arc::new(RwLock::new( let filter = Arc::new(RwLock::new(Filter {
Filter {
src_view: None, src_view: None,
pred, pred,
old_preds: RwLock::new(Vec::new()), old_preds: RwLock::new(Vec::new()),
cast: port.inner().get_broadcast() cast: port.inner().get_broadcast(),
} }));
));
self.add_observer(filter.clone()); self.add_observer(filter.clone());
port.inner().set_view(Some(filter)); port.inner().set_view(Some(filter));
@ -38,18 +33,20 @@ impl<V: SequenceView + ?Sized + 'static> OuterViewPort<V>
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
struct Filter<SrcView, P> struct Filter<SrcView, P>
where SrcView: SequenceView + ?Sized + 'static, where
P: Fn(&SrcView::Item) -> bool + Send + Sync + 'static SrcView: SequenceView + ?Sized + 'static,
P: Fn(&SrcView::Item) -> bool + Send + Sync + 'static,
{ {
src_view: Option<Arc<SrcView>>, src_view: Option<Arc<SrcView>>,
pred: P, pred: P,
old_preds: RwLock<Vec<bool>>, old_preds: RwLock<Vec<bool>>,
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = SrcView::Item>>>> cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = SrcView::Item>>>>,
} }
impl<SrcView, P> Filter<SrcView, P> impl<SrcView, P> Filter<SrcView, P>
where SrcView: SequenceView + ?Sized + 'static, where
P: Fn(&SrcView::Item) -> bool + Send + Sync + 'static SrcView: SequenceView + ?Sized + 'static,
P: Fn(&SrcView::Item) -> bool + Send + Sync + 'static,
{ {
fn get_offset(&self, idx: usize) -> usize { fn get_offset(&self, idx: usize) -> usize {
if let Some(v) = self.src_view.clone() { if let Some(v) = self.src_view.clone() {
@ -63,7 +60,7 @@ where SrcView: SequenceView + ?Sized + 'static,
} else { } else {
offset += 1; offset += 1;
} }
i+=1; i += 1;
} }
offset offset
@ -76,36 +73,39 @@ where SrcView: SequenceView + ?Sized + 'static,
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<SrcView, P> View for Filter<SrcView, P> impl<SrcView, P> View for Filter<SrcView, P>
where SrcView: SequenceView + ?Sized + 'static, where
P: Fn(&SrcView::Item) -> bool + Send + Sync + 'static SrcView: SequenceView + ?Sized + 'static,
P: Fn(&SrcView::Item) -> bool + Send + Sync + 'static,
{ {
type Msg = usize; type Msg = usize;
} }
impl<SrcView, P> SequenceView for Filter<SrcView, P> impl<SrcView, P> SequenceView for Filter<SrcView, P>
where SrcView: SequenceView + ?Sized + 'static, where
P: Fn(&SrcView::Item) -> bool + Send + Sync + 'static SrcView: SequenceView + ?Sized + 'static,
P: Fn(&SrcView::Item) -> bool + Send + Sync + 'static,
{ {
type Item = SrcView::Item; type Item = SrcView::Item;
fn len(&self) -> Option<usize> { fn len(&self) -> Option<usize> {
if let Some(src_len) = self.src_view.len() { if let Some(src_len) = self.src_view.len() {
Some(src_len - self.get_offset(src_len) ) Some(src_len - self.get_offset(src_len))
} else { } else {
None None
} }
} }
fn get(&self, idx: &usize) -> Option<Self::Item> { fn get(&self, idx: &usize) -> Option<Self::Item> {
self.src_view.get(&( idx + self.get_offset(*idx) )) self.src_view.get(&(idx + self.get_offset(*idx)))
} }
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<SrcView, P> Observer<SrcView> for Filter<SrcView, P> impl<SrcView, P> Observer<SrcView> for Filter<SrcView, P>
where SrcView: SequenceView + ?Sized + 'static, where
P: Fn(&SrcView::Item) -> bool + Send + Sync + 'static SrcView: SequenceView + ?Sized + 'static,
P: Fn(&SrcView::Item) -> bool + Send + Sync + 'static,
{ {
fn reset(&mut self, new_src: Option<Arc<SrcView>>) { fn reset(&mut self, new_src: Option<Arc<SrcView>>) {
let old_len = self.len(); let old_len = self.len();
@ -113,14 +113,17 @@ where SrcView: SequenceView + ?Sized + 'static,
self.old_preds = RwLock::new(Vec::new()); self.old_preds = RwLock::new(Vec::new());
let new_len = self.len(); let new_len = self.len();
if let Some(len) = old_len { self.cast.notify_each(0 .. len); } if let Some(len) = old_len {
if let Some(len) = new_len { self.cast.notify_each(0 .. len); } self.cast.notify_each(0..len);
}
if let Some(len) = new_len {
self.cast.notify_each(0..len);
}
} }
fn notify(&mut self, idx: &usize) { fn notify(&mut self, idx: &usize) {
let l = self.len().unwrap_or(0)+1; let l = self.len().unwrap_or(0) + 1;
let np = let np = if let Some(x) = self.src_view.get(idx) {
if let Some(x) = self.src_view.get(idx) {
(self.pred)(&x) (self.pred)(&x)
} else { } else {
false false
@ -128,29 +131,30 @@ where SrcView: SequenceView + ?Sized + 'static,
let mut opds = self.old_preds.write().unwrap(); let mut opds = self.old_preds.write().unwrap();
opds.resize_with(1+*idx, || false); opds.resize_with(1 + *idx, || false);
let op = opds.get(*idx).cloned().unwrap_or(false); let op = opds.get(*idx).cloned().unwrap_or(false);
*opds.get_mut(*idx).unwrap() = np; *opds.get_mut(*idx).unwrap() = np;
drop(opds); drop(opds);
let i = let i = (0..*idx)
(0 .. *idx) .map(|j| {
.map(
|j|
if let Some(x) = self.src_view.get(&j) { if let Some(x) = self.src_view.get(&j) {
if (self.pred)(&x) { 1 } else { 0 } if (self.pred)(&x) {
1
} else { } else {
0 0
} }
) } else {
0
}
})
.sum(); .sum();
if np != op { if np != op {
self.cast.notify_each(i .. l); self.cast.notify_each(i..l);
} else { } else {
self.cast.notify(&i); self.cast.notify(&i);
} }
} }
} }

View file

@ -1,22 +1,20 @@
use { use {
std::{
sync::Arc,
collections::BTreeMap
},
std::sync::RwLock,
crate::{ crate::{
core::{ core::{
View, Observer, ObserverBroadcast, ObserverExt, port::UpdateTask, InnerViewPort, Observer, ObserverBroadcast, ObserverExt,
ViewPort, InnerViewPort, OuterViewPort, OuterViewPort, View, ViewPort,
port::UpdateTask
}, },
projection::ProjectionHelper,
sequence::SequenceView, sequence::SequenceView,
projection::ProjectionHelper },
} std::sync::RwLock,
std::{collections::BTreeMap, sync::Arc},
}; };
impl<Item> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = Item>>>> impl<Item> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = Item>>>>
where Item: 'static{ where
Item: 'static,
{
pub fn flatten(&self) -> OuterViewPort<dyn SequenceView<Item = Item>> { pub fn flatten(&self) -> OuterViewPort<dyn SequenceView<Item = Item>> {
let port = ViewPort::new(); let port = ViewPort::new();
Flatten::new(self.clone(), port.inner()); Flatten::new(self.clone(), port.inner());
@ -25,31 +23,35 @@ where Item: 'static{
} }
pub struct Chunk<Item> pub struct Chunk<Item>
where Item: 'static where
Item: 'static,
{ {
offset: usize, offset: usize,
len: usize, len: usize,
view: Arc<dyn SequenceView<Item = Item>> view: Arc<dyn SequenceView<Item = Item>>,
} }
pub struct Flatten<Item> pub struct Flatten<Item>
where Item: 'static where
Item: 'static,
{ {
length: usize, length: usize,
top: Arc<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = Item>>>>, top: Arc<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = Item>>>>,
chunks: BTreeMap<usize, Chunk<Item>>, chunks: BTreeMap<usize, Chunk<Item>>,
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = Item>>>>, cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = Item>>>>,
proj_helper: ProjectionHelper<usize, Self> proj_helper: ProjectionHelper<usize, Self>,
} }
impl<Item> View for Flatten<Item> impl<Item> View for Flatten<Item>
where Item: 'static where
Item: 'static,
{ {
type Msg = usize; type Msg = usize;
} }
impl<Item> SequenceView for Flatten<Item> impl<Item> SequenceView for Flatten<Item>
where Item: 'static where
Item: 'static,
{ {
type Item = Item; type Item = Item;
@ -65,27 +67,25 @@ where Item: 'static
/* TODO: remove unused projection args (bot-views) if they get replaced by a new viewport */ /* TODO: remove unused projection args (bot-views) if they get replaced by a new viewport */
impl<Item> Flatten<Item> impl<Item> Flatten<Item>
where Item: 'static where
Item: 'static,
{ {
pub fn new( pub fn new(
top_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = Item>>>>, top_port: OuterViewPort<
out_port: InnerViewPort<dyn SequenceView<Item = Item>> dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = Item>>>,
>,
out_port: InnerViewPort<dyn SequenceView<Item = Item>>,
) -> Arc<RwLock<Self>> { ) -> Arc<RwLock<Self>> {
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone()); let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
let flat = Arc::new(RwLock::new( let flat = Arc::new(RwLock::new(Flatten {
Flatten {
length: 0, length: 0,
top: proj_helper.new_sequence_arg( top: proj_helper.new_sequence_arg(usize::MAX, top_port, |s: &mut Self, chunk_idx| {
usize::MAX,
top_port,
|s: &mut Self, chunk_idx| {
s.update_chunk(*chunk_idx); s.update_chunk(*chunk_idx);
} }),
),
chunks: BTreeMap::new(), chunks: BTreeMap::new(),
cast: out_port.get_broadcast(), cast: out_port.get_broadcast(),
proj_helper proj_helper,
})); }));
flat.write().unwrap().proj_helper.set_proj(&flat); flat.write().unwrap().proj_helper.set_proj(&flat);
@ -118,9 +118,9 @@ where Item: 'static
s.cast.notify(&(idx + chunk_offset)); s.cast.notify(&(idx + chunk_offset));
s.cast.notify_each(dirty_idx); s.cast.notify_each(dirty_idx);
} }
} },
) ),
} },
); );
chunk_port.0.update(); chunk_port.0.update();
@ -152,7 +152,7 @@ where Item: 'static
if old_offset != cur_offset { if old_offset != cur_offset {
dirty_idx.extend( dirty_idx.extend(
std::cmp::min(old_offset, cur_offset) std::cmp::min(old_offset, cur_offset)
.. std::cmp::max(old_offset, cur_offset) + chunk.len ..std::cmp::max(old_offset, cur_offset) + chunk.len,
); );
} }
@ -162,7 +162,7 @@ where Item: 'static
let old_length = self.length; let old_length = self.length;
self.length = cur_offset; self.length = cur_offset;
dirty_idx.extend(self.length .. old_length); dirty_idx.extend(self.length..old_length);
dirty_idx dirty_idx
} }
@ -179,4 +179,3 @@ where Item: 'static
None None
} }
} }

View file

@ -1,24 +1,18 @@
use { use {
crate::{
core::{Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View, ViewPort},
sequence::SequenceView,
},
std::sync::Arc, std::sync::Arc,
std::sync::RwLock, std::sync::RwLock,
crate::{
sequence::{SequenceView},
core::{
Observer, ObserverExt, ObserverBroadcast,
View, ViewPort, OuterViewPort
}
}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<Item: 'static> OuterViewPort<dyn SequenceView<Item = Item>> { impl<Item: 'static> OuterViewPort<dyn SequenceView<Item = Item>> {
pub fn map< pub fn map<DstItem: 'static, F: Fn(&Item) -> DstItem + Send + Sync + 'static>(
DstItem: 'static,
F: Fn(&Item) -> DstItem + Send + Sync + 'static
>(
&self, &self,
f: F f: F,
) -> OuterViewPort<dyn SequenceView<Item = DstItem>> { ) -> OuterViewPort<dyn SequenceView<Item = DstItem>> {
let port = ViewPort::new(); let port = ViewPort::new();
port.add_update_hook(Arc::new(self.0.clone())); port.add_update_hook(Arc::new(self.0.clone()));
@ -26,7 +20,7 @@ impl<Item: 'static> OuterViewPort<dyn SequenceView<Item = Item>> {
let map = Arc::new(RwLock::new(MapSequenceItem { let map = Arc::new(RwLock::new(MapSequenceItem {
src_view: None, src_view: None,
f, f,
cast: port.inner().get_broadcast() cast: port.inner().get_broadcast(),
})); }));
self.add_observer(map.clone()); self.add_observer(map.clone());
@ -36,10 +30,10 @@ impl<Item: 'static> OuterViewPort<dyn SequenceView<Item = Item>> {
pub fn filter_map< pub fn filter_map<
DstItem: Clone + 'static, DstItem: Clone + 'static,
F: Fn(&Item) -> Option<DstItem> + Send + Sync + 'static F: Fn(&Item) -> Option<DstItem> + Send + Sync + 'static,
>( >(
&self, &self,
f: F f: F,
) -> OuterViewPort<dyn SequenceView<Item = DstItem>> { ) -> OuterViewPort<dyn SequenceView<Item = DstItem>> {
self.map(f) self.map(f)
.filter(|x| x.is_some()) .filter(|x| x.is_some())
@ -50,26 +44,29 @@ impl<Item: 'static> OuterViewPort<dyn SequenceView<Item = Item>> {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct MapSequenceItem<DstItem, SrcView, F> pub struct MapSequenceItem<DstItem, SrcView, F>
where SrcView: SequenceView + ?Sized, where
F: Fn(&SrcView::Item) -> DstItem + Send + Sync SrcView: SequenceView + ?Sized,
F: Fn(&SrcView::Item) -> DstItem + Send + Sync,
{ {
src_view: Option<Arc<SrcView>>, src_view: Option<Arc<SrcView>>,
f: F, f: F,
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = DstItem>>>> cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = DstItem>>>>,
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<DstItem, SrcView, F> View for MapSequenceItem<DstItem, SrcView, F> impl<DstItem, SrcView, F> View for MapSequenceItem<DstItem, SrcView, F>
where SrcView: SequenceView + ?Sized, where
F: Fn(&SrcView::Item) -> DstItem + Send + Sync SrcView: SequenceView + ?Sized,
F: Fn(&SrcView::Item) -> DstItem + Send + Sync,
{ {
type Msg = usize; type Msg = usize;
} }
impl<DstItem, SrcView, F> SequenceView for MapSequenceItem<DstItem, SrcView, F> impl<DstItem, SrcView, F> SequenceView for MapSequenceItem<DstItem, SrcView, F>
where SrcView: SequenceView + ?Sized, where
F: Fn(&SrcView::Item) -> DstItem + Send + Sync SrcView: SequenceView + ?Sized,
F: Fn(&SrcView::Item) -> DstItem + Send + Sync,
{ {
type Item = DstItem; type Item = DstItem;
@ -85,20 +82,24 @@ where SrcView: SequenceView + ?Sized,
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<DstItem, SrcView, F> Observer<SrcView> for MapSequenceItem<DstItem, SrcView, F> impl<DstItem, SrcView, F> Observer<SrcView> for MapSequenceItem<DstItem, SrcView, F>
where SrcView: SequenceView + ?Sized, where
F: Fn(&SrcView::Item) -> DstItem + Send + Sync SrcView: SequenceView + ?Sized,
F: Fn(&SrcView::Item) -> DstItem + Send + Sync,
{ {
fn reset(&mut self, view: Option<Arc<SrcView>>) { fn reset(&mut self, view: Option<Arc<SrcView>>) {
let old_len = self.len(); let old_len = self.len();
self.src_view = view; self.src_view = view;
let new_len = self.len(); let new_len = self.len();
if let Some(len) = old_len { self.cast.notify_each(0 .. len ); } if let Some(len) = old_len {
if let Some(len) = new_len { self.cast.notify_each(0 .. len ); } self.cast.notify_each(0..len);
}
if let Some(len) = new_len {
self.cast.notify_each(0..len);
}
} }
fn notify(&mut self, msg: &usize) { fn notify(&mut self, msg: &usize) {
self.cast.notify(msg); self.cast.notify(msg);
} }
} }

View file

@ -1,16 +1,15 @@
pub mod seq2idx;
pub mod map;
pub mod filter; pub mod filter;
pub mod flatten; pub mod flatten;
pub mod map;
pub mod seq2idx;
pub use seq2idx::{Sequence2Index}; pub use seq2idx::Sequence2Index;
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
use crate::core::View; use crate::core::View;
pub trait SequenceView : View<Msg = usize> { pub trait SequenceView: View<Msg = usize> {
type Item; type Item;
fn get(&self, idx: &usize) -> Option<Self::Item>; fn get(&self, idx: &usize) -> Option<Self::Item>;
@ -19,12 +18,9 @@ pub trait SequenceView : View<Msg = usize> {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub trait SequenceViewExt : SequenceView { pub trait SequenceViewExt: SequenceView {
fn iter<'a>(&'a self) -> SequenceViewIter<'a, Self> { fn iter<'a>(&'a self) -> SequenceViewIter<'a, Self> {
SequenceViewIter { SequenceViewIter { view: self, cur: 0 }
view: self,
cur: 0
}
} }
} }
@ -33,14 +29,16 @@ impl<V: SequenceView + ?Sized> SequenceViewExt for V {}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct SequenceViewIter<'a, V> pub struct SequenceViewIter<'a, V>
where V: SequenceView + ?Sized where
V: SequenceView + ?Sized,
{ {
view: &'a V, view: &'a V,
cur: usize cur: usize,
} }
impl<'a, V> Iterator for SequenceViewIter<'a, V> impl<'a, V> Iterator for SequenceViewIter<'a, V>
where V: SequenceView + ?Sized where
V: SequenceView + ?Sized,
{ {
type Item = V::Item; type Item = V::Item;
@ -53,11 +51,8 @@ where V: SequenceView + ?Sized
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
use std::{
sync::Arc,
ops::{Deref}
};
use std::sync::RwLock; use std::sync::RwLock;
use std::{ops::Deref, sync::Arc};
impl<V: SequenceView + ?Sized> SequenceView for RwLock<V> { impl<V: SequenceView + ?Sized> SequenceView for RwLock<V> {
type Item = V::Item; type Item = V::Item;
@ -98,4 +93,3 @@ impl<V: SequenceView> SequenceView for Option<V> {
} }
} }
} }

View file

@ -1,37 +1,34 @@
use { use {
std::{
sync::Arc
},
std::sync::RwLock,
crate::{ crate::{
core::{ core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View, ViewPort},
View, Observer, ObserverBroadcast, grid::GridView,
ViewPort, InnerViewPort, OuterViewPort
},
sequence::SequenceView,
index::{IndexArea, IndexView}, index::{IndexArea, IndexView},
grid::GridView sequence::SequenceView,
} },
std::sync::Arc,
std::sync::RwLock,
}; };
/// Transforms a SequenceView into IndexView<usize> /// Transforms a SequenceView into IndexView<usize>
pub struct Sequence2Index<SrcView> pub struct Sequence2Index<SrcView>
where SrcView: SequenceView + ?Sized + 'static { where
SrcView: SequenceView + ?Sized + 'static,
{
src_view: Option<Arc<SrcView>>, src_view: Option<Arc<SrcView>>,
cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<usize, Item = SrcView::Item>>>> cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<usize, Item = SrcView::Item>>>>,
} }
impl<SrcView> Sequence2Index<SrcView> impl<SrcView> Sequence2Index<SrcView>
where SrcView: SequenceView + ?Sized + 'static { where
SrcView: SequenceView + ?Sized + 'static,
{
pub fn new( pub fn new(
port: InnerViewPort<dyn IndexView<usize, Item = SrcView::Item>> port: InnerViewPort<dyn IndexView<usize, Item = SrcView::Item>>,
) -> Arc<RwLock<Self>> { ) -> Arc<RwLock<Self>> {
let s2i = Arc::new(RwLock::new( let s2i = Arc::new(RwLock::new(Sequence2Index {
Sequence2Index {
src_view: None, src_view: None,
cast: port.get_broadcast() cast: port.get_broadcast(),
} }));
));
port.set_view(Some(s2i.clone())); port.set_view(Some(s2i.clone()));
s2i s2i
} }
@ -55,12 +52,16 @@ impl<Item: 'static> OuterViewPort<dyn SequenceView<Item = Item>> {
} }
impl<SrcView> View for Sequence2Index<SrcView> impl<SrcView> View for Sequence2Index<SrcView>
where SrcView: SequenceView + ?Sized + 'static { where
SrcView: SequenceView + ?Sized + 'static,
{
type Msg = IndexArea<usize>; type Msg = IndexArea<usize>;
} }
impl<SrcView> IndexView<usize> for Sequence2Index<SrcView> impl<SrcView> IndexView<usize> for Sequence2Index<SrcView>
where SrcView: SequenceView + ?Sized + 'static { where
SrcView: SequenceView + ?Sized + 'static,
{
type Item = SrcView::Item; type Item = SrcView::Item;
fn get(&self, key: &usize) -> Option<Self::Item> { fn get(&self, key: &usize) -> Option<Self::Item> {
@ -70,7 +71,7 @@ where SrcView: SequenceView + ?Sized + 'static {
fn area(&self) -> IndexArea<usize> { fn area(&self) -> IndexArea<usize> {
if let Some(len) = self.src_view.len() { if let Some(len) = self.src_view.len() {
if len > 0 { if len > 0 {
IndexArea::Range(0 ..= len-1) IndexArea::Range(0..=len - 1)
} else { } else {
IndexArea::Empty IndexArea::Empty
} }
@ -81,7 +82,9 @@ where SrcView: SequenceView + ?Sized + 'static {
} }
impl<SrcView> Observer<SrcView> for Sequence2Index<SrcView> impl<SrcView> Observer<SrcView> for Sequence2Index<SrcView>
where SrcView: SequenceView + ?Sized + 'static { where
SrcView: SequenceView + ?Sized + 'static,
{
fn reset(&mut self, view: Option<Arc<SrcView>>) { fn reset(&mut self, view: Option<Arc<SrcView>>) {
let old_area = self.area(); let old_area = self.area();
self.src_view = view; self.src_view = view;
@ -91,7 +94,6 @@ where SrcView: SequenceView + ?Sized + 'static {
} }
fn notify(&mut self, idx: &usize) { fn notify(&mut self, idx: &usize) {
self.cast.notify(&IndexArea::Set(vec![ *idx ])); self.cast.notify(&IndexArea::Set(vec![*idx]));
} }
} }

View file

@ -1,18 +1,13 @@
use { use {
std::{ crate::{
sync::{Arc}, core::{InnerViewPort, Observer, ObserverBroadcast, View},
ops::{Deref, DerefMut} singleton::SingletonView,
}, },
std::sync::RwLock, std::sync::RwLock,
crate::{ std::{
core::{ ops::{Deref, DerefMut},
Observer, sync::Arc,
ObserverBroadcast,
View,
InnerViewPort
}, },
singleton::{SingletonView}
}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -20,12 +15,16 @@ use {
pub struct SingletonBufferView<T: Clone + Send + Sync + 'static>(Arc<RwLock<T>>); pub struct SingletonBufferView<T: Clone + Send + Sync + 'static>(Arc<RwLock<T>>);
impl<T> View for SingletonBufferView<T> impl<T> View for SingletonBufferView<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
type Msg = (); type Msg = ();
} }
impl<T> SingletonView for SingletonBufferView<T> impl<T> SingletonView for SingletonBufferView<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
type Item = T; type Item = T;
fn get(&self) -> Self::Item { fn get(&self) -> Self::Item {
@ -37,23 +36,24 @@ where T: Clone + Send + Sync + 'static {
#[derive(Clone)] #[derive(Clone)]
pub struct SingletonBuffer<T> pub struct SingletonBuffer<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
value: Arc<RwLock<T>>, value: Arc<RwLock<T>>,
cast: Arc<RwLock<ObserverBroadcast<dyn SingletonView<Item = T>>>> cast: Arc<RwLock<ObserverBroadcast<dyn SingletonView<Item = T>>>>,
} }
impl<T> SingletonBuffer<T> impl<T> SingletonBuffer<T>
where T: Clone + Send + Sync + 'static { where
pub fn new( T: Clone + Send + Sync + 'static,
value: T, {
port: InnerViewPort<dyn SingletonView<Item = T>> pub fn new(value: T, port: InnerViewPort<dyn SingletonView<Item = T>>) -> Self {
) -> Self {
let value = Arc::new(RwLock::new(value)); let value = Arc::new(RwLock::new(value));
port.set_view(Some(Arc::new(SingletonBufferView(value.clone())))); port.set_view(Some(Arc::new(SingletonBufferView(value.clone()))));
SingletonBuffer { SingletonBuffer {
value, value,
cast: port.get_broadcast() cast: port.get_broadcast(),
} }
} }
@ -64,7 +64,7 @@ where T: Clone + Send + Sync + 'static {
pub fn get_mut(&self) -> MutableSingletonAccess<T> { pub fn get_mut(&self) -> MutableSingletonAccess<T> {
MutableSingletonAccess { MutableSingletonAccess {
buf: self.clone(), buf: self.clone(),
val: self.get() val: self.get(),
} }
} }
@ -79,13 +79,17 @@ where T: Clone + Send + Sync + 'static {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct MutableSingletonAccess<T> pub struct MutableSingletonAccess<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
buf: SingletonBuffer<T>, buf: SingletonBuffer<T>,
val: T, val: T,
} }
impl<T> Deref for MutableSingletonAccess<T> impl<T> Deref for MutableSingletonAccess<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
type Target = T; type Target = T;
fn deref(&self) -> &T { fn deref(&self) -> &T {
@ -94,17 +98,19 @@ where T: Clone + Send + Sync + 'static {
} }
impl<T> DerefMut for MutableSingletonAccess<T> impl<T> DerefMut for MutableSingletonAccess<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.val &mut self.val
} }
} }
impl<T> Drop for MutableSingletonAccess<T> impl<T> Drop for MutableSingletonAccess<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
fn drop(&mut self) { fn drop(&mut self) {
self.buf.set(self.val.clone()); self.buf.set(self.val.clone());
} }
} }

View file

@ -1,24 +1,18 @@
use { use {
crate::{
core::{Observer, ObserverBroadcast, OuterViewPort, View, ViewPort},
singleton::SingletonView,
},
std::sync::Arc, std::sync::Arc,
std::sync::RwLock, std::sync::RwLock,
crate::{
singleton::{SingletonView},
core::{
Observer, ObserverBroadcast,
View, ViewPort, OuterViewPort
}
}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<Item: 'static> OuterViewPort<dyn SingletonView<Item = Item>> { impl<Item: 'static> OuterViewPort<dyn SingletonView<Item = Item>> {
pub fn map< pub fn map<DstItem: 'static, F: Fn(Item) -> DstItem + Send + Sync + 'static>(
DstItem: 'static,
F: Fn(Item) -> DstItem + Send + Sync + 'static
>(
&self, &self,
f: F f: F,
) -> OuterViewPort<dyn SingletonView<Item = DstItem>> { ) -> OuterViewPort<dyn SingletonView<Item = DstItem>> {
let port = ViewPort::new(); let port = ViewPort::new();
port.add_update_hook(Arc::new(self.0.clone())); port.add_update_hook(Arc::new(self.0.clone()));
@ -26,7 +20,7 @@ impl<Item: 'static> OuterViewPort<dyn SingletonView<Item = Item>> {
let map = Arc::new(RwLock::new(MapSingleton { let map = Arc::new(RwLock::new(MapSingleton {
src_view: None, src_view: None,
f, f,
cast: port.inner().get_broadcast() cast: port.inner().get_broadcast(),
})); }));
self.add_observer(map.clone()); self.add_observer(map.clone());
@ -38,26 +32,29 @@ impl<Item: 'static> OuterViewPort<dyn SingletonView<Item = Item>> {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct MapSingleton<DstItem, SrcView, F> pub struct MapSingleton<DstItem, SrcView, F>
where SrcView: SingletonView + ?Sized, where
F: Fn(SrcView::Item) -> DstItem + Send + Sync SrcView: SingletonView + ?Sized,
F: Fn(SrcView::Item) -> DstItem + Send + Sync,
{ {
src_view: Option<Arc<SrcView>>, src_view: Option<Arc<SrcView>>,
f: F, f: F,
cast: Arc<RwLock<ObserverBroadcast<dyn SingletonView<Item = DstItem>>>> cast: Arc<RwLock<ObserverBroadcast<dyn SingletonView<Item = DstItem>>>>,
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<DstItem, SrcView, F> View for MapSingleton<DstItem, SrcView, F> impl<DstItem, SrcView, F> View for MapSingleton<DstItem, SrcView, F>
where SrcView: SingletonView + ?Sized, where
F: Fn(SrcView::Item) -> DstItem + Send + Sync SrcView: SingletonView + ?Sized,
F: Fn(SrcView::Item) -> DstItem + Send + Sync,
{ {
type Msg = (); type Msg = ();
} }
impl<DstItem, SrcView, F> SingletonView for MapSingleton<DstItem, SrcView, F> impl<DstItem, SrcView, F> SingletonView for MapSingleton<DstItem, SrcView, F>
where SrcView: SingletonView + ?Sized, where
F: Fn(SrcView::Item) -> DstItem + Send + Sync SrcView: SingletonView + ?Sized,
F: Fn(SrcView::Item) -> DstItem + Send + Sync,
{ {
type Item = DstItem; type Item = DstItem;
@ -69,8 +66,9 @@ where SrcView: SingletonView + ?Sized,
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<DstItem, SrcView, F> Observer<SrcView> for MapSingleton<DstItem, SrcView, F> impl<DstItem, SrcView, F> Observer<SrcView> for MapSingleton<DstItem, SrcView, F>
where SrcView: SingletonView + ?Sized, where
F: Fn(SrcView::Item) -> DstItem + Send + Sync SrcView: SingletonView + ?Sized,
F: Fn(SrcView::Item) -> DstItem + Send + Sync,
{ {
fn reset(&mut self, view: Option<Arc<SrcView>>) { fn reset(&mut self, view: Option<Arc<SrcView>>) {
self.src_view = view; self.src_view = view;
@ -81,4 +79,3 @@ where SrcView: SingletonView + ?Sized,
self.cast.notify(msg); self.cast.notify(msg);
} }
} }

View file

@ -1,22 +1,18 @@
pub mod buffer; pub mod buffer;
pub mod map; pub mod map;
pub mod to_index; pub mod to_index;
//pub mod unwrap; //pub mod unwrap;
use { use {
std::{ crate::core::View,
sync::Arc,
ops::Deref
},
std::sync::RwLock, std::sync::RwLock,
crate::core::{View} std::{ops::Deref, sync::Arc},
}; };
pub use buffer::SingletonBuffer; pub use buffer::SingletonBuffer;
// TODO: #[ImplForArc, ImplForRwLock] // TODO: #[ImplForArc, ImplForRwLock]
pub trait SingletonView : View<Msg = ()> { pub trait SingletonView: View<Msg = ()> {
type Item; type Item;
fn get(&self) -> Self::Item; fn get(&self) -> Self::Item;
@ -41,7 +37,9 @@ impl<V: SingletonView + ?Sized> SingletonView for Arc<V> {
} }
impl<V: SingletonView> SingletonView for Option<V> impl<V: SingletonView> SingletonView for Option<V>
where V::Item: Default{ where
V::Item: Default,
{
type Item = V::Item; type Item = V::Item;
fn get(&self) -> Self::Item { fn get(&self) -> Self::Item {
@ -65,4 +63,3 @@ impl<T> OuterViewPort<dyn SingletonView<Item = T>> {
} }
} }
*/ */

View file

@ -1,15 +1,12 @@
use { use {
crate::{
core::{Observer, ObserverBroadcast, OuterViewPort, View, ViewPort},
grid::GridView,
index::{IndexArea, IndexView},
singleton::SingletonView,
},
std::sync::Arc, std::sync::Arc,
std::sync::RwLock, std::sync::RwLock,
crate::{
singleton::{SingletonView},
index::{IndexArea, IndexView},
grid::{GridView},
core::{
Observer, ObserverBroadcast,
View, ViewPort, OuterViewPort
}
}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -21,7 +18,7 @@ impl<Item: 'static> OuterViewPort<dyn SingletonView<Item = Item>> {
let map = Arc::new(RwLock::new(Singleton2Index { let map = Arc::new(RwLock::new(Singleton2Index {
src_view: None, src_view: None,
cast: port.inner().get_broadcast() cast: port.inner().get_broadcast(),
})); }));
self.add_observer(map.clone()); self.add_observer(map.clone());
@ -30,10 +27,15 @@ impl<Item: 'static> OuterViewPort<dyn SingletonView<Item = Item>> {
} }
pub fn to_grid(&self) -> OuterViewPort<dyn GridView<Item = Item>> { pub fn to_grid(&self) -> OuterViewPort<dyn GridView<Item = Item>> {
self.to_index() self.to_index().map_key(
.map_key(
|_msg: &()| cgmath::Point2::new(0, 0), |_msg: &()| cgmath::Point2::new(0, 0),
|pt| if pt.x == 0 && pt.y == 0 { Some(()) } else { None } |pt| {
if pt.x == 0 && pt.y == 0 {
Some(())
} else {
None
}
},
) )
} }
} }
@ -41,22 +43,25 @@ impl<Item: 'static> OuterViewPort<dyn SingletonView<Item = Item>> {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct Singleton2Index<SrcView> pub struct Singleton2Index<SrcView>
where SrcView: SingletonView + ?Sized where
SrcView: SingletonView + ?Sized,
{ {
src_view: Option<Arc<SrcView>>, src_view: Option<Arc<SrcView>>,
cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<(), Item = SrcView::Item>>>> cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<(), Item = SrcView::Item>>>>,
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<SrcView> View for Singleton2Index<SrcView> impl<SrcView> View for Singleton2Index<SrcView>
where SrcView: SingletonView + ?Sized where
SrcView: SingletonView + ?Sized,
{ {
type Msg = IndexArea<()>; type Msg = IndexArea<()>;
} }
impl<SrcView> IndexView<()> for Singleton2Index<SrcView> impl<SrcView> IndexView<()> for Singleton2Index<SrcView>
where SrcView: SingletonView + ?Sized where
SrcView: SingletonView + ?Sized,
{ {
type Item = SrcView::Item; type Item = SrcView::Item;
@ -72,7 +77,8 @@ where SrcView: SingletonView + ?Sized
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<SrcView> Observer<SrcView> for Singleton2Index<SrcView> impl<SrcView> Observer<SrcView> for Singleton2Index<SrcView>
where SrcView: SingletonView + ?Sized where
SrcView: SingletonView + ?Sized,
{ {
fn reset(&mut self, view: Option<Arc<SrcView>>) { fn reset(&mut self, view: Option<Arc<SrcView>>) {
self.src_view = view; self.src_view = view;
@ -83,4 +89,3 @@ where SrcView: SingletonView + ?Sized
self.cast.notify(&IndexArea::Full); self.cast.notify(&IndexArea::Full);
} }
} }

View file

@ -1,30 +1,32 @@
use { use {
crate::{
core::{OuterViewPort, ViewPort},
list::{sexpr::ListDecoration, ListEditor},
sequence::SequenceView,
singleton::{SingletonBuffer, SingletonView},
terminal::{
TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView,
},
tree_nav::{TreeCursor, TreeNav, TreeNavResult},
},
std::sync::Arc, std::sync::Arc,
std::sync::RwLock, std::sync::RwLock,
termion::event::{Key, Event}, termion::event::{Event, Key},
crate::{
core::{ViewPort, OuterViewPort},
singleton::{SingletonView, SingletonBuffer},
sequence::{SequenceView},
terminal::{TerminalView, TerminalStyle, TerminalEvent, TerminalEditor, TerminalEditorResult},
list::{ListEditor, sexpr::ListDecoration},
tree_nav::{TreeNav, TreeNavResult, TreeCursor}
}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct CharEditor { pub struct CharEditor {
data: SingletonBuffer<Option<char>>, data: SingletonBuffer<Option<char>>,
data_port: ViewPort<dyn SingletonView<Item = Option<char>>> data_port: ViewPort<dyn SingletonView<Item = Option<char>>>,
} }
impl CharEditor { impl CharEditor {
pub fn new() -> Self { pub fn new() -> Self {
let mut data_port = ViewPort::new(); let data_port = ViewPort::new();
CharEditor { CharEditor {
data: SingletonBuffer::new(None, data_port.inner()), data: SingletonBuffer::new(None, data_port.inner()),
data_port data_port,
} }
} }
@ -36,8 +38,7 @@ impl CharEditor {
impl TreeNav for CharEditor {} impl TreeNav for CharEditor {}
impl TerminalEditor for CharEditor { impl TerminalEditor for CharEditor {
fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> { fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> {
crate::terminal::make_label( crate::terminal::make_label(&if let Some(c) = self.data.get() {
&if let Some(c) = self.data.get() {
c.to_string() c.to_string()
} else { } else {
"".to_string() "".to_string()
@ -46,18 +47,17 @@ impl TerminalEditor for CharEditor {
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
match event { match event {
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => TerminalEvent::Input(Event::Key(Key::Char('\n'))) => TerminalEditorResult::Continue,
TerminalEditorResult::Continue,
TerminalEvent::Input(Event::Key(Key::Char(c))) => { TerminalEvent::Input(Event::Key(Key::Char(c))) => {
self.data.set(Some(*c)); self.data.set(Some(*c));
TerminalEditorResult::Exit TerminalEditorResult::Exit
} }
TerminalEvent::Input(Event::Key(Key::Backspace)) | TerminalEvent::Input(Event::Key(Key::Backspace))
TerminalEvent::Input(Event::Key(Key::Delete)) => { | TerminalEvent::Input(Event::Key(Key::Delete)) => {
self.data.set(None); self.data.set(None);
TerminalEditorResult::Exit TerminalEditorResult::Exit
} }
_ => TerminalEditorResult::Continue _ => TerminalEditorResult::Continue,
} }
} }
} }
@ -65,41 +65,52 @@ impl TerminalEditor for CharEditor {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct StringEditor { pub struct StringEditor {
chars_editor: ListEditor< CharEditor, chars_editor:
Box<dyn Fn() -> Arc<RwLock<CharEditor>> + Send + Sync + 'static> > ListEditor<CharEditor, Box<dyn Fn() -> Arc<RwLock<CharEditor>> + Send + Sync + 'static>>,
} }
impl StringEditor { impl StringEditor {
pub fn new() -> Self { pub fn new() -> Self {
StringEditor { StringEditor {
chars_editor: ListEditor::new( chars_editor: ListEditor::new(
Box::new( Box::new(move || Arc::new(RwLock::new(CharEditor::new()))),
move || { crate::list::ListEditorStyle::String,
Arc::new(RwLock::new(CharEditor::new()))
}
), ),
crate::list::ListEditorStyle::String
)
} }
} }
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = char>> { pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = char>> {
self.chars_editor.get_data_port() self.chars_editor
.map( .get_data_port()
|char_editor| char_editor.read().unwrap().data.get().unwrap() .map(|char_editor| char_editor.read().unwrap().data.get().unwrap())
)
} }
} }
impl TreeNav for StringEditor { impl TreeNav for StringEditor {
fn get_cursor(&self) -> TreeCursor { self.chars_editor.get_cursor() } fn get_cursor(&self) -> TreeCursor {
fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { self.chars_editor.goto(cur) } self.chars_editor.get_cursor()
fn goto_home(&mut self) -> TreeNavResult { self.chars_editor.goto_home() } }
fn goto_end(&mut self) -> TreeNavResult { self.chars_editor.goto_end() } fn goto(&mut self, cur: TreeCursor) -> TreeNavResult {
fn pxev(&mut self) -> TreeNavResult { self.chars_editor.pxev() } self.chars_editor.goto(cur)
fn nexd(&mut self) -> TreeNavResult { self.chars_editor.nexd() } }
fn up(&mut self) -> TreeNavResult { self.chars_editor.up() } fn goto_home(&mut self) -> TreeNavResult {
fn dn(&mut self) -> TreeNavResult { TreeNavResult::Exit } self.chars_editor.goto_home()
}
fn goto_end(&mut self) -> TreeNavResult {
self.chars_editor.goto_end()
}
fn pxev(&mut self) -> TreeNavResult {
self.chars_editor.pxev()
}
fn nexd(&mut self) -> TreeNavResult {
self.chars_editor.nexd()
}
fn up(&mut self) -> TreeNavResult {
self.chars_editor.up()
}
fn dn(&mut self) -> TreeNavResult {
TreeNavResult::Exit
}
} }
impl TerminalEditor for StringEditor { impl TerminalEditor for StringEditor {
@ -109,10 +120,7 @@ impl TerminalEditor for StringEditor {
.decorate("\"", "\"", "", 1) .decorate("\"", "\"", "", 1)
.to_grid_horizontal() .to_grid_horizontal()
.flatten() .flatten()
.map_item( .map_item(|_idx, atom| atom.add_style_back(TerminalStyle::fg_color((120, 200, 10))))
|_idx, atom|
atom.add_style_back(TerminalStyle::fg_color((120, 200, 10)))
)
} }
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
@ -121,8 +129,7 @@ impl TerminalEditor for StringEditor {
self.chars_editor.up(); self.chars_editor.up();
TerminalEditorResult::Exit TerminalEditorResult::Exit
} }
event => self.chars_editor.handle_terminal_event(event) event => self.chars_editor.handle_terminal_event(event),
} }
} }
} }

View file

@ -1,37 +1,25 @@
use { use {
std::{
sync::{Arc, RwLock},
pin::Pin,
fs::File,
os::unix::io::FromRawFd
},
std::io::Read,
//async_std::{io::{Read, ReadExt}}, //async_std::{io::{Read, ReadExt}},
crate::{ crate::{
core::{View, InnerViewPort, OuterViewPort, ViewPort, Observer, ObserverBroadcast}, core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View, ViewPort},
index::{buffer::IndexBuffer, IndexArea, IndexView},
projection::ProjectionHelper, projection::ProjectionHelper,
terminal::{ singleton::{SingletonBuffer, SingletonView},
TerminalAtom, terminal::{TerminalAtom, TerminalStyle, TerminalView},
TerminalStyle,
TerminalView
}, },
singleton::{ cgmath::{Point2, Vector2},
SingletonBuffer, std::io::Read,
SingletonView std::sync::{Arc, RwLock},
}, vte::{Params, Parser, Perform},
index::{
buffer::IndexBuffer,
IndexView,
IndexArea
}
},
cgmath::{Vector2, Point2},
vte::{Params, Parser, Perform}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub fn read_ansi_from<R: Read + Unpin>(ansi_reader: &mut R, max_size: Vector2<i16>, port: InnerViewPort<dyn TerminalView>) { pub fn read_ansi_from<R: Read + Unpin>(
ansi_reader: &mut R,
max_size: Vector2<i16>,
port: InnerViewPort<dyn TerminalView>,
) {
let mut statemachine = Parser::new(); let mut statemachine = Parser::new();
let buf_port = ViewPort::new(); let buf_port = ViewPort::new();
@ -56,17 +44,16 @@ pub fn read_ansi_from<R: Read + Unpin>(ansi_reader: &mut R, max_size: Vector2<i1
blue: (0, 111, 184), blue: (0, 111, 184),
magenta: (118, 38, 113), magenta: (118, 38, 113),
cyan: (44, 181, 233), cyan: (44, 181, 233),
white: (204, 204, 204) white: (204, 204, 204),
}, },
pty_proj: PtyView::new( _pty_proj: PtyView::new(
buf_port.outer(), buf_port.outer(),
cursor_port.outer().map(|x| Some(x)), cursor_port.outer().map(|x| Some(x)),
offset_port.outer().map(|x| Some(x)), offset_port.outer().map(|x| Some(x)),
size_port.outer().map(|x| Some(x)), size_port.outer().map(|x| Some(x)),
port,
port ),
)
}; };
let mut buf = [0; 2048]; let mut buf = [0; 2048];
@ -78,11 +65,11 @@ pub fn read_ansi_from<R: Read + Unpin>(ansi_reader: &mut R, max_size: Vector2<i1
for byte in &buf[..n] { for byte in &buf[..n] {
statemachine.advance(&mut performer, *byte); statemachine.advance(&mut performer, *byte);
} }
}, }
Err(err) => { Err(_err) => {
//println!("err: {}", err); //println!("err: {}", err);
break; break;
}, }
} }
} }
} }
@ -93,14 +80,22 @@ enum TTYColor {
Rgb(u8, u8, u8), Rgb(u8, u8, u8),
// 3-Bit/4-Bit colors // 3-Bit/4-Bit colors
Black, LightBlack, Black,
Red, LightRed, LightBlack,
Green, LightGreen, Red,
Yellow, LightYellow, LightRed,
Blue, LightBlue, Green,
Magenta,LightMagenta, LightGreen,
Cyan, LightCyan, Yellow,
White, LightWhite, LightYellow,
Blue,
LightBlue,
Magenta,
LightMagenta,
Cyan,
LightCyan,
White,
LightWhite,
} }
struct ColorPalett { struct ColorPalett {
@ -117,7 +112,7 @@ struct ColorPalett {
impl ColorPalett { impl ColorPalett {
fn get_rgb(&self, col: &TTYColor) -> (u8, u8, u8) { fn get_rgb(&self, col: &TTYColor) -> (u8, u8, u8) {
match col { match col {
TTYColor::Rgb(r,g,b) => (*r,*g,*b), TTYColor::Rgb(r, g, b) => (*r, *g, *b),
TTYColor::Black | TTYColor::LightBlack => self.black, TTYColor::Black | TTYColor::LightBlack => self.black,
TTYColor::Red | TTYColor::LightRed => self.red, TTYColor::Red | TTYColor::LightRed => self.red,
TTYColor::Green | TTYColor::LightGreen => self.green, TTYColor::Green | TTYColor::LightGreen => self.green,
@ -146,7 +141,7 @@ struct PtyView {
max_pt: Point2<i16>, max_pt: Point2<i16>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>, cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
proj_helper: ProjectionHelper<usize, Self> proj_helper: ProjectionHelper<usize, Self>,
} }
impl View for PtyView { impl View for PtyView {
@ -160,13 +155,16 @@ impl IndexView<Point2<i16>> for PtyView {
let atom = self.buf.get(&(pt + self.old_offset)); let atom = self.buf.get(&(pt + self.old_offset));
if self.old_curpos == *pt { if self.old_curpos == *pt {
if let Some(mut a) = atom { if let Some(mut a) = atom {
let bg_col = a.style.fg_color.unwrap_or((255,255,255)); let bg_col = a.style.fg_color.unwrap_or((255, 255, 255));
let fg_col = a.style.bg_color.unwrap_or((0,0,0)); let fg_col = a.style.bg_color.unwrap_or((0, 0, 0));
a.style.fg_color = Some(fg_col); a.style.fg_color = Some(fg_col);
a.style.bg_color = Some(bg_col); a.style.bg_color = Some(bg_col);
Some(a) Some(a)
} else { } else {
Some(TerminalAtom::new(' ', TerminalStyle::bg_color((255, 255, 255)))) Some(TerminalAtom::new(
' ',
TerminalStyle::bg_color((255, 255, 255)),
))
} }
} else { } else {
atom atom
@ -174,10 +172,13 @@ impl IndexView<Point2<i16>> for PtyView {
} }
fn area(&self) -> IndexArea<Point2<i16>> { fn area(&self) -> IndexArea<Point2<i16>> {
IndexArea::Range(Point2::new(0, 0) ..= Point2::new( IndexArea::Range(
Point2::new(0, 0)
..=Point2::new(
std::cmp::max(self.old_curpos.x, self.max_pt.x), std::cmp::max(self.old_curpos.x, self.max_pt.x),
std::cmp::max(self.old_curpos.y, self.max_pt.y) std::cmp::max(self.old_curpos.y, self.max_pt.y),
)) ),
)
} }
} }
@ -188,29 +189,22 @@ impl PtyView {
offset_port: OuterViewPort<dyn SingletonView<Item = Option<Vector2<i16>>>>, offset_port: OuterViewPort<dyn SingletonView<Item = Option<Vector2<i16>>>>,
size_port: OuterViewPort<dyn SingletonView<Item = Option<Vector2<i16>>>>, size_port: OuterViewPort<dyn SingletonView<Item = Option<Vector2<i16>>>>,
out_port: InnerViewPort<dyn TerminalView> out_port: InnerViewPort<dyn TerminalView>,
) -> Arc<RwLock<Self>> { ) -> Arc<RwLock<Self>> {
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone()); let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
let proj = Arc::new(RwLock::new( let proj = Arc::new(RwLock::new(PtyView {
PtyView {
old_curpos: Point2::new(0, 0), old_curpos: Point2::new(0, 0),
old_size: Vector2::new(0, 0), old_size: Vector2::new(0, 0),
old_offset: Vector2::new(0, 0), old_offset: Vector2::new(0, 0),
max_pt: Point2::new(0, 0), max_pt: Point2::new(0, 0),
curpos: proj_helper.new_singleton_arg( curpos: proj_helper.new_singleton_arg(0, curpos_port, |s: &mut Self, _msg| {
0, s.cast.notify(&IndexArea::Set(vec![s.old_curpos]));
curpos_port, s.old_curpos = s.curpos.get().unwrap_or(Point2::new(0, 0));
|s: &mut Self, _msg| { s.cast.notify(&IndexArea::Set(vec![s.old_curpos]));
s.cast.notify(&IndexArea::Set(vec![ s.old_curpos ]));
s.old_curpos = s.curpos.get().unwrap_or(Point2::new(0,0));
s.cast.notify(&IndexArea::Set(vec![ s.old_curpos ]));
}), }),
offset: proj_helper.new_singleton_arg( offset: proj_helper.new_singleton_arg(1, offset_port, |s: &mut Self, _msg| {
1,
offset_port,
|s: &mut Self, _msg| {
// todo // todo
let new_offset = s.offset.get().unwrap_or(Vector2::new(0, 0)); let new_offset = s.offset.get().unwrap_or(Vector2::new(0, 0));
if s.old_offset != new_offset { if s.old_offset != new_offset {
@ -219,10 +213,7 @@ impl PtyView {
} }
}), }),
size: proj_helper.new_singleton_arg( size: proj_helper.new_singleton_arg(2, size_port, |s: &mut Self, _msg| {
2,
size_port,
|s: &mut Self, _msg| {
let new_size = s.size.get().unwrap_or(Vector2::new(0, 0)); let new_size = s.size.get().unwrap_or(Vector2::new(0, 0));
if s.old_size != new_size { if s.old_size != new_size {
s.old_size = new_size; s.old_size = new_size;
@ -230,16 +221,9 @@ impl PtyView {
} }
}), }),
buf: proj_helper.new_index_arg( buf: proj_helper.new_index_arg(3, buf_port, |s: &mut Self, area| {
3,
buf_port,
|s: &mut Self, area| {
let size = s.old_size; let size = s.old_size;
let area = area.map( let area = area.map(|pt| *pt - s.old_offset);
|pt| {
*pt - s.old_offset
}
);
if s.max_pt.x < size.x || s.max_pt.y < size.y { if s.max_pt.x < size.x || s.max_pt.y < size.y {
match &area { match &area {
@ -264,9 +248,8 @@ impl PtyView {
}), }),
cast: out_port.get_broadcast(), cast: out_port.get_broadcast(),
proj_helper proj_helper,
} }));
));
proj.write().unwrap().proj_helper.set_proj(&proj); proj.write().unwrap().proj_helper.set_proj(&proj);
out_port.set_view(Some(proj.clone())); out_port.set_view(Some(proj.clone()));
@ -288,12 +271,12 @@ struct PerfAtom {
colors: ColorPalett, colors: ColorPalett,
pty_proj: Arc<RwLock<PtyView>> _pty_proj: Arc<RwLock<PtyView>>,
} }
impl PerfAtom { impl PerfAtom {
fn write_atom(&mut self, pos: Point2<i16>, atom: Option<TerminalAtom>) { fn write_atom(&mut self, pos: Point2<i16>, atom: Option<TerminalAtom>) {
if let Some(mut a) = atom { if let Some(a) = atom {
self.buf.insert(pos + self.offset.get(), a); self.buf.insert(pos + self.offset.get(), a);
} else { } else {
self.buf.remove(pos); self.buf.remove(pos);
@ -310,11 +293,15 @@ impl PerfAtom {
} }
fn set_fg_color(&mut self, col: &TTYColor) { fn set_fg_color(&mut self, col: &TTYColor) {
self.cursty = self.cursty.add(TerminalStyle::fg_color(self.colors.get_rgb(col))); self.cursty = self
.cursty
.add(TerminalStyle::fg_color(self.colors.get_rgb(col)));
} }
fn set_bg_color(&mut self, col: &TTYColor) { fn set_bg_color(&mut self, col: &TTYColor) {
self.cursty = self.cursty.add(TerminalStyle::bg_color(self.colors.get_rgb(col))); self.cursty = self
.cursty
.add(TerminalStyle::bg_color(self.colors.get_rgb(col)));
} }
fn linefeed(&mut self) { fn linefeed(&mut self) {
@ -322,7 +309,7 @@ impl PerfAtom {
let mut c = self.cursor.get_mut(); let mut c = self.cursor.get_mut();
c.x = 0; c.x = 0;
if c.y+1 >= size.y { if c.y + 1 >= size.y {
self.scroll_up(1); self.scroll_up(1);
} else { } else {
c.y += 1; c.y += 1;
@ -365,14 +352,14 @@ impl PerfAtom {
c.y += n as i16; c.y += n as i16;
} else { } else {
let r = (n as i16) - (s.y - 1 - c.y); let r = (n as i16) - (s.y - 1 - c.y);
c.y = s.y-1; c.y = s.y - 1;
self.scroll_up(r as usize); self.scroll_up(r as usize);
} }
} }
fn cursor_pxev(&mut self, n: usize) { fn cursor_pxev(&mut self, n: usize) {
let mut c = self.cursor.get_mut(); let mut c = self.cursor.get_mut();
let s = self.size.get(); let _s = self.size.get();
if c.y - (n as i16) >= 0 { if c.y - (n as i16) >= 0 {
c.y -= n as i16; c.y -= n as i16;
@ -392,7 +379,7 @@ impl PerfAtom {
} }
} }
fn insert_blank_lines(&mut self, n: usize) { fn insert_blank_lines(&mut self, _n: usize) {
//eprintln!("insert blank lines"); //eprintln!("insert blank lines");
} }
@ -437,7 +424,7 @@ impl Perform for PerfAtom {
} }
} }
fn hook(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) { fn hook(&mut self, _params: &Params, _intermediates: &[u8], _ignore: bool, _c: char) {
/* /*
eprintln!( eprintln!(
"[hook] params={:?}, intermediates={:?}, ignore={:?}, char={:?}", "[hook] params={:?}, intermediates={:?}, ignore={:?}, char={:?}",
@ -446,7 +433,7 @@ impl Perform for PerfAtom {
*/ */
} }
fn put(&mut self, byte: u8) { fn put(&mut self, _byte: u8) {
/* /*
eprintln!("[put] {:02x}", byte); eprintln!("[put] {:02x}", byte);
*/ */
@ -456,7 +443,7 @@ impl Perform for PerfAtom {
//eprintln!("[unhook]"); //eprintln!("[unhook]");
} }
fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) { fn osc_dispatch(&mut self, params: &[&[u8]], _bell_terminated: bool) {
//eprintln!("[osc_dispatch] params={:?} bell_terminated={}", params, bell_terminated); //eprintln!("[osc_dispatch] params={:?} bell_terminated={}", params, bell_terminated);
match params[0] { match params[0] {
@ -465,17 +452,18 @@ impl Perform for PerfAtom {
// Reset background color // Reset background color
b"111" => self.set_bg_color(&TTYColor::Black), b"111" => self.set_bg_color(&TTYColor::Black),
// Reset text cursor color // Reset text cursor color
b"112" => {}, b"112" => {}
_ => {} _ => {}
} }
} }
fn csi_dispatch(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) { fn csi_dispatch(&mut self, params: &Params, _intermediates: &[u8], _ignore: bool, c: char) {
let mut piter = params.into_iter(); let mut piter = params.into_iter();
match c { match c {
// Set SGR // Set SGR
'm' => while let Some(n) = piter.next() { 'm' => {
while let Some(n) = piter.next() {
match n[0] { match n[0] {
0 => { 0 => {
self.cursty = TerminalStyle::default(); self.cursty = TerminalStyle::default();
@ -527,16 +515,16 @@ impl Perform for PerfAtom {
let r = piter.next().unwrap()[0] as u8; let r = piter.next().unwrap()[0] as u8;
let g = piter.next().unwrap()[0] as u8; let g = piter.next().unwrap()[0] as u8;
let b = piter.next().unwrap()[0] as u8; let b = piter.next().unwrap()[0] as u8;
self.set_fg_color(&TTYColor::Rgb(r,g,b)); self.set_fg_color(&TTYColor::Rgb(r, g, b));
}, }
5 => { 5 => {
let v = piter.next().unwrap(); let v = piter.next().unwrap();
let rgb = ansi_colours::rgb_from_ansi256(v[0] as u8); let rgb = ansi_colours::rgb_from_ansi256(v[0] as u8);
self.set_fg_color(&TTYColor::Rgb(rgb.0, rgb.1, rgb.2)); self.set_fg_color(&TTYColor::Rgb(rgb.0, rgb.1, rgb.2));
}, }
_ => {} _ => {}
} }
}, }
48 => { 48 => {
let x = piter.next().unwrap(); let x = piter.next().unwrap();
match x[0] { match x[0] {
@ -544,28 +532,33 @@ impl Perform for PerfAtom {
let r = piter.next().unwrap()[0] as u8; let r = piter.next().unwrap()[0] as u8;
let g = piter.next().unwrap()[0] as u8; let g = piter.next().unwrap()[0] as u8;
let b = piter.next().unwrap()[0] as u8; let b = piter.next().unwrap()[0] as u8;
self.set_bg_color(&TTYColor::Rgb(r,g,b)); self.set_bg_color(&TTYColor::Rgb(r, g, b));
}, }
5 => { 5 => {
let v = piter.next().unwrap(); let v = piter.next().unwrap();
let rgb = ansi_colours::rgb_from_ansi256(v[0] as u8); let rgb = ansi_colours::rgb_from_ansi256(v[0] as u8);
self.set_bg_color(&TTYColor::Rgb(rgb.0, rgb.1, rgb.2)); self.set_bg_color(&TTYColor::Rgb(rgb.0, rgb.1, rgb.2));
}, }
_ => {} _ => {}
} }
}, }
_ => {} _ => {}
} }
} }
}
'@' => { '@' => {
let n = piter.next().unwrap_or(&[1])[0] as usize; let n = piter.next().unwrap_or(&[1])[0] as usize;
for _ in 0..n { for _ in 0..n {
self.print(' '); self.print(' ');
} }
} }
'A' => { self.cursor_up(piter.next().unwrap_or(&[1])[0] as usize); } 'A' => {
'B' => { self.cursor_dn(piter.next().unwrap_or(&[1])[0] as usize); } self.cursor_up(piter.next().unwrap_or(&[1])[0] as usize);
}
'B' => {
self.cursor_dn(piter.next().unwrap_or(&[1])[0] as usize);
}
'C' | 'a' => { 'C' | 'a' => {
self.cursor_nexd(piter.next().unwrap_or(&[1])[0] as usize); self.cursor_nexd(piter.next().unwrap_or(&[1])[0] as usize);
} }
@ -587,7 +580,6 @@ impl Perform for PerfAtom {
let mut c = self.cursor.get_mut(); let mut c = self.cursor.get_mut();
c.x = 0; c.x = 0;
c.y -= piter.next().unwrap_or(&[1])[0] as i16; c.y -= piter.next().unwrap_or(&[1])[0] as i16;
} }
'G' | '`' => { 'G' | '`' => {
self.cursor.get_mut().x = piter.next().unwrap_or(&[1])[0] as i16 - 1; self.cursor.get_mut().x = piter.next().unwrap_or(&[1])[0] as i16 - 1;
@ -600,7 +592,6 @@ impl Perform for PerfAtom {
'J' => { 'J' => {
let x = piter.next().unwrap_or(&[0 as u16; 1]); let x = piter.next().unwrap_or(&[0 as u16; 1]);
match x[0] { match x[0] {
// clear from cursor until end of screen // clear from cursor until end of screen
0 => { 0 => {
let mut pos = self.cursor.get(); let mut pos = self.cursor.get();
@ -613,7 +604,7 @@ impl Perform for PerfAtom {
pos.y += 1; pos.y += 1;
} }
} }
}, }
// clear from cursor to begin // clear from cursor to begin
1 => { 1 => {
@ -633,8 +624,8 @@ impl Perform for PerfAtom {
// erase entire screen // erase entire screen
2 => { 2 => {
for y in 0 .. 100 { for y in 0..100 {
for x in 0 .. self.size.get().x { for x in 0..self.size.get().x {
self.write_atom(Point2::new(x, y), None); self.write_atom(Point2::new(x, y), None);
} }
} }
@ -649,30 +640,38 @@ impl Perform for PerfAtom {
'K' => { 'K' => {
let x = piter.next().unwrap_or(&[0]); let x = piter.next().unwrap_or(&[0]);
match x[0] { match x[0] {
// clear from cursor until end of line // clear from cursor until end of line
0 => { 0 => {
let c = self.cursor.get(); let c = self.cursor.get();
for x in c.x .. self.size.get().x { for x in c.x..self.size.get().x {
self.write_atom(Point2::new(x, c.y), Some(TerminalAtom::new(' ', self.get_style()))); self.write_atom(
Point2::new(x, c.y),
Some(TerminalAtom::new(' ', self.get_style())),
);
}
} }
},
// clear from start of line until cursor // clear from start of line until cursor
1 => { 1 => {
let c = self.cursor.get(); let c = self.cursor.get();
for x in 0 .. c.x { for x in 0..c.x {
self.write_atom(Point2::new(x, c.y), Some(TerminalAtom::new(' ', self.get_style()))); self.write_atom(
Point2::new(x, c.y),
Some(TerminalAtom::new(' ', self.get_style())),
);
}
} }
},
// clear entire line // clear entire line
2 => { 2 => {
let c = self.cursor.get(); let c = self.cursor.get();
for x in 0 .. self.size.get().x { for x in 0..self.size.get().x {
self.write_atom(Point2::new(x, c.y), Some(TerminalAtom::new(' ', self.get_style()))); self.write_atom(
Point2::new(x, c.y),
Some(TerminalAtom::new(' ', self.get_style())),
);
}
} }
},
// invalid // invalid
_ => {} _ => {}
@ -691,7 +690,7 @@ impl Perform for PerfAtom {
self.write_atom(Point2::new(x, self.cursor.y+y), None); self.write_atom(Point2::new(x, self.cursor.y+y), None);
} }
} }
*/ */
} }
/* /*
'P' => { 'P' => {
@ -699,38 +698,49 @@ impl Perform for PerfAtom {
self.backspace(); self.backspace();
} }
} }
*/ */
'X' => { 'X' => {
//eprintln!("delete chars"); //eprintln!("delete chars");
let c = self.cursor.get(); let c = self.cursor.get();
for x in 0 .. piter.next().unwrap_or(&[1])[0] { for x in 0..piter.next().unwrap_or(&[1])[0] {
self.write_atom(Point2::new(c.x + x as i16, c.y), Some(TerminalAtom::new(' ', self.get_style()))); self.write_atom(
Point2::new(c.x + x as i16, c.y),
Some(TerminalAtom::new(' ', self.get_style())),
);
} }
} }
'S' => { self.scroll_up(piter.next().unwrap_or(&[1])[0] as usize); } 'S' => {
'T' => { self.scroll_dn(piter.next().unwrap_or(&[1])[0] as usize); } self.scroll_up(piter.next().unwrap_or(&[1])[0] as usize);
's' => { self.save_cursor_position(); } }
'u' => { self.restore_cursor_position(); } 'T' => {
self.scroll_dn(piter.next().unwrap_or(&[1])[0] as usize);
}
's' => {
self.save_cursor_position();
}
'u' => {
self.restore_cursor_position();
}
_ => { _ => {
/* /*
eprintln!( eprintln!(
"[csi_dispatch] params={:#?}, intermediates={:?}, ignore={:?}, char={:?}", "[csi_dispatch] params={:#?}, intermediates={:?}, ignore={:?}, char={:?}",
params, intermediates, ignore, c params, intermediates, ignore, c
); );
*/ */
} }
} }
} }
fn esc_dispatch(&mut self, intermediates: &[u8], ignore: bool, byte: u8) { fn esc_dispatch(&mut self, intermediates: &[u8], _ignore: bool, byte: u8) {
match (byte, intermediates) { match (byte, intermediates) {
//(b'B', intermediates) => configure_charset!(StandardCharset::Ascii, intermediates), //(b'B', intermediates) => configure_charset!(StandardCharset::Ascii, intermediates),
(b'D', []) => self.linefeed(), (b'D', []) => self.linefeed(),
(b'E', []) => { (b'E', []) => {
self.linefeed(); self.linefeed();
self.carriage_return(); self.carriage_return();
}, }
/* /*
(b'H', []) => self.handler.set_horizontal_tabstop(), (b'H', []) => self.handler.set_horizontal_tabstop(),
(b'M', []) => self.handler.reverse_index(), (b'M', []) => self.handler.reverse_index(),
@ -739,14 +749,14 @@ impl Perform for PerfAtom {
(b'0', intermediates) => { (b'0', intermediates) => {
configure_charset!(StandardCharset::SpecialCharacterAndLineDrawing, intermediates) configure_charset!(StandardCharset::SpecialCharacterAndLineDrawing, intermediates)
}, },
*/ */
(b'7', []) => self.save_cursor_position(), (b'7', []) => self.save_cursor_position(),
//(b'8', [b'#']) => self.handler.decaln(), //(b'8', [b'#']) => self.handler.decaln(),
(b'8', []) => self.restore_cursor_position(), (b'8', []) => self.restore_cursor_position(),
/* /*
(b'=', []) => self.handler.set_keypad_application_mode(), (b'=', []) => self.handler.set_keypad_application_mode(),
(b'>', []) => self.handler.unset_keypad_application_mode(), (b'>', []) => self.handler.unset_keypad_application_mode(),
**/ **/
// String terminator, do nothing (parser handles as string terminator). // String terminator, do nothing (parser handles as string terminator).
(b'\\', []) => (), (b'\\', []) => (),
_ => { _ => {
@ -755,10 +765,8 @@ impl Perform for PerfAtom {
"unhandled esc_dispatch intermediates={:?}, ignore={:?}, byte={:02x}", "unhandled esc_dispatch intermediates={:?}, ignore={:?}, byte={:02x}",
intermediates, ignore, byte intermediates, ignore, byte
); );
*/ */
} }
} }
} }
} }

View file

@ -1,12 +1,12 @@
use { use {
super::TerminalStyle, super::TerminalStyle,
serde::{Serialize, Deserialize} serde::{Deserialize, Serialize},
}; };
#[derive(Clone, Copy, Serialize, Deserialize, Debug)] #[derive(Clone, Copy, Serialize, Deserialize, Debug)]
pub struct TerminalAtom { pub struct TerminalAtom {
pub c: Option<char>, pub c: Option<char>,
pub style: TerminalStyle pub style: TerminalStyle,
} }
impl TerminalAtom { impl TerminalAtom {
@ -15,7 +15,10 @@ impl TerminalAtom {
} }
pub fn new_bg(bg_color: (u8, u8, u8)) -> Self { pub fn new_bg(bg_color: (u8, u8, u8)) -> Self {
TerminalAtom { c: None, style: TerminalStyle::bg_color(bg_color) } TerminalAtom {
c: None,
style: TerminalStyle::bg_color(bg_color),
}
} }
pub fn add_style_front(mut self, style: TerminalStyle) -> Self { pub fn add_style_front(mut self, style: TerminalStyle) -> Self {
@ -33,7 +36,7 @@ impl From<char> for TerminalAtom {
fn from(c: char) -> Self { fn from(c: char) -> Self {
TerminalAtom { TerminalAtom {
c: Some(c), c: Some(c),
style: TerminalStyle::default() style: TerminalStyle::default(),
} }
} }
} }
@ -42,7 +45,7 @@ impl From<Option<char>> for TerminalAtom {
fn from(c: Option<char>) -> Self { fn from(c: Option<char>) -> Self {
TerminalAtom { TerminalAtom {
c, c,
style: TerminalStyle::default() style: TerminalStyle::default(),
} }
} }
} }
@ -51,8 +54,7 @@ impl From<&char> for TerminalAtom {
fn from(c: &char) -> Self { fn from(c: &char) -> Self {
TerminalAtom { TerminalAtom {
c: Some(*c), c: Some(*c),
style: TerminalStyle::default() style: TerminalStyle::default(),
} }
} }
} }

View file

@ -1,15 +1,13 @@
use { use {
std::{
sync::{Arc}
},
std::sync::RwLock,
cgmath::Point2,
crate::{ crate::{
core::{InnerViewPort, OuterViewPort, View, Observer, ObserverBroadcast}, core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View},
index::{IndexArea, IndexView}, index::{IndexArea, IndexView},
projection::ProjectionHelper,
terminal::{TerminalAtom, TerminalView}, terminal::{TerminalAtom, TerminalView},
projection::ProjectionHelper },
} cgmath::Point2,
std::sync::Arc,
std::sync::RwLock,
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -17,22 +15,18 @@ use {
pub struct TerminalCompositor { pub struct TerminalCompositor {
layers: Vec<Arc<dyn TerminalView>>, layers: Vec<Arc<dyn TerminalView>>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>, cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
proj_helper: ProjectionHelper<usize, Self> proj_helper: ProjectionHelper<usize, Self>,
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl TerminalCompositor { impl TerminalCompositor {
pub fn new( pub fn new(port: InnerViewPort<dyn TerminalView>) -> Arc<RwLock<Self>> {
port: InnerViewPort<dyn TerminalView> let comp = Arc::new(RwLock::new(TerminalCompositor {
) -> Arc<RwLock<Self>> {
let comp = Arc::new(RwLock::new(
TerminalCompositor {
layers: Vec::new(), layers: Vec::new(),
cast: port.get_broadcast(), cast: port.get_broadcast(),
proj_helper: ProjectionHelper::new(port.0.update_hooks.clone()) proj_helper: ProjectionHelper::new(port.0.update_hooks.clone()),
} }));
));
comp.write().unwrap().proj_helper.set_proj(&comp); comp.write().unwrap().proj_helper.set_proj(&comp);
port.set_view(Some(comp.clone())); port.set_view(Some(comp.clone()));
@ -43,13 +37,10 @@ impl TerminalCompositor {
pub fn push(&mut self, v: OuterViewPort<dyn TerminalView>) { pub fn push(&mut self, v: OuterViewPort<dyn TerminalView>) {
let idx = self.layers.len(); let idx = self.layers.len();
self.layers.push( self.layers.push(
self.proj_helper.new_index_arg( self.proj_helper
idx, .new_index_arg(idx, v, |s: &mut Self, area| {
v,
|s: &mut Self, area| {
s.cast.notify(area); s.cast.notify(area);
} }),
)
); );
} }
} }
@ -87,4 +78,3 @@ impl IndexView<Point2<i16>> for TerminalCompositor {
area area
} }
} }

View file

@ -1,21 +1,17 @@
pub mod style;
pub mod atom;
pub mod terminal;
pub mod compositor;
pub mod ansi_parser; pub mod ansi_parser;
pub mod atom;
pub mod compositor;
pub mod style;
pub mod terminal;
pub use { pub use {
style::{TerminalStyle}, atom::TerminalAtom,
atom::{TerminalAtom},
terminal::{Terminal, TerminalEvent},
compositor::TerminalCompositor, compositor::TerminalCompositor,
style::TerminalStyle,
terminal::{Terminal, TerminalEvent},
}; };
use { use crate::grid::GridView;
crate::{
grid::GridView
}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -25,7 +21,7 @@ pub trait TerminalView = GridView<Item = TerminalAtom>;
pub enum TerminalEditorResult { pub enum TerminalEditorResult {
Continue, Continue,
Exit Exit,
} }
pub trait TerminalEditor { pub trait TerminalEditor {
@ -37,25 +33,25 @@ pub trait TerminalEditor {
use { use {
crate::{ crate::{
core::{OuterViewPort, ViewPort},
vec::VecBuffer, vec::VecBuffer,
core::{ViewPort, OuterViewPort}
}, },
cgmath::Point2 cgmath::Point2,
}; };
pub fn make_label(s: &str) -> OuterViewPort<dyn TerminalView> { pub fn make_label(s: &str) -> OuterViewPort<dyn TerminalView> {
let label_port = ViewPort::new(); let label_port = ViewPort::new();
let mut label = VecBuffer::with_data(s.chars().collect(), label_port.inner()); let _label = VecBuffer::with_data(s.chars().collect(), label_port.inner());
let v = label_port.outer() let v = label_port
.outer()
.to_sequence() .to_sequence()
.map(|c| TerminalAtom::from(c)) .map(|c| TerminalAtom::from(c))
.to_index() .to_index()
.map_key( .map_key(
|idx| Point2::new(*idx as i16, 0), |idx| Point2::new(*idx as i16, 0),
|pt| if pt.y == 0 { Some(pt.x as usize) } else { None } |pt| if pt.y == 0 { Some(pt.x as usize) } else { None },
); );
v v
} }

View file

@ -1,4 +1,4 @@
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
#[derive(Default, Copy, Clone, PartialEq, Serialize, Deserialize, Debug)] #[derive(Default, Copy, Clone, PartialEq, Serialize, Deserialize, Debug)]
pub struct TerminalStyle { pub struct TerminalStyle {
@ -6,7 +6,7 @@ pub struct TerminalStyle {
pub bg_color: Option<(u8, u8, u8)>, pub bg_color: Option<(u8, u8, u8)>,
pub bold: Option<bool>, pub bold: Option<bool>,
pub italic: Option<bool>, pub italic: Option<bool>,
pub underline: Option<bool> pub underline: Option<bool>,
} }
impl TerminalStyle { impl TerminalStyle {
@ -85,4 +85,3 @@ impl std::fmt::Display for TerminalStyle {
Ok(()) Ok(())
} }
} }

View file

@ -1,44 +1,32 @@
use { use {
std::{ super::{TerminalStyle, TerminalView},
sync::Arc,
io::{Write, stdout, stdin},
collections::HashSet
},
std::sync::RwLock,
async_std::{
stream::StreamExt,
task
},
signal_hook,
signal_hook_async_std::Signals,
cgmath::{Vector2, Point2},
termion::{
raw::IntoRawMode,
input::{TermRead, MouseTerminal}
},
crate::{ crate::{
core::{ core::{
OuterViewPort, channel::{queue_channel, set_channel, ChannelReceiver, ChannelSender},
Observer, Observer, OuterViewPort,
channel::{
ChannelReceiver,
ChannelSender,
queue_channel,
set_channel
}
}, },
index::{IndexArea}, grid::GridWindowIterator,
grid::{GridWindowIterator} index::IndexArea,
}, },
super::{ async_std::{stream::StreamExt, task},
TerminalStyle, cgmath::{Point2, Vector2},
TerminalView signal_hook,
signal_hook_async_std::Signals,
std::sync::RwLock,
std::{
collections::HashSet,
io::{stdin, stdout, Write},
sync::Arc,
},
termion::{
input::{MouseTerminal, TermRead},
raw::IntoRawMode,
}, },
}; };
pub enum TerminalEvent { pub enum TerminalEvent {
Resize(Vector2<i16>), Resize(Vector2<i16>),
Input(termion::event::Event) Input(termion::event::Event),
} }
pub struct Terminal { pub struct Terminal {
@ -46,24 +34,22 @@ pub struct Terminal {
_observer: Arc<RwLock<TermOutObserver>>, _observer: Arc<RwLock<TermOutObserver>>,
events: ChannelReceiver<Vec<TerminalEvent>>, events: ChannelReceiver<Vec<TerminalEvent>>,
_signal_handle: signal_hook_async_std::Handle _signal_handle: signal_hook_async_std::Handle,
} }
impl Terminal { impl Terminal {
pub fn new( pub fn new(port: OuterViewPort<dyn TerminalView>) -> Self {
port: OuterViewPort<dyn TerminalView>
) -> Self {
let (dirty_pos_tx, dirty_pos_rx) = set_channel(); let (dirty_pos_tx, dirty_pos_rx) = set_channel();
let writer = Arc::new(TermOutWriter { let writer = Arc::new(TermOutWriter {
out: RwLock::new(MouseTerminal::from(stdout().into_raw_mode().unwrap())), out: RwLock::new(MouseTerminal::from(stdout().into_raw_mode().unwrap())),
dirty_pos_rx, dirty_pos_rx,
view: port.get_view_arc() view: port.get_view_arc(),
}); });
let observer = Arc::new(RwLock::new(TermOutObserver { let observer = Arc::new(RwLock::new(TermOutObserver {
dirty_pos_tx, dirty_pos_tx,
writer: writer.clone() writer: writer.clone(),
})); }));
port.add_observer(observer.clone()); port.add_observer(observer.clone());
@ -82,7 +68,7 @@ impl Terminal {
event_tx.send(TerminalEvent::Resize(Vector2::new(w as i16, h as i16))); event_tx.send(TerminalEvent::Resize(Vector2::new(w as i16, h as i16)));
// and again on SIGWINCH // and again on SIGWINCH
let signals = Signals::new(&[ signal_hook::consts::signal::SIGWINCH ]).unwrap(); let signals = Signals::new(&[signal_hook::consts::signal::SIGWINCH]).unwrap();
let handle = signals.handle(); let handle = signals.handle();
task::spawn(async move { task::spawn(async move {
@ -90,9 +76,9 @@ impl Terminal {
while let Some(signal) = signals.next().await { while let Some(signal) = signals.next().await {
match signal { match signal {
signal_hook::consts::signal::SIGWINCH => { signal_hook::consts::signal::SIGWINCH => {
let (w,h) = termion::terminal_size().unwrap(); let (w, h) = termion::terminal_size().unwrap();
event_tx.send(TerminalEvent::Resize(Vector2::new(w as i16, h as i16))); event_tx.send(TerminalEvent::Resize(Vector2::new(w as i16, h as i16)));
}, }
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -102,7 +88,7 @@ impl Terminal {
writer, writer,
_observer: observer, _observer: observer,
events: event_rx, events: event_rx,
_signal_handle: handle _signal_handle: handle,
} }
} }
@ -117,16 +103,18 @@ impl Terminal {
struct TermOutObserver { struct TermOutObserver {
dirty_pos_tx: ChannelSender<HashSet<Point2<i16>>>, dirty_pos_tx: ChannelSender<HashSet<Point2<i16>>>,
writer: Arc<TermOutWriter> writer: Arc<TermOutWriter>,
} }
impl TermOutObserver { impl TermOutObserver {
fn send_area(&mut self, area: IndexArea<Point2<i16>>) { fn send_area(&mut self, area: IndexArea<Point2<i16>>) {
match area { match area {
IndexArea::Empty => {}, IndexArea::Empty => {}
IndexArea::Full => { IndexArea::Full => {
let (w, h) = termion::terminal_size().unwrap(); let (w, h) = termion::terminal_size().unwrap();
for pos in GridWindowIterator::from(Point2::new(0, 0) .. Point2::new(w as i16, h as i16)) { for pos in
GridWindowIterator::from(Point2::new(0, 0)..Point2::new(w as i16, h as i16))
{
self.dirty_pos_tx.send(pos); self.dirty_pos_tx.send(pos);
} }
} }
@ -160,7 +148,7 @@ impl Observer<dyn TerminalView> for TermOutObserver {
pub struct TermOutWriter { pub struct TermOutWriter {
out: RwLock<MouseTerminal<termion::raw::RawTerminal<std::io::Stdout>>>, out: RwLock<MouseTerminal<termion::raw::RawTerminal<std::io::Stdout>>>,
dirty_pos_rx: ChannelReceiver<HashSet<Point2<i16>>>, dirty_pos_rx: ChannelReceiver<HashSet<Point2<i16>>>,
view: Arc<RwLock<Option<Arc<dyn TerminalView>>>> view: Arc<RwLock<Option<Arc<dyn TerminalView>>>>,
} }
impl TermOutWriter { impl TermOutWriter {
@ -173,22 +161,27 @@ impl TermOutWriter {
impl TermOutWriter { impl TermOutWriter {
pub async fn show(&self) -> std::io::Result<()> { pub async fn show(&self) -> std::io::Result<()> {
// init // init
write!(self.out.write().unwrap(), "{}{}{}", write!(
self.out.write().unwrap(),
"{}{}{}",
termion::cursor::Hide, termion::cursor::Hide,
termion::cursor::Goto(1, 1), termion::cursor::Goto(1, 1),
termion::style::Reset)?; termion::style::Reset
)?;
let mut cur_pos = Point2::<i16>::new(0, 0); let mut cur_pos = Point2::<i16>::new(0, 0);
let mut cur_style = TerminalStyle::default(); let mut cur_style = TerminalStyle::default();
// draw atoms until view port is destroyed // draw atoms until view port is destroyed
while let Some(dirty_pos) = self.dirty_pos_rx.recv().await { while let Some(dirty_pos) = self.dirty_pos_rx.recv().await {
let (w, h) = termion::terminal_size().unwrap(); let (w, _h) = termion::terminal_size().unwrap();
if let Some(view) = self.view.read().unwrap().as_ref() { if let Some(view) = self.view.read().unwrap().as_ref() {
let mut out = self.out.write().unwrap(); let mut out = self.out.write().unwrap();
let d = dirty_pos.into_iter().filter(|p| p.x >= 0 && p.y >= 0 && p.x < w as i16 && p.y < w as i16);//.collect::<Vec<_>>(); let d = dirty_pos
.into_iter()
.filter(|p| p.x >= 0 && p.y >= 0 && p.x < w as i16 && p.y < w as i16); //.collect::<Vec<_>>();
/* /*
d.sort_by(|a,b| { d.sort_by(|a,b| {
if a.y < b.y { if a.y < b.y {
@ -199,10 +192,14 @@ impl TermOutWriter {
std::cmp::Ordering::Greater std::cmp::Ordering::Greater
} }
}); });
*/ */
for pos in d { for pos in d {
if pos != cur_pos { if pos != cur_pos {
write!(out, "{}", termion::cursor::Goto(pos.x as u16 + 1, pos.y as u16 + 1))?; write!(
out,
"{}",
termion::cursor::Goto(pos.x as u16 + 1, pos.y as u16 + 1)
)?;
} }
if let Some(atom) = view.get(&pos) { if let Some(atom) = view.get(&pos) {
@ -232,4 +229,3 @@ impl TermOutWriter {
std::io::Result::Ok(()) std::io::Result::Ok(())
} }
} }

View file

@ -1,10 +1,9 @@
use crate::list::ListCursorMode; use crate::list::ListCursorMode;
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy, Eq, PartialEq)]
pub enum TreeNavResult { pub enum TreeNavResult {
Continue, Continue,
Exit Exit,
} }
/* /*
impl From<TreeNavResult> for TerminalEditorResult { impl From<TreeNavResult> for TerminalEditorResult {
@ -19,14 +18,14 @@ impl From<TreeNavResult> for TerminalEditorResult {
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq)]
pub struct TreeCursor { pub struct TreeCursor {
pub leaf_mode: ListCursorMode, pub leaf_mode: ListCursorMode,
pub tree_addr: Vec<usize> pub tree_addr: Vec<usize>,
} }
impl Default for TreeCursor { impl Default for TreeCursor {
fn default() -> Self { fn default() -> Self {
TreeCursor { TreeCursor {
leaf_mode: ListCursorMode::Select, leaf_mode: ListCursorMode::Select,
tree_addr: vec![] tree_addr: vec![],
} }
} }
} }
@ -56,7 +55,7 @@ pub trait TreeNav {
TreeNavResult::Exit TreeNavResult::Exit
} }
fn goto(&mut self, new_cursor: TreeCursor) -> TreeNavResult { fn goto(&mut self, _new_cursor: TreeCursor) -> TreeNavResult {
TreeNavResult::Exit TreeNavResult::Exit
} }
@ -65,7 +64,6 @@ pub trait TreeNav {
} }
} }
use crate::terminal::{TerminalView, TerminalEditor}; use crate::terminal::{TerminalEditor};
pub trait TerminalTreeEditor = TerminalEditor + TreeNav; pub trait TerminalTreeEditor = TerminalEditor + TreeNav;

View file

@ -1,19 +1,21 @@
use { use {
std::{ crate::{
sync::Arc, core::{InnerViewPort, Observer, ObserverBroadcast, View},
ops::{Deref, DerefMut}, vec::VecDiff,
}, },
std::sync::RwLock, std::sync::RwLock,
crate::{ std::{
core::{View, Observer, ObserverBroadcast, InnerViewPort}, ops::{Deref, DerefMut},
vec::VecDiff sync::Arc,
} },
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<T> View for Vec<T> impl<T> View for Vec<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
type Msg = VecDiff<T>; type Msg = VecDiff<T>;
} }
@ -21,19 +23,18 @@ where T: Clone + Send + Sync + 'static {
#[derive(Clone)] #[derive(Clone)]
pub struct VecBuffer<T> pub struct VecBuffer<T>
where T: Clone + Send + Sync + 'static where
T: Clone + Send + Sync + 'static,
{ {
data: Arc<RwLock<Vec<T>>>, data: Arc<RwLock<Vec<T>>>,
cast: Arc<RwLock<ObserverBroadcast<RwLock<Vec<T>>>>> cast: Arc<RwLock<ObserverBroadcast<RwLock<Vec<T>>>>>,
} }
impl<T> VecBuffer<T> impl<T> VecBuffer<T>
where T: Clone + Send + Sync + 'static where
T: Clone + Send + Sync + 'static,
{ {
pub fn with_data( pub fn with_data(data: Vec<T>, port: InnerViewPort<RwLock<Vec<T>>>) -> Self {
data: Vec<T>,
port: InnerViewPort<RwLock<Vec<T>>>
) -> Self {
let mut b = VecBuffer::new(port); let mut b = VecBuffer::new(port);
for x in data.into_iter() { for x in data.into_iter() {
b.push(x); b.push(x);
@ -45,17 +46,30 @@ where T: Clone + Send + Sync + 'static
pub fn new(port: InnerViewPort<RwLock<Vec<T>>>) -> Self { pub fn new(port: InnerViewPort<RwLock<Vec<T>>>) -> Self {
let data = Arc::new(RwLock::new(Vec::new())); let data = Arc::new(RwLock::new(Vec::new()));
port.set_view(Some(data.clone())); port.set_view(Some(data.clone()));
VecBuffer { data, cast: port.get_broadcast() } VecBuffer {
data,
cast: port.get_broadcast(),
}
} }
pub fn apply_diff(&mut self, diff: VecDiff<T>) { pub fn apply_diff(&mut self, diff: VecDiff<T>) {
let mut data = self.data.write().unwrap(); let mut data = self.data.write().unwrap();
match &diff { match &diff {
VecDiff::Clear => { data.clear(); }, VecDiff::Clear => {
VecDiff::Push(val) => { data.push(val.clone()); }, data.clear();
VecDiff::Remove(idx) => { data.remove(*idx); }, }
VecDiff::Insert{ idx, val } => { data.insert(*idx, val.clone()); }, VecDiff::Push(val) => {
VecDiff::Update{ idx, val } => { data[*idx] = val.clone(); } data.push(val.clone());
}
VecDiff::Remove(idx) => {
data.remove(*idx);
}
VecDiff::Insert { idx, val } => {
data.insert(*idx, val.clone());
}
VecDiff::Update { idx, val } => {
data[*idx] = val.clone();
}
} }
drop(data); drop(data);
@ -83,18 +97,18 @@ where T: Clone + Send + Sync + 'static
} }
pub fn insert(&mut self, idx: usize, val: T) { pub fn insert(&mut self, idx: usize, val: T) {
self.apply_diff(VecDiff::Insert{ idx, val }); self.apply_diff(VecDiff::Insert { idx, val });
} }
pub fn update(&mut self, idx: usize, val: T) { pub fn update(&mut self, idx: usize, val: T) {
self.apply_diff(VecDiff::Update{ idx, val }); self.apply_diff(VecDiff::Update { idx, val });
} }
pub fn get_mut(&mut self, idx: usize) -> MutableVecAccess<T> { pub fn get_mut(&mut self, idx: usize) -> MutableVecAccess<T> {
MutableVecAccess { MutableVecAccess {
buf: self.clone(), buf: self.clone(),
idx, idx,
val: self.get(idx) val: self.get(idx),
} }
} }
} }
@ -102,14 +116,18 @@ where T: Clone + Send + Sync + 'static
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct MutableVecAccess<T> pub struct MutableVecAccess<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
buf: VecBuffer<T>, buf: VecBuffer<T>,
idx: usize, idx: usize,
val: T, val: T,
} }
impl<T> Deref for MutableVecAccess<T> impl<T> Deref for MutableVecAccess<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
type Target = T; type Target = T;
fn deref(&self) -> &T { fn deref(&self) -> &T {
@ -118,17 +136,19 @@ where T: Clone + Send + Sync + 'static {
} }
impl<T> DerefMut for MutableVecAccess<T> impl<T> DerefMut for MutableVecAccess<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.val &mut self.val
} }
} }
impl<T> Drop for MutableVecAccess<T> impl<T> Drop for MutableVecAccess<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
fn drop(&mut self) { fn drop(&mut self) {
self.buf.update(self.idx, self.val.clone()); self.buf.update(self.idx, self.val.clone());
} }
} }

View file

@ -1,25 +1,19 @@
pub mod buffer; pub mod buffer;
pub mod vec2seq;
pub mod vec2json;
pub mod vec2bin; pub mod vec2bin;
pub mod vec2json;
pub mod vec2seq;
pub use { pub use buffer::VecBuffer;
buffer::VecBuffer
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
use { use serde::{Deserialize, Serialize};
serde::{Serialize, Deserialize}
};
#[derive(Clone, Serialize, Deserialize)] #[derive(Clone, Serialize, Deserialize)]
pub enum VecDiff<T> { pub enum VecDiff<T> {
Clear, Clear,
Push(T), Push(T),
Remove(usize), Remove(usize),
Insert{ idx: usize, val: T }, Insert { idx: usize, val: T },
Update{ idx: usize, val: T } Update { idx: usize, val: T },
} }

View file

@ -1,56 +1,70 @@
use { use {
std::{
sync::Arc,
io::Write
},
std::sync::RwLock,
serde::Serialize,
crate::{ crate::{
core::{Observer, OuterViewPort}, core::{Observer, OuterViewPort},
vec::VecDiff vec::VecDiff,
} },
serde::Serialize,
std::sync::RwLock,
std::{io::Write, sync::Arc},
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
/// Serialization Observer for `Vec` /// Serialization Observer for `Vec`
pub struct VecBinWriter<T, W> pub struct VecBinWriter<T, W>
where T: Clone + Send + Sync + 'static, where
W: Write + Send + Sync { T: Clone + Send + Sync + 'static,
W: Write + Send + Sync,
{
data: Option<Arc<RwLock<Vec<T>>>>, data: Option<Arc<RwLock<Vec<T>>>>,
out: RwLock<W> out: RwLock<W>,
} }
impl<T> OuterViewPort<RwLock<Vec<T>>> impl<T> OuterViewPort<RwLock<Vec<T>>>
where T: Clone + Serialize + Send + Sync + 'static { where
pub fn serialize_bin<W: Write + Send + Sync + 'static>(&self, out: W) -> Arc<RwLock<VecBinWriter<T, W>>> { T: Clone + Serialize + Send + Sync + 'static,
let writer = Arc::new(RwLock::new( {
VecBinWriter { pub fn serialize_bin<W: Write + Send + Sync + 'static>(
&self,
out: W,
) -> Arc<RwLock<VecBinWriter<T, W>>> {
let writer = Arc::new(RwLock::new(VecBinWriter {
data: None, data: None,
out: RwLock::new(out), out: RwLock::new(out),
} }));
));
self.add_observer(writer.clone()); self.add_observer(writer.clone());
writer writer
} }
} }
impl<T, W> Observer<RwLock<Vec<T>>> for VecBinWriter<T, W> impl<T, W> Observer<RwLock<Vec<T>>> for VecBinWriter<T, W>
where T: Clone + Serialize + Send + Sync + 'static, where
W: Write + Send + Sync T: Clone + Serialize + Send + Sync + 'static,
W: Write + Send + Sync,
{ {
fn reset(&mut self, view: Option<Arc<RwLock<Vec<T>>>>) { fn reset(&mut self, view: Option<Arc<RwLock<Vec<T>>>>) {
self.data = view; self.data = view;
let mut out = self.out.write().unwrap(); let mut out = self.out.write().unwrap();
out.write(&bincode::serialized_size(&VecDiff::<T>::Clear).unwrap().to_le_bytes()).expect(""); out.write(
out.write(&bincode::serialize(&VecDiff::<T>::Clear).unwrap()).expect(""); &bincode::serialized_size(&VecDiff::<T>::Clear)
.unwrap()
.to_le_bytes(),
)
.expect("");
out.write(&bincode::serialize(&VecDiff::<T>::Clear).unwrap())
.expect("");
if let Some(data) = self.data.as_ref() { if let Some(data) = self.data.as_ref() {
for x in data.read().unwrap().iter() { for x in data.read().unwrap().iter() {
out.write(&bincode::serialized_size(&VecDiff::Push(x)).unwrap().to_le_bytes()).expect(""); out.write(
out.write(&bincode::serialize(&VecDiff::Push(x)).unwrap()).expect(""); &bincode::serialized_size(&VecDiff::Push(x))
.unwrap()
.to_le_bytes(),
)
.expect("");
out.write(&bincode::serialize(&VecDiff::Push(x)).unwrap())
.expect("");
} }
} }
@ -59,9 +73,9 @@ where T: Clone + Serialize + Send + Sync + 'static,
fn notify(&mut self, diff: &VecDiff<T>) { fn notify(&mut self, diff: &VecDiff<T>) {
let mut out = self.out.write().unwrap(); let mut out = self.out.write().unwrap();
out.write(&bincode::serialized_size(diff).unwrap().to_le_bytes()).expect(""); out.write(&bincode::serialized_size(diff).unwrap().to_le_bytes())
.expect("");
out.write(&bincode::serialize(diff).unwrap()).expect(""); out.write(&bincode::serialize(diff).unwrap()).expect("");
out.flush().expect(""); out.flush().expect("");
} }
} }

View file

@ -1,56 +1,71 @@
use { use {
std::{
sync::Arc,
io::Write
},
std::sync::RwLock,
async_std::{
io::{Read, ReadExt},
stream::{StreamExt}
},
serde::{Serialize, de::DeserializeOwned},
crate::{ crate::{
core::{Observer, OuterViewPort}, core::{Observer, OuterViewPort},
vec::{VecDiff, VecBuffer} vec::{VecBuffer, VecDiff},
} },
async_std::{
io::{Read, ReadExt},
stream::StreamExt,
},
serde::{de::DeserializeOwned, Serialize},
std::sync::RwLock,
std::{io::Write, sync::Arc},
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct VecJsonWriter<T, W> pub struct VecJsonWriter<T, W>
where T: Clone + Send + Sync + 'static, where
W: Write + Send + Sync { T: Clone + Send + Sync + 'static,
W: Write + Send + Sync,
{
data: Option<Arc<RwLock<Vec<T>>>>, data: Option<Arc<RwLock<Vec<T>>>>,
out: RwLock<W> out: RwLock<W>,
} }
impl<T> OuterViewPort<RwLock<Vec<T>>> impl<T> OuterViewPort<RwLock<Vec<T>>>
where T: Clone + Serialize + Send + Sync + 'static { where
pub fn serialize_json<W: Write + Send + Sync + 'static>(&self, out: W) -> Arc<RwLock<VecJsonWriter<T, W>>> { T: Clone + Serialize + Send + Sync + 'static,
let writer = Arc::new(RwLock::new( {
VecJsonWriter { pub fn serialize_json<W: Write + Send + Sync + 'static>(
&self,
out: W,
) -> Arc<RwLock<VecJsonWriter<T, W>>> {
let writer = Arc::new(RwLock::new(VecJsonWriter {
data: None, data: None,
out: RwLock::new(out), out: RwLock::new(out),
} }));
));
self.add_observer(writer.clone()); self.add_observer(writer.clone());
writer writer
} }
} }
impl<T, W> Observer<RwLock<Vec<T>>> for VecJsonWriter<T, W> impl<T, W> Observer<RwLock<Vec<T>>> for VecJsonWriter<T, W>
where T: Clone + Serialize + Send + Sync + 'static, where
W: Write + Send + Sync T: Clone + Serialize + Send + Sync + 'static,
W: Write + Send + Sync,
{ {
fn reset(&mut self, view: Option<Arc<RwLock<Vec<T>>>>) { fn reset(&mut self, view: Option<Arc<RwLock<Vec<T>>>>) {
self.data = view; self.data = view;
self.out.write().unwrap().write(&serde_json::to_string(&VecDiff::<T>::Clear).unwrap().as_bytes()).expect(""); self.out
.write()
.unwrap()
.write(
&serde_json::to_string(&VecDiff::<T>::Clear)
.unwrap()
.as_bytes(),
)
.expect("");
self.out.write().unwrap().write(b"\n").expect(""); self.out.write().unwrap().write(b"\n").expect("");
if let Some(data) = self.data.as_ref() { if let Some(data) = self.data.as_ref() {
for x in data.read().unwrap().iter() { for x in data.read().unwrap().iter() {
self.out.write().unwrap().write(&serde_json::to_string(&VecDiff::Push(x)).unwrap().as_bytes()).expect(""); self.out
.write()
.unwrap()
.write(&serde_json::to_string(&VecDiff::Push(x)).unwrap().as_bytes())
.expect("");
self.out.write().unwrap().write(b"\n").expect(""); self.out.write().unwrap().write(b"\n").expect("");
} }
} }
@ -59,14 +74,19 @@ where T: Clone + Serialize + Send + Sync + 'static,
} }
fn notify(&mut self, diff: &VecDiff<T>) { fn notify(&mut self, diff: &VecDiff<T>) {
self.out.write().unwrap().write(serde_json::to_string(diff).unwrap().as_bytes()).expect(""); self.out
.write()
.unwrap()
.write(serde_json::to_string(diff).unwrap().as_bytes())
.expect("");
self.out.write().unwrap().write(b"\n").expect(""); self.out.write().unwrap().write(b"\n").expect("");
self.out.write().unwrap().flush().expect(""); self.out.write().unwrap().flush().expect("");
} }
} }
impl<T> VecBuffer<T> impl<T> VecBuffer<T>
where T: DeserializeOwned + Clone + Send + Sync + 'static where
T: DeserializeOwned + Clone + Send + Sync + 'static,
{ {
pub async fn from_json<R: Read + async_std::io::Read + Unpin>(&mut self, read: R) { pub async fn from_json<R: Read + async_std::io::Read + Unpin>(&mut self, read: R) {
let mut bytes = read.bytes(); let mut bytes = read.bytes();
@ -75,11 +95,12 @@ where T: DeserializeOwned + Clone + Send + Sync + 'static
match b { match b {
b'\n' => { b'\n' => {
if s.len() > 0 { if s.len() > 0 {
let diff = serde_json::from_str::<VecDiff<T>>(&s).expect("error parsing json"); let diff =
serde_json::from_str::<VecDiff<T>>(&s).expect("error parsing json");
self.apply_diff(diff); self.apply_diff(diff);
s.clear(); s.clear();
} }
}, }
c => { c => {
s.push(c as char); s.push(c as char);
} }
@ -87,5 +108,3 @@ where T: DeserializeOwned + Clone + Send + Sync + 'static
} }
} }
} }

View file

@ -1,78 +1,78 @@
use { use {
std::{
sync::Arc,
},
std::sync::RwLock,
crate::{ crate::{
core::{View, Observer, ObserverExt, ObserverBroadcast, ViewPort, InnerViewPort, OuterViewPort}, core::{
InnerViewPort, Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View, ViewPort,
},
sequence::SequenceView, sequence::SequenceView,
vec::VecDiff vec::VecDiff,
} },
std::sync::Arc,
std::sync::RwLock,
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
/// Adapter View implementing `Sequence` for `Vec` /// Adapter View implementing `Sequence` for `Vec`
pub struct VecSequence<T> pub struct VecSequence<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
cur_len: usize, cur_len: usize,
data: Option<Arc<RwLock<Vec<T>>>>, data: Option<Arc<RwLock<Vec<T>>>>,
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = T>>>> cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = T>>>>,
} }
impl<T> VecSequence<T> impl<T> VecSequence<T>
where T: Clone + Send + Sync + 'static { where
pub fn new( T: Clone + Send + Sync + 'static,
port: InnerViewPort<dyn SequenceView<Item = T>> {
) -> Arc<RwLock<Self>> { pub fn new(port: InnerViewPort<dyn SequenceView<Item = T>>) -> Arc<RwLock<Self>> {
let seq = Arc::new(RwLock::new( let seq = Arc::new(RwLock::new(VecSequence {
VecSequence {
cur_len: 0, cur_len: 0,
data: None, data: None,
cast: port.get_broadcast() cast: port.get_broadcast(),
} }));
));
port.set_view(Some(seq.clone())); port.set_view(Some(seq.clone()));
seq seq
} }
} }
impl<T> Observer<RwLock<Vec<T>>> for VecSequence<T> impl<T> Observer<RwLock<Vec<T>>> for VecSequence<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
fn reset(&mut self, view: Option<Arc<RwLock<Vec<T>>>>) { fn reset(&mut self, view: Option<Arc<RwLock<Vec<T>>>>) {
let old_len = self.cur_len; let old_len = self.cur_len;
self.data = view; self.data = view;
let new_len = let new_len = if let Some(data) = self.data.as_ref() {
if let Some(data) = self.data.as_ref() {
data.read().unwrap().len() data.read().unwrap().len()
} else { } else {
0 0
}; };
self.cur_len = new_len; self.cur_len = new_len;
self.cast.notify_each(0 .. std::cmp::max(old_len, new_len)); self.cast.notify_each(0..std::cmp::max(old_len, new_len));
} }
fn notify(&mut self, diff: &VecDiff<T>) { fn notify(&mut self, diff: &VecDiff<T>) {
match diff { match diff {
VecDiff::Clear => { VecDiff::Clear => {
self.cast.notify_each(0 .. self.cur_len); self.cast.notify_each(0..self.cur_len);
self.cur_len = 0 self.cur_len = 0
}, }
VecDiff::Push(_) => { VecDiff::Push(_) => {
self.cast.notify(&self.cur_len); self.cast.notify(&self.cur_len);
self.cur_len += 1; self.cur_len += 1;
}, }
VecDiff::Remove(idx) => { VecDiff::Remove(idx) => {
self.cast.notify_each(*idx .. self.cur_len); self.cast.notify_each(*idx..self.cur_len);
self.cur_len -= 1; self.cur_len -= 1;
}, }
VecDiff::Insert{ idx, val: _ } => { VecDiff::Insert { idx, val: _ } => {
self.cur_len += 1; self.cur_len += 1;
self.cast.notify_each(*idx .. self.cur_len); self.cast.notify_each(*idx..self.cur_len);
}, }
VecDiff::Update{ idx, val: _ } => { VecDiff::Update { idx, val: _ } => {
self.cast.notify(&idx); self.cast.notify(&idx);
} }
} }
@ -80,18 +80,20 @@ where T: Clone + Send + Sync + 'static {
} }
impl<T> View for VecSequence<T> impl<T> View for VecSequence<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
type Msg = usize; type Msg = usize;
} }
impl<T> SequenceView for VecSequence<T> impl<T> SequenceView for VecSequence<T>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
type Item = T; type Item = T;
fn get(&self, idx: &usize) -> Option<T> { fn get(&self, idx: &usize) -> Option<T> {
self.data.as_ref()? self.data.as_ref()?.read().unwrap().get(*idx).cloned()
.read().unwrap()
.get(*idx).cloned()
} }
fn len(&self) -> Option<usize> { fn len(&self) -> Option<usize> {
@ -102,7 +104,9 @@ where T: Clone + Send + Sync + 'static {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<T> OuterViewPort<RwLock<Vec<T>>> impl<T> OuterViewPort<RwLock<Vec<T>>>
where T: Clone + Send + Sync + 'static { where
T: Clone + Send + Sync + 'static,
{
pub fn to_sequence(&self) -> OuterViewPort<dyn SequenceView<Item = T>> { pub fn to_sequence(&self) -> OuterViewPort<dyn SequenceView<Item = T>> {
let port = ViewPort::new(); let port = ViewPort::new();
port.add_update_hook(Arc::new(self.0.clone())); port.add_update_hook(Arc::new(self.0.clone()));
@ -112,5 +116,3 @@ where T: Clone + Send + Sync + 'static {
port.into_outer() port.into_outer()
} }
} }

View file

@ -1,52 +1,38 @@
use {
use{
std::sync::{Arc, RwLock},
cgmath::{Point2, Vector2}, cgmath::{Point2, Vector2},
nested::{ nested::{
core::{ core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View},
View,
ViewPort,
InnerViewPort,
OuterViewPort,
Observer,
ObserverExt,
ObserverBroadcast,
context::{ReprTree, Object, MorphismType, MorphismMode, Context},
port::{UpdateTask}},
index::{IndexArea, IndexView}, index::{IndexArea, IndexView},
grid::{GridWindowIterator}, terminal::{TerminalAtom, TerminalView},
terminal::{ },
Terminal, std::sync::{Arc, RwLock},
TerminalStyle,
TerminalAtom,
TerminalCompositor,
TerminalEvent,
make_label,
TerminalView,
TerminalEditor},
}
}; };
pub struct AsciiBox { pub struct AsciiBox {
content: Option<Arc<dyn TerminalView>>, content: Option<Arc<dyn TerminalView>>,
extent: Vector2<i16>, extent: Vector2<i16>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>> cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
} }
impl AsciiBox { impl AsciiBox {
pub fn new( pub fn new(
extent: Vector2<i16>, extent: Vector2<i16>,
content_port: OuterViewPort<dyn TerminalView>, content_port: OuterViewPort<dyn TerminalView>,
output_port: InnerViewPort<dyn TerminalView> output_port: InnerViewPort<dyn TerminalView>,
) -> Arc<RwLock<Self>> { ) -> Arc<RwLock<Self>> {
let ascii_box = Arc::new(RwLock::new(AsciiBox { let ascii_box = Arc::new(RwLock::new(AsciiBox {
content: None, content: None,
extent, extent,
cast: output_port.get_broadcast() cast: output_port.get_broadcast(),
})); }));
output_port.0.update_hooks.write().unwrap().push(Arc::new(content_port.0.clone())); output_port
.0
.update_hooks
.write()
.unwrap()
.push(Arc::new(content_port.0.clone()));
output_port.set_view(Some(ascii_box.clone())); output_port.set_view(Some(ascii_box.clone()));
content_port.add_observer(ascii_box.clone()); content_port.add_observer(ascii_box.clone());
@ -57,19 +43,20 @@ impl AsciiBox {
if self.extent != new_extent { if self.extent != new_extent {
let old_extent = self.extent; let old_extent = self.extent;
self.extent = new_extent; self.extent = new_extent;
self.cast.notify( self.cast.notify(&IndexArea::Range(
&IndexArea::Range( Point2::new(0, 0)
Point2::new(0, 0) ..= ..=Point2::new(
Point2::new( 1 + std::cmp::max(old_extent.x, new_extent.x),
1+std::cmp::max(old_extent.x, new_extent.x), 1 + std::cmp::max(old_extent.y, new_extent.y),
1+std::cmp::max(old_extent.y, new_extent.y)))); ),
));
} }
} }
pub fn fit_content(&mut self) { pub fn fit_content(&mut self) {
if let Some(c) = self.content.as_ref() { if let Some(c) = self.content.as_ref() {
let p = *c.area().range().end(); let p = *c.area().range().end();
self.resize(Vector2::new(p.x+1, p.y+1)); self.resize(Vector2::new(p.x + 1, p.y + 1));
} else { } else {
self.resize(Vector2::new(0, 0)); self.resize(Vector2::new(0, 0));
} }
@ -96,42 +83,40 @@ impl IndexView<Point2<i16>> for AsciiBox {
type Item = TerminalAtom; type Item = TerminalAtom;
fn get(&self, pt: &Point2<i16>) -> Option<TerminalAtom> { fn get(&self, pt: &Point2<i16>) -> Option<TerminalAtom> {
if pt.x == 0 || pt.x == self.extent.x+1 { if pt.x == 0 || pt.x == self.extent.x + 1 {
// vertical line // vertical line
if pt.y == 0 && pt.x == 0 { if pt.y == 0 && pt.x == 0 {
Some(TerminalAtom::from('╭')) Some(TerminalAtom::from('╭'))
} else if pt.y == 0 && pt.x == self.extent.x+1 { } else if pt.y == 0 && pt.x == self.extent.x + 1 {
Some(TerminalAtom::from('╮')) Some(TerminalAtom::from('╮'))
} else if pt.y > 0 && pt.y < self.extent.y+1 { } else if pt.y > 0 && pt.y < self.extent.y + 1 {
Some(TerminalAtom::from('│')) Some(TerminalAtom::from('│'))
} else if pt.y == self.extent.y+1 && pt.x == 0 { } else if pt.y == self.extent.y + 1 && pt.x == 0 {
Some(TerminalAtom::from('╰')) Some(TerminalAtom::from('╰'))
} else if pt.y == self.extent.y+1 && pt.x == self.extent.x+1 { } else if pt.y == self.extent.y + 1 && pt.x == self.extent.x + 1 {
Some(TerminalAtom::from('╯')) Some(TerminalAtom::from('╯'))
} else { } else {
None None
} }
} else if pt.y == 0 || pt.y == self.extent.y+1 { } else if pt.y == 0 || pt.y == self.extent.y + 1 {
// horizontal line // horizontal line
if pt.x > 0 && pt.x < self.extent.x+1 { if pt.x > 0 && pt.x < self.extent.x + 1 {
Some(TerminalAtom::from('─')) Some(TerminalAtom::from('─'))
} else { } else {
None None
} }
} else if } else if pt.x > 0 && pt.y > 0 && pt.x < self.extent.x + 1 && pt.y < self.extent.y + 1 {
pt.x > 0 && Some(
pt.y > 0 && self.content
pt.x < self.extent.x+1 && .get(&(pt - Vector2::new(1, 1)))
pt.y < self.extent.y+1 .unwrap_or(TerminalAtom::from(' ')),
{ )
Some(self.content.get(&(pt - Vector2::new(1, 1))).unwrap_or(TerminalAtom::from(' ')))
} else { } else {
None None
} }
} }
fn area(&self) -> IndexArea<Point2<i16>> { fn area(&self) -> IndexArea<Point2<i16>> {
IndexArea::Range(Point2::new(0, 0) ..= Point2::new(1,1)+self.extent) IndexArea::Range(Point2::new(0, 0)..=Point2::new(1, 1) + self.extent)
} }
} }

View file

@ -1,52 +1,28 @@
extern crate portable_pty; extern crate portable_pty;
mod ascii_box;
mod monstera; mod monstera;
mod process; mod process;
mod pty; mod pty;
mod ascii_box;
mod plot; mod plot;
use{ use {
std::sync::{Arc, RwLock}, crate::process::ProcessLauncher,
cgmath::{Point2, Vector2}, cgmath::{Point2, Vector2},
termion::event::{Event, Key},
nested::{ nested::{
core::{ core::{port::UpdateTask, Observer, OuterViewPort, ViewPort},
View, index::IndexArea,
ViewPort, list::{ListCursorMode, ListEditor, ListEditorStyle},
InnerViewPort,
OuterViewPort,
Observer,
ObserverExt,
ObserverBroadcast,
context::{ReprTree, Object, MorphismType, MorphismMode, Context},
port::{UpdateTask}},
index::{IndexView, IndexArea},
grid::{GridWindowIterator},
sequence::{SequenceView, SequenceViewExt},
vec::{VecBuffer},
integer::{RadixProjection, DigitEditor, PosIntEditor},
terminal::{ terminal::{
Terminal, make_label, Terminal, TerminalAtom, TerminalCompositor, TerminalEditor,
TerminalStyle, TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView,
TerminalAtom,
TerminalCompositor,
TerminalEvent,
make_label,
TerminalView,
TerminalEditor,
TerminalEditorResult
}, },
string_editor::{StringEditor}, tree_nav::{TerminalTreeEditor, TreeCursor, TreeNavResult},
tree_nav::{TreeNav, TreeNavResult, TreeCursor, TerminalTreeEditor}, vec::VecBuffer,
list::{SExprView, ListCursorMode, ListEditor, ListEditorStyle},
projection::ProjectionHelper
}, },
crate::{ std::sync::{Arc, RwLock},
process::ProcessLauncher termion::event::{Event, Key},
}
}; };
#[async_std::main] #[async_std::main]
@ -57,53 +33,45 @@ async fn main() {
let mut term = Terminal::new(term_port.outer()); let mut term = Terminal::new(term_port.outer());
let term_writer = term.get_writer(); let term_writer = term.get_writer();
async_std::task::spawn( async_std::task::spawn(async move {
async move { let table_port =
let table_port = ViewPort::<dyn nested::grid::GridView<Item = OuterViewPort<dyn TerminalView>>>::new(); ViewPort::<dyn nested::grid::GridView<Item = OuterViewPort<dyn TerminalView>>>::new();
let mut table_buf = nested::index::buffer::IndexBuffer::new(table_port.inner()); let mut table_buf = nested::index::buffer::IndexBuffer::new(table_port.inner());
let magic = let magic =
make_label("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>") make_label("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>").map_item(|pos, atom| {
.map_item( atom.add_style_back(TerminalStyle::fg_color((
|pos, atom| 5,
atom.add_style_back( ((80 + (pos.x * 30) % 100) as u8),
TerminalStyle::fg_color( (55 + (pos.x * 15) % 180) as u8,
(5, )))
((80+(pos.x*30)%100) as u8), });
(55+(pos.x*15)%180) as u8)
)
)
);
let cur_size_port = ViewPort::new(); let cur_size_port = ViewPort::new();
let mut cur_size = nested::singleton::SingletonBuffer::new(Vector2::new(10, 10), cur_size_port.inner()); let mut cur_size =
nested::singleton::SingletonBuffer::new(Vector2::new(10, 10), cur_size_port.inner());
let status_chars_port = ViewPort::new(); let status_chars_port = ViewPort::new();
let mut status_chars = VecBuffer::new(status_chars_port.inner()); let mut status_chars = VecBuffer::new(status_chars_port.inner());
let mut process_list_editor = ListEditor::new( let mut process_list_editor = ListEditor::new(
Box::new(|| { Box::new(|| Arc::new(RwLock::new(ProcessLauncher::new()))),
Arc::new(RwLock::new( ListEditorStyle::VerticalSexpr,
ProcessLauncher::new()
))
}),
ListEditorStyle::VerticalSexpr
); );
let plist_vec_port = ViewPort::new(); let plist_vec_port = ViewPort::new();
let mut plist = VecBuffer::new(plist_vec_port.inner()); let mut plist = VecBuffer::new(plist_vec_port.inner());
async_std::task::spawn(async move { async_std::task::spawn(async move {
let (w, h) = termion::terminal_size().unwrap(); let (w, _h) = termion::terminal_size().unwrap();
let mut x : usize = 0; let mut x: usize = 0;
loop { loop {
let val = let val = (5.0
( + (x as f32 / 3.0).sin() * 5.0
5.0 + (x as f32 / 3.0).sin() * 5.0 + + 2.0
2.0 + ((7+x) as f32 / 5.0).sin() * 2.0 + + ((7 + x) as f32 / 5.0).sin() * 2.0
2.0 + ((9+x) as f32 / 10.0).cos() * 3.0 + 2.0
) as usize; + ((9 + x) as f32 / 10.0).cos() * 3.0) as usize;
if x < w as usize { if x < w as usize {
plist.push(val); plist.push(val);
@ -111,21 +79,24 @@ async fn main() {
*plist.get_mut(x % (w as usize)) = val; *plist.get_mut(x % (w as usize)) = val;
} }
x+=1; x += 1;
async_std::task::sleep(std::time::Duration::from_millis(10)).await; async_std::task::sleep(std::time::Duration::from_millis(10)).await;
if x%(w as usize) == 0 { if x % (w as usize) == 0 {
async_std::task::sleep(std::time::Duration::from_secs(3)).await; async_std::task::sleep(std::time::Duration::from_secs(3)).await;
} }
} }
}); });
let plot_port = ViewPort::new(); let plot_port = ViewPort::new();
let plot = crate::plot::Plot::new(plist_vec_port.outer().to_sequence(), plot_port.inner()); let _plot = crate::plot::Plot::new(plist_vec_port.outer().to_sequence(), plot_port.inner());
table_buf.insert_iter(vec![ table_buf.insert_iter(vec![
(Point2::new(0, 0), magic.clone()), (Point2::new(0, 0), magic.clone()),
(Point2::new(0, 1), status_chars_port.outer().to_sequence().to_grid_horizontal()), (
Point2::new(0, 1),
status_chars_port.outer().to_sequence().to_grid_horizontal(),
),
(Point2::new(0, 2), magic.clone()), (Point2::new(0, 2), magic.clone()),
(Point2::new(0, 3), process_list_editor.get_term_view()), (Point2::new(0, 3), process_list_editor.get_term_view()),
]); ]);
@ -133,65 +104,87 @@ async fn main() {
let (w, h) = termion::terminal_size().unwrap(); let (w, h) = termion::terminal_size().unwrap();
compositor.write().unwrap().push( compositor.write().unwrap().push(
plot_port.outer() plot_port
.map_item(|pt,a| { .outer()
a.add_style_back(TerminalStyle::fg_color((255 - pt.y as u8 * 8, 100, pt.y as u8 *15))) .map_item(|pt, a| {
a.add_style_back(TerminalStyle::fg_color((
255 - pt.y as u8 * 8,
100,
pt.y as u8 * 15,
)))
}) })
.offset(Vector2::new(0,h as i16-20)) .offset(Vector2::new(0, h as i16 - 20)),
); );
compositor.write().unwrap().push( compositor
monstera::make_monstera() .write()
.offset(Vector2::new(w as i16-38, 0))); .unwrap()
.push(monstera::make_monstera().offset(Vector2::new(w as i16 - 38, 0)));
compositor.write().unwrap().push( compositor
table_port.outer() .write()
.flatten() .unwrap()
.offset(Vector2::new(3, 0)) .push(table_port.outer().flatten().offset(Vector2::new(3, 0)));
);
process_list_editor.goto(TreeCursor { process_list_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Insert, leaf_mode: ListCursorMode::Insert,
tree_addr: vec![ 0 ] tree_addr: vec![0],
}); });
let tp = term_port.clone(); let tp = term_port.clone();
async_std::task::spawn( async_std::task::spawn(async move {
async move {
loop { loop {
tp.update(); tp.update();
async_std::task::sleep(std::time::Duration::from_millis(10)).await; async_std::task::sleep(std::time::Duration::from_millis(10)).await;
} }
} });
);
loop { loop {
status_chars.clear(); status_chars.clear();
let cur = process_list_editor.get_cursor(); let cur = process_list_editor.get_cursor();
if cur.tree_addr.len() > 0 { if cur.tree_addr.len() > 0 {
status_chars.push(TerminalAtom::new('@', TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true)))); status_chars.push(TerminalAtom::new(
'@',
TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true)),
));
for x in cur.tree_addr { for x in cur.tree_addr {
for c in format!("{}", x).chars() { for c in format!("{}", x).chars() {
status_chars.push(TerminalAtom::new(c, TerminalStyle::fg_color((0, 100, 20)))); status_chars
.push(TerminalAtom::new(c, TerminalStyle::fg_color((0, 100, 20))));
} }
status_chars.push(TerminalAtom::new('.', TerminalStyle::fg_color((120, 80, 80)))); status_chars.push(TerminalAtom::new(
'.',
TerminalStyle::fg_color((120, 80, 80)),
));
} }
status_chars.push(TerminalAtom::new(':', TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true)))); status_chars.push(TerminalAtom::new(
for c in ':',
match cur.leaf_mode { TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true)),
));
for c in match cur.leaf_mode {
ListCursorMode::Insert => "INSERT", ListCursorMode::Insert => "INSERT",
ListCursorMode::Select => "SELECT", ListCursorMode::Select => "SELECT",
ListCursorMode::Modify => "MODIFY" ListCursorMode::Modify => "MODIFY",
}.chars()
{
status_chars.push(TerminalAtom::new(c, TerminalStyle::fg_color((200, 200, 20))));
} }
status_chars.push(TerminalAtom::new(':', TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true)))); .chars()
{
status_chars.push(TerminalAtom::new(
c,
TerminalStyle::fg_color((200, 200, 20)),
));
}
status_chars.push(TerminalAtom::new(
':',
TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true)),
));
} else { } else {
for c in "Press <DN> to enter".chars() { for c in "Press <DN> to enter".chars() {
status_chars.push(TerminalAtom::new(c, TerminalStyle::fg_color((200, 200, 20)))); status_chars.push(TerminalAtom::new(
c,
TerminalStyle::fg_color((200, 200, 20)),
));
} }
} }
@ -220,10 +213,10 @@ async fn main() {
TerminalEvent::Input(Event::Key(Key::Ctrl('l'))) => { TerminalEvent::Input(Event::Key(Key::Ctrl('l'))) => {
process_list_editor.goto(TreeCursor { process_list_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Insert, leaf_mode: ListCursorMode::Insert,
tree_addr: vec![ 0 ] tree_addr: vec![0],
}); });
process_list_editor.data.clear(); process_list_editor.clear();
}, }
TerminalEvent::Input(Event::Key(Key::Left)) => { TerminalEvent::Input(Event::Key(Key::Left)) => {
process_list_editor.pxev(); process_list_editor.pxev();
} }
@ -250,18 +243,32 @@ async fn main() {
ev => { ev => {
if process_list_editor.get_cursor().leaf_mode == ListCursorMode::Select { if process_list_editor.get_cursor().leaf_mode == ListCursorMode::Select {
match ev { match ev {
TerminalEvent::Input(Event::Key(Key::Char('l'))) => { process_list_editor.up(); }, TerminalEvent::Input(Event::Key(Key::Char('l'))) => {
TerminalEvent::Input(Event::Key(Key::Char('a'))) => { process_list_editor.dn(); }, process_list_editor.up();
TerminalEvent::Input(Event::Key(Key::Char('i'))) => { process_list_editor.pxev(); }, }
TerminalEvent::Input(Event::Key(Key::Char('e'))) => { process_list_editor.nexd(); }, TerminalEvent::Input(Event::Key(Key::Char('a'))) => {
TerminalEvent::Input(Event::Key(Key::Char('u'))) => { process_list_editor.goto_home(); }, process_list_editor.dn();
TerminalEvent::Input(Event::Key(Key::Char('o'))) => { process_list_editor.goto_end(); }, }
TerminalEvent::Input(Event::Key(Key::Char('i'))) => {
process_list_editor.pxev();
}
TerminalEvent::Input(Event::Key(Key::Char('e'))) => {
process_list_editor.nexd();
}
TerminalEvent::Input(Event::Key(Key::Char('u'))) => {
process_list_editor.goto_home();
}
TerminalEvent::Input(Event::Key(Key::Char('o'))) => {
process_list_editor.goto_end();
}
_ => { _ => {
process_list_editor.handle_terminal_event(&ev); process_list_editor.handle_terminal_event(&ev);
} }
} }
} else { } else {
if let TerminalEditorResult::Exit = process_list_editor.handle_terminal_event(&ev) { if let TerminalEditorResult::Exit =
process_list_editor.handle_terminal_event(&ev)
{
process_list_editor.nexd(); process_list_editor.nexd();
} }
} }
@ -271,9 +278,7 @@ async fn main() {
drop(term); drop(term);
drop(term_port); drop(term_port);
} });
);
term_writer.show().await.expect("output error!"); term_writer.show().await.expect("output error!");
} }

View file

@ -1,18 +1,15 @@
use { use {
cgmath::Point2, cgmath::Point2,
nested::{ nested::{
core::{ViewPort, OuterViewPort}, core::{OuterViewPort, ViewPort},
terminal::{make_label, TerminalStyle, TerminalView},
vec::VecBuffer, vec::VecBuffer,
terminal::{
TerminalStyle, TerminalView, make_label
}, },
}
}; };
pub fn make_monstera() -> OuterViewPort<dyn TerminalView> { pub fn make_monstera() -> OuterViewPort<dyn TerminalView> {
let monstera_lines_port = ViewPort::new(); let monstera_lines_port = ViewPort::new();
let monstera_lines = VecBuffer::with_data( let _monstera_lines = VecBuffer::with_data(
vec![ vec![
make_label(" |"), make_label(" |"),
make_label(" |"), make_label(" |"),
@ -36,21 +33,19 @@ pub fn make_monstera() -> OuterViewPort<dyn TerminalView> {
make_label(" *. ( | ) .*"), make_label(" *. ( | ) .*"),
make_label(" \\_ . | . _/"), make_label(" \\_ . | . _/"),
make_label(" \\ | /"), make_label(" \\ | /"),
make_label(" .") make_label(" ."),
], ],
monstera_lines_port.inner() monstera_lines_port.inner(),
); );
monstera_lines_port.outer() monstera_lines_port
.outer()
.to_sequence() .to_sequence()
.to_index() .to_index()
.map_key( .map_key(
|idx| Point2::new(0 as i16, *idx as i16), |idx| Point2::new(0 as i16, *idx as i16),
|pt| if pt.x == 0 { Some(pt.y as usize) } else { None } |pt| if pt.x == 0 { Some(pt.y as usize) } else { None },
) )
.flatten() .flatten()
.map_item( .map_item(|_p, at| at.add_style_back(TerminalStyle::fg_color((0, 100, 10))))
|p, at| at.add_style_back(TerminalStyle::fg_color((0,100,10)))
)
} }

View file

@ -1,49 +1,20 @@
use{ use {
std::sync::{Arc, RwLock}, cgmath::Point2,
cgmath::{Point2, Vector2},
termion::event::{Event, Key},
nested::{ nested::{
core::{ core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View},
View, sequence::{SequenceView},
ViewPort, index::{IndexArea, IndexView},
InnerViewPort, projection::ProjectionHelper,
OuterViewPort, terminal::{TerminalAtom, TerminalView},
Observer,
ObserverExt,
ObserverBroadcast,
context::{ReprTree, Object, MorphismType, MorphismMode, Context},
port::{UpdateTask}},
index::{IndexView, IndexArea},
grid::{GridWindowIterator},
sequence::{SequenceView, SequenceViewExt},
vec::{VecBuffer},
integer::{RadixProjection, DigitEditor, PosIntEditor},
terminal::{
Terminal,
TerminalStyle,
TerminalAtom,
TerminalCompositor,
TerminalEvent,
make_label,
TerminalView,
TerminalEditor,
TerminalEditorResult
}, },
string_editor::{StringEditor}, std::sync::{Arc, RwLock},
tree_nav::{TreeNav, TreeNavResult, TreeCursor, TerminalTreeEditor},
list::{SExprView, ListCursorMode, ListEditor, ListEditorStyle},
projection::ProjectionHelper
},
crate::{
process::ProcessLauncher
}
}; };
pub struct Plot { pub struct Plot {
limit: usize, limit: usize,
data: Arc<dyn SequenceView<Item = usize>>, data: Arc<dyn SequenceView<Item = usize>>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>, cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
proj_helper: ProjectionHelper<(), Self> proj_helper: ProjectionHelper<(), Self>,
} }
impl View for Plot { impl View for Plot {
@ -58,25 +29,21 @@ impl IndexView<Point2<i16>> for Plot {
if let Some(cur_val) = self.data.get(&(pt.x as usize)) { if let Some(cur_val) = self.data.get(&(pt.x as usize)) {
if cur_val <= self.limit { if cur_val <= self.limit {
if pt.y == (self.limit - cur_val) as i16 { if pt.y == (self.limit - cur_val) as i16 {
return Some(TerminalAtom::from( return Some(TerminalAtom::from(if cur_val < 4 {
if cur_val < 4 { 'o' } 'o'
else if cur_val < 8 { 'O' } } else if cur_val < 8 {
else { '*' } 'O'
)); } else {
'*'
}));
} }
} }
if pt.x > 0 { if pt.x > 0 {
if let Some(prev_val) = self.data.get(&((pt.x-1) as usize)) { if let Some(prev_val) = self.data.get(&((pt.x - 1) as usize)) {
if if (pt.y > (self.limit - prev_val) as i16
( && pt.y < (self.limit - cur_val) as i16)
pt.y > (self.limit - prev_val) as i16 && || (pt.y < (self.limit - prev_val) as i16
pt.y < (self.limit - cur_val) as i16 && pt.y > (self.limit - cur_val) as i16)
)
||
(
pt.y < (self.limit - prev_val) as i16 &&
pt.y > (self.limit - cur_val) as i16
)
{ {
return Some(TerminalAtom::from('.')); return Some(TerminalAtom::from('.'));
} }
@ -89,11 +56,7 @@ impl IndexView<Point2<i16>> for Plot {
fn area(&self) -> IndexArea<Point2<i16>> { fn area(&self) -> IndexArea<Point2<i16>> {
IndexArea::Range( IndexArea::Range(
Point2::new(0,0) Point2::new(0, 0)..=Point2::new(self.data.len().unwrap_or(0) as i16, self.limit as i16),
..= Point2::new(
self.data.len().unwrap_or(0) as i16,
self.limit as i16
)
) )
} }
} }
@ -101,15 +64,11 @@ impl IndexView<Point2<i16>> for Plot {
impl Plot { impl Plot {
pub fn new( pub fn new(
data_port: OuterViewPort<dyn SequenceView<Item = usize>>, data_port: OuterViewPort<dyn SequenceView<Item = usize>>,
out_port: InnerViewPort<dyn TerminalView> out_port: InnerViewPort<dyn TerminalView>,
) -> Arc<RwLock<Self>> { ) -> Arc<RwLock<Self>> {
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone()); let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
let proj = Arc::new(RwLock::new( let proj = Arc::new(RwLock::new(Plot {
Plot { data: proj_helper.new_sequence_arg((), data_port, |s: &mut Self, idx| {
data: proj_helper.new_sequence_arg(
(),
data_port,
|s: &mut Self, idx| {
let val = s.data.get(idx).unwrap_or(0); let val = s.data.get(idx).unwrap_or(0);
if val > s.limit { if val > s.limit {
@ -117,18 +76,15 @@ impl Plot {
s.cast.notify(&s.area()); s.cast.notify(&s.area());
} else { } else {
s.cast.notify(&IndexArea::Range( s.cast.notify(&IndexArea::Range(
Point2::new(*idx as i16, 0) Point2::new(*idx as i16, 0)..=Point2::new(*idx as i16, s.limit as i16),
..= Point2::new(*idx as i16, s.limit as i16)
)); ));
} }
} }),
),
limit: 0, limit: 0,
cast: out_port.get_broadcast(), cast: out_port.get_broadcast(),
proj_helper proj_helper,
} }));
));
proj.write().unwrap().proj_helper.set_proj(&proj); proj.write().unwrap().proj_helper.set_proj(&proj);
out_port.set_view(Some(proj.clone())); out_port.set_view(Some(proj.clone()));
@ -136,4 +92,3 @@ impl Plot {
proj proj
} }
} }

View file

@ -1,39 +1,41 @@
use { use {
std::{ crate::pty::{PTYStatus, PTY},
sync::Arc,
process::Command,
os::unix::io::{FromRawFd, AsRawFd},
},
std::sync::RwLock,
termion::event::{Key, Event},
cgmath::Point2,
nested::{ nested::{
core::{ViewPort, OuterViewPort, InnerViewPort, Observer}, core::{OuterViewPort, ViewPort},
singleton::{SingletonView, SingletonBuffer}, list::{sexpr::ListDecoration, ListCursorMode, ListEditor, ListEditorStyle},
sequence::{SequenceView, SequenceViewExt}, sequence::{SequenceView, SequenceViewExt},
index::buffer::IndexBuffer, singleton::SingletonView,
vec::VecBuffer,
terminal::{TerminalAtom, TerminalStyle, TerminalView, TerminalEvent, TerminalEditor, TerminalEditorResult, make_label},
tree_nav::{TreeNav, TreeNavResult, TerminalTreeEditor, TreeCursor},
list::{ListCursorMode, ListEditor, ListEditorStyle, sexpr::ListDecoration},
string_editor::CharEditor, string_editor::CharEditor,
terminal::{
TerminalAtom, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle,
TerminalView,
}, },
crate::pty::{PTY, PTYStatus} tree_nav::{TerminalTreeEditor, TreeCursor, TreeNav, TreeNavResult},
},
std::sync::Arc,
std::sync::RwLock,
termion::event::{Event, Key},
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct ProcessArg { pub struct ProcessArg {
editor: ListEditor< CharEditor, editor:
Box<dyn Fn() -> Arc<RwLock<CharEditor>> + Send + Sync + 'static> > ListEditor<CharEditor, Box<dyn Fn() -> Arc<RwLock<CharEditor>> + Send + Sync + 'static>>,
} }
impl ProcessArg { impl ProcessArg {
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = char>> { pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = char>> {
self.editor.get_data_port() self.editor.get_data_port().map(|char_editor| {
.map( char_editor
|char_editor| char_editor.read().unwrap().get_data_port().get_view().unwrap().get().unwrap() .read()
) .unwrap()
.get_data_port()
.get_view()
.unwrap()
.get()
.unwrap()
})
} }
} }
@ -47,41 +49,56 @@ impl TerminalEditor for ProcessArg {
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
match event { match event {
TerminalEvent::Input(Event::Key(Key::Char(' '))) | TerminalEvent::Input(Event::Key(Key::Char(' ')))
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => { | TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
self.editor.up(); self.editor.up();
TerminalEditorResult::Exit TerminalEditorResult::Exit
} }
event => self.editor.handle_terminal_event(event) event => self.editor.handle_terminal_event(event),
} }
} }
} }
impl TreeNav for ProcessArg { impl TreeNav for ProcessArg {
fn get_cursor(&self) -> TreeCursor { self.editor.get_cursor() } fn get_cursor(&self) -> TreeCursor {
fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { self.editor.goto(cur) } self.editor.get_cursor()
fn goto_home(&mut self) -> TreeNavResult { self.editor.goto_home() } }
fn goto_end(&mut self) -> TreeNavResult { self.editor.goto_end() } fn goto(&mut self, cur: TreeCursor) -> TreeNavResult {
fn pxev(&mut self) -> TreeNavResult { self.editor.pxev() } self.editor.goto(cur)
fn nexd(&mut self) -> TreeNavResult { self.editor.nexd() } }
fn up(&mut self) -> TreeNavResult { self.editor.up() } fn goto_home(&mut self) -> TreeNavResult {
fn dn(&mut self) -> TreeNavResult { self.editor.dn() } self.editor.goto_home()
}
fn goto_end(&mut self) -> TreeNavResult {
self.editor.goto_end()
}
fn pxev(&mut self) -> TreeNavResult {
self.editor.pxev()
}
fn nexd(&mut self) -> TreeNavResult {
self.editor.nexd()
}
fn up(&mut self) -> TreeNavResult {
self.editor.up()
}
fn dn(&mut self) -> TreeNavResult {
self.editor.dn()
}
} }
pub struct ProcessLauncher { pub struct ProcessLauncher {
cmd_editor: ListEditor< cmd_editor:
ProcessArg, Box<dyn Fn() -> Arc<RwLock<ProcessArg>> + Send + Sync + 'static> ListEditor<ProcessArg, Box<dyn Fn() -> Arc<RwLock<ProcessArg>> + Send + Sync + 'static>>,
>,
pty: Option<crate::pty::PTY>, pty: Option<crate::pty::PTY>,
ptybox: Arc<RwLock<crate::ascii_box::AsciiBox>>, _ptybox: Arc<RwLock<crate::ascii_box::AsciiBox>>,
suspended: bool, suspended: bool,
pty_port: ViewPort<dyn TerminalView>, pty_port: ViewPort<dyn TerminalView>,
status_port: ViewPort<dyn SingletonView<Item = PTYStatus>>, status_port: ViewPort<dyn SingletonView<Item = PTYStatus>>,
comp_port: ViewPort<dyn TerminalView>, comp_port: ViewPort<dyn TerminalView>,
compositor: Arc<RwLock<nested::terminal::TerminalCompositor>> _compositor: Arc<RwLock<nested::terminal::TerminalCompositor>>,
} }
impl ProcessLauncher { impl ProcessLauncher {
@ -93,50 +110,45 @@ impl ProcessLauncher {
let compositor = nested::terminal::TerminalCompositor::new(comp_port.inner()); let compositor = nested::terminal::TerminalCompositor::new(comp_port.inner());
let cmd_editor = ListEditor::new( let cmd_editor = ListEditor::new(
Box::new( Box::new(|| {
|| {
Arc::new(RwLock::new(ProcessArg { Arc::new(RwLock::new(ProcessArg {
editor: ListEditor::new( editor: ListEditor::new(
Box::new( Box::new(|| Arc::new(RwLock::new(CharEditor::new()))),
|| { ListEditorStyle::Plain,
Arc::new(RwLock::new(CharEditor::new()))
}
), ),
ListEditorStyle::Plain)
})) }))
} }) as Box<dyn Fn() -> Arc<RwLock<ProcessArg>> + Send + Sync>,
) as Box::<dyn Fn() -> Arc<RwLock<ProcessArg>> + Send + Sync>, ListEditorStyle::Plain,
ListEditorStyle::Plain
); );
compositor.write().unwrap().push( compositor.write().unwrap().push(
box_port.outer() box_port
.map_item(|_idx, x| x.add_style_back(TerminalStyle::fg_color((90, 120, 100)))) .outer()
.map_item(|_idx, x| x.add_style_back(TerminalStyle::fg_color((90, 120, 100)))),
); );
compositor.write().unwrap().push( compositor.write().unwrap().push(
cmd_editor cmd_editor
.get_seg_seq_view() .get_seg_seq_view()
.decorate("$(", ")", " ", 0) .decorate("$(", ")", " ", 0)
.to_grid_horizontal() .to_grid_horizontal()
.flatten() .flatten(),
); );
ProcessLauncher { ProcessLauncher {
cmd_editor, cmd_editor,
pty: None, pty: None,
ptybox: crate::ascii_box::AsciiBox::new( _ptybox: crate::ascii_box::AsciiBox::new(
cgmath::Vector2::new(0, 0), cgmath::Vector2::new(0, 0),
pty_port.outer() pty_port.outer().map_item(|_, a: &TerminalAtom| {
.map_item(|_,a:&TerminalAtom| a.add_style_back(TerminalStyle::fg_color((230, 230, 230)))), a.add_style_back(TerminalStyle::fg_color((230, 230, 230)))
box_port.inner() }),
box_port.inner(),
), ),
suspended: false, suspended: false,
pty_port, pty_port,
status_port, status_port,
comp_port, comp_port,
compositor _compositor: compositor,
} }
} }
@ -144,8 +156,15 @@ impl ProcessLauncher {
let mut strings = Vec::new(); let mut strings = Vec::new();
let v = self.cmd_editor.get_data_port().get_view().unwrap(); let v = self.cmd_editor.get_data_port().get_view().unwrap();
for i in 0 .. v.len().unwrap_or(0) { for i in 0..v.len().unwrap_or(0) {
let arg_view = v.get(&i).unwrap().read().unwrap().get_data_port().get_view().unwrap(); let arg_view = v
.get(&i)
.unwrap()
.read()
.unwrap()
.get_data_port()
.get_view()
.unwrap();
strings.push(arg_view.iter().collect::<String>()); strings.push(arg_view.iter().collect::<String>());
} }
@ -157,10 +176,15 @@ impl ProcessLauncher {
self.cmd_editor.goto(TreeCursor { self.cmd_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Insert, leaf_mode: ListCursorMode::Insert,
tree_addr: vec![] tree_addr: vec![],
}); });
self.pty = PTY::new(cmd, cgmath::Vector2::new(120, 40), self.pty_port.inner(), self.status_port.inner()); self.pty = PTY::new(
cmd,
cgmath::Vector2::new(120, 40),
self.pty_port.inner(),
self.status_port.inner(),
);
} }
} }
@ -175,9 +199,8 @@ impl TerminalEditor for ProcessLauncher {
} }
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
// todo: move to observer of status view // todo: move to observer of status view
if let PTYStatus::Done{ status } = self.status_port.outer().get_view().get() { if let PTYStatus::Done { status: _ } = self.status_port.outer().get_view().get() {
self.pty = None; self.pty = None;
self.suspended = false; self.suspended = false;
} }
@ -185,7 +208,7 @@ impl TerminalEditor for ProcessLauncher {
match event { match event {
TerminalEvent::Input(Event::Key(Key::Ctrl('c'))) => { TerminalEvent::Input(Event::Key(Key::Ctrl('c'))) => {
// todo: sigterm instead of kill? // todo: sigterm instead of kill?
if let Some(mut pty) = self.pty.as_mut() { if let Some(pty) = self.pty.as_mut() {
pty.kill(); pty.kill();
} }
@ -193,15 +216,15 @@ impl TerminalEditor for ProcessLauncher {
self.suspended = false; self.suspended = false;
self.cmd_editor.goto(TreeCursor { self.cmd_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Insert, leaf_mode: ListCursorMode::Insert,
tree_addr: vec![] tree_addr: vec![],
}); });
TerminalEditorResult::Exit TerminalEditorResult::Exit
}, }
TerminalEvent::Input(Event::Key(Key::Ctrl('z'))) => { TerminalEvent::Input(Event::Key(Key::Ctrl('z'))) => {
self.suspended = true; self.suspended = true;
self.cmd_editor.goto(TreeCursor { self.cmd_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Insert, leaf_mode: ListCursorMode::Insert,
tree_addr: vec![] tree_addr: vec![],
}); });
TerminalEditorResult::Exit TerminalEditorResult::Exit
} }
@ -216,7 +239,7 @@ impl TerminalEditor for ProcessLauncher {
self.launch_pty(); self.launch_pty();
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
event => self.cmd_editor.handle_terminal_event(event) event => self.cmd_editor.handle_terminal_event(event),
} }
} }
} }
@ -231,7 +254,7 @@ impl TreeNav for ProcessLauncher {
fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { fn goto(&mut self, cur: TreeCursor) -> TreeNavResult {
self.suspended = false; self.suspended = false;
if let PTYStatus::Done{status} = self.status_port.outer().get_view().get() { if let PTYStatus::Done { status: _ } = self.status_port.outer().get_view().get() {
self.pty = None; self.pty = None;
} }
@ -240,7 +263,7 @@ impl TreeNav for ProcessLauncher {
} else { } else {
self.cmd_editor.goto(TreeCursor { self.cmd_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Select, leaf_mode: ListCursorMode::Select,
tree_addr: vec![] tree_addr: vec![],
}); });
TreeNavResult::Continue TreeNavResult::Continue
} }
@ -270,4 +293,3 @@ impl TreeNav for ProcessLauncher {
self.cmd_editor.dn() self.cmd_editor.dn()
} }
} }

View file

@ -1,13 +1,12 @@
use { use {
std::sync::{Arc, Mutex},
termion::event::{Key, Event},
cgmath::Vector2, cgmath::Vector2,
nested::{ nested::{
core::{InnerViewPort}, core::InnerViewPort,
singleton::{SingletonView, SingletonBuffer}, singleton::{SingletonBuffer, SingletonView},
terminal::{TerminalView, TerminalEvent, TerminalEditorResult} terminal::{TerminalEditorResult, TerminalEvent, TerminalView},
} },
std::sync::{Arc, Mutex},
termion::event::{Event, Key},
}; };
pub use portable_pty::CommandBuilder; pub use portable_pty::CommandBuilder;
@ -16,15 +15,13 @@ pub use portable_pty::CommandBuilder;
#[derive(Clone)] #[derive(Clone)]
pub enum PTYStatus { pub enum PTYStatus {
Running{ pid: u32 }, Running { pid: u32 },
Done{ status: portable_pty::ExitStatus } Done { status: portable_pty::ExitStatus },
} }
impl Default for PTYStatus { impl Default for PTYStatus {
fn default() -> Self { fn default() -> Self {
PTYStatus::Running { PTYStatus::Running { pid: 0 }
pid: 0
}
} }
} }
@ -32,7 +29,7 @@ impl Default for PTYStatus {
pub struct PTY { pub struct PTY {
master: Mutex<Box<dyn portable_pty::MasterPty + Send>>, master: Mutex<Box<dyn portable_pty::MasterPty + Send>>,
child: Arc<Mutex<Box<dyn portable_pty::Child + Send + Sync>>> child: Arc<Mutex<Box<dyn portable_pty::Child + Send + Sync>>>,
} }
impl PTY { impl PTY {
@ -40,11 +37,11 @@ impl PTY {
cmd: portable_pty::CommandBuilder, cmd: portable_pty::CommandBuilder,
max_size: Vector2<i16>, max_size: Vector2<i16>,
term_port: InnerViewPort<dyn TerminalView>, term_port: InnerViewPort<dyn TerminalView>,
status_port: InnerViewPort<dyn SingletonView<Item = PTYStatus>> status_port: InnerViewPort<dyn SingletonView<Item = PTYStatus>>,
) -> Option<Self> { ) -> Option<Self> {
// Create a new pty // Create a new pty
let mut pair = portable_pty::native_pty_system().openpty(portable_pty::PtySize { let pair = portable_pty::native_pty_system()
.openpty(portable_pty::PtySize {
rows: max_size.y as u16, rows: max_size.y as u16,
cols: max_size.x as u16, cols: max_size.x as u16,
@ -55,36 +52,39 @@ impl PTY {
// brief example though! // brief example though!
pixel_width: 0, pixel_width: 0,
pixel_height: 0, pixel_height: 0,
}).unwrap(); })
.unwrap();
if let Ok(mut child) = pair.slave.spawn_command(cmd) { if let Ok(child) = pair.slave.spawn_command(cmd) {
let mut reader = pair.master.try_clone_reader().unwrap(); let mut reader = pair.master.try_clone_reader().unwrap();
let mut status_buf = SingletonBuffer::new(PTYStatus::Running{ pid: child.process_id().expect("") }, status_port); let mut status_buf = SingletonBuffer::new(
PTYStatus::Running {
pid: child.process_id().expect(""),
},
status_port,
);
let child = Arc::new(Mutex::new(child)); let child = Arc::new(Mutex::new(child));
async_std::task::spawn_blocking( async_std::task::spawn_blocking(move || {
move || {
nested::terminal::ansi_parser::read_ansi_from(&mut reader, max_size, term_port); nested::terminal::ansi_parser::read_ansi_from(&mut reader, max_size, term_port);
}); });
async_std::task::spawn_blocking({ async_std::task::spawn_blocking({
let child = child.clone(); let child = child.clone();
move || { move || loop {
loop {
if let Ok(Some(status)) = child.lock().unwrap().try_wait() { if let Ok(Some(status)) = child.lock().unwrap().try_wait() {
status_buf.set(PTYStatus::Done{ status }); status_buf.set(PTYStatus::Done { status });
break; break;
} }
std::thread::sleep(std::time::Duration::from_millis(10)); std::thread::sleep(std::time::Duration::from_millis(10));
} }
}
}); });
Some(PTY { Some(PTY {
master: Mutex::new(pair.master), master: Mutex::new(pair.master),
child child,
}) })
} else { } else {
None None
@ -92,7 +92,7 @@ impl PTY {
} }
pub fn kill(&mut self) { pub fn kill(&mut self) {
self.child.lock().unwrap().kill(); self.child.lock().unwrap().kill().unwrap();
} }
pub fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { pub fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
@ -100,11 +100,11 @@ impl PTY {
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => { TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
self.master.lock().unwrap().write(&[13]).unwrap(); self.master.lock().unwrap().write(&[13]).unwrap();
TerminalEditorResult::Continue TerminalEditorResult::Continue
}, }
TerminalEvent::Input(Event::Key(Key::Char(c))) => { TerminalEvent::Input(Event::Key(Key::Char(c))) => {
write!(self.master.lock().unwrap(), "{}", c); write!(self.master.lock().unwrap(), "{}", c).unwrap();
TerminalEditorResult::Continue TerminalEditorResult::Continue
}, }
TerminalEvent::Input(Event::Key(Key::Esc)) => { TerminalEvent::Input(Event::Key(Key::Esc)) => {
self.master.lock().unwrap().write(&[0x1b]).unwrap(); self.master.lock().unwrap().write(&[0x1b]).unwrap();
TerminalEditorResult::Continue TerminalEditorResult::Continue
@ -114,37 +114,54 @@ impl PTY {
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
TerminalEvent::Input(Event::Key(Key::F(n))) => { TerminalEvent::Input(Event::Key(Key::F(n))) => {
self.master.lock().unwrap().write(&[ self.master
.lock()
.unwrap()
.write(&[
0x1b, 0x1b,
0x0a, 0x0a,
match n { match n {
11 => 133, 11 => 133,
12 => 134, 12 => 134,
n => 58 + n n => 58 + n,
} },
]).unwrap(); ])
.unwrap();
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
TerminalEvent::Input(Event::Key(Key::Up)) => { TerminalEvent::Input(Event::Key(Key::Up)) => {
self.master.lock().unwrap().write(&[b'\x1B', b'[', b'A']).unwrap(); self.master
.lock()
.unwrap()
.write(&[b'\x1B', b'[', b'A'])
.unwrap();
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
TerminalEvent::Input(Event::Key(Key::Down)) => { TerminalEvent::Input(Event::Key(Key::Down)) => {
self.master.lock().unwrap().write(&[b'\x1B', b'[', b'B']).unwrap(); self.master
.lock()
.unwrap()
.write(&[b'\x1B', b'[', b'B'])
.unwrap();
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
TerminalEvent::Input(Event::Key(Key::Right)) => { TerminalEvent::Input(Event::Key(Key::Right)) => {
self.master.lock().unwrap().write(&[b'\x1B', b'[', b'C']).unwrap(); self.master
.lock()
.unwrap()
.write(&[b'\x1B', b'[', b'C'])
.unwrap();
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
TerminalEvent::Input(Event::Key(Key::Left)) => { TerminalEvent::Input(Event::Key(Key::Left)) => {
self.master.lock().unwrap().write(&[b'\x1B', b'[', b'D']).unwrap(); self.master
.lock()
.unwrap()
.write(&[b'\x1B', b'[', b'D'])
.unwrap();
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
_ => { _ => TerminalEditorResult::Exit,
TerminalEditorResult::Exit
}
} }
} }
} }

View file

@ -1,19 +1,14 @@
#![feature(iter_advance_by)] #![feature(iter_advance_by)]
use { use {
cgmath::Point2,
nested::terminal::{TerminalAtom, TerminalStyle},
std::{ std::{
fs::File, fs::File,
io::{stdin, Read, Write},
os::unix::io::FromRawFd, os::unix::io::FromRawFd,
io::{Read, Write, stdin}
}, },
nested::{ vte::{Params, Parser, Perform},
terminal::{
TerminalAtom,
TerminalStyle
},
},
cgmath::Point2,
vte::{Params, Parser, Perform}
}; };
struct ColorPalett { struct ColorPalett {
@ -24,7 +19,7 @@ struct ColorPalett {
blue: (u8, u8, u8), blue: (u8, u8, u8),
magenta: (u8, u8, u8), magenta: (u8, u8, u8),
cyan: (u8, u8, u8), cyan: (u8, u8, u8),
white: (u8, u8, u8) white: (u8, u8, u8),
} }
struct PerfAtom { struct PerfAtom {
@ -39,17 +34,16 @@ struct PerfAtom {
impl PerfAtom { impl PerfAtom {
fn write_atom(&mut self, pos: Point2<i16>, atom: Option<TerminalAtom>) { fn write_atom(&mut self, pos: Point2<i16>, atom: Option<TerminalAtom>) {
self.out.write(&bincode::serialize(&(pos, atom)).unwrap()).expect(""); self.out
.write(&bincode::serialize(&(pos, atom)).unwrap())
.expect("");
} }
} }
impl Perform for PerfAtom { impl Perform for PerfAtom {
fn print(&mut self, c: char) { fn print(&mut self, c: char) {
//eprintln!("[print] {:?}", c); //eprintln!("[print] {:?}", c);
self.write_atom( self.write_atom(self.cursor, Some(TerminalAtom::new(c, self.style)));
self.cursor,
Some(TerminalAtom::new(c, self.style))
);
self.cursor.x += 1; self.cursor.x += 1;
if self.cursor.x > self.term_width { if self.cursor.x > self.term_width {
@ -64,7 +58,7 @@ impl Perform for PerfAtom {
b'\n' => { b'\n' => {
self.cursor.x = 0; self.cursor.x = 0;
self.cursor.y += 1; self.cursor.y += 1;
}, }
_ => {} _ => {}
} }
} }
@ -85,7 +79,10 @@ impl Perform for PerfAtom {
} }
fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) { fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) {
eprintln!("[osc_dispatch] params={:?} bell_terminated={}", params, bell_terminated); eprintln!(
"[osc_dispatch] params={:?} bell_terminated={}",
params, bell_terminated
);
} }
fn csi_dispatch(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) { fn csi_dispatch(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) {
@ -98,29 +95,60 @@ impl Perform for PerfAtom {
match c { match c {
// Set SGR // Set SGR
'm' => while let Some(n) = piter.next() { 'm' => {
while let Some(n) = piter.next() {
match n[0] { match n[0] {
0 => self.style = TerminalStyle::default(), 0 => self.style = TerminalStyle::default(),
1 => self.style = self.style.add(TerminalStyle::bold(true)), 1 => self.style = self.style.add(TerminalStyle::bold(true)),
3 => self.style = self.style.add(TerminalStyle::italic(true)), 3 => self.style = self.style.add(TerminalStyle::italic(true)),
4 => self.style = self.style.add(TerminalStyle::underline(true)), 4 => self.style = self.style.add(TerminalStyle::underline(true)),
30 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.black)), 30 => {
40 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.black)), self.style = self.style.add(TerminalStyle::fg_color(self.colors.black))
}
40 => {
self.style = self.style.add(TerminalStyle::bg_color(self.colors.black))
}
31 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.red)), 31 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.red)),
41 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.red)), 41 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.red)),
32 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.green)), 32 => {
42 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.green)), self.style = self.style.add(TerminalStyle::fg_color(self.colors.green))
33 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.yellow)), }
43 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.yellow)), 42 => {
34 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.blue)), self.style = self.style.add(TerminalStyle::bg_color(self.colors.green))
44 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.blue)), }
35 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.magenta)), 33 => {
45 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.magenta)), self.style = self.style.add(TerminalStyle::fg_color(self.colors.yellow))
36 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.cyan)), }
46 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.cyan)), 43 => {
37 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.white)), self.style = self.style.add(TerminalStyle::bg_color(self.colors.yellow))
47 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.white)), }
34 => {
self.style = self.style.add(TerminalStyle::fg_color(self.colors.blue))
}
44 => {
self.style = self.style.add(TerminalStyle::bg_color(self.colors.blue))
}
35 => {
self.style =
self.style.add(TerminalStyle::fg_color(self.colors.magenta))
}
45 => {
self.style =
self.style.add(TerminalStyle::bg_color(self.colors.magenta))
}
36 => {
self.style = self.style.add(TerminalStyle::fg_color(self.colors.cyan))
}
46 => {
self.style = self.style.add(TerminalStyle::bg_color(self.colors.cyan))
}
37 => {
self.style = self.style.add(TerminalStyle::fg_color(self.colors.white))
}
47 => {
self.style = self.style.add(TerminalStyle::bg_color(self.colors.white))
}
38 => { 38 => {
let x = piter.next().unwrap(); let x = piter.next().unwrap();
@ -129,15 +157,21 @@ impl Perform for PerfAtom {
let r = piter.next().unwrap(); let r = piter.next().unwrap();
let g = piter.next().unwrap(); let g = piter.next().unwrap();
let b = piter.next().unwrap(); let b = piter.next().unwrap();
self.style = self.style.add(TerminalStyle::fg_color((r[0] as u8, g[0] as u8, b[30] as u8))) self.style = self.style.add(TerminalStyle::fg_color((
}, r[0] as u8,
g[0] as u8,
b[30] as u8,
)))
}
5 => { 5 => {
let v = piter.next().unwrap(); let v = piter.next().unwrap();
self.style = self.style.add(TerminalStyle::fg_color(ansi_colours::rgb_from_ansi256(v[0] as u8))) self.style = self.style.add(TerminalStyle::fg_color(
}, ansi_colours::rgb_from_ansi256(v[0] as u8),
))
}
_ => {} _ => {}
} }
}, }
48 => { 48 => {
let x = piter.next().unwrap(); let x = piter.next().unwrap();
@ -146,31 +180,50 @@ impl Perform for PerfAtom {
let r = piter.next().unwrap(); let r = piter.next().unwrap();
let g = piter.next().unwrap(); let g = piter.next().unwrap();
let b = piter.next().unwrap(); let b = piter.next().unwrap();
self.style = self.style.add(TerminalStyle::bg_color((r[0] as u8, g[0] as u8, b[30] as u8))) self.style = self.style.add(TerminalStyle::bg_color((
}, r[0] as u8,
g[0] as u8,
b[30] as u8,
)))
}
5 => { 5 => {
let v = piter.next().unwrap(); let v = piter.next().unwrap();
self.style = self.style.add(TerminalStyle::bg_color(ansi_colours::rgb_from_ansi256(v[0] as u8))) self.style = self.style.add(TerminalStyle::bg_color(
}, ansi_colours::rgb_from_ansi256(v[0] as u8),
))
}
_ => {} _ => {}
} }
}, }
_ => {} _ => {}
} }
}, }
}
'H' => { 'H' => {
if let Some(y) = piter.next() { self.cursor.y = y[0] as i16 - 1 }; if let Some(y) = piter.next() {
if let Some(x) = piter.next() { self.cursor.x = x[0] as i16 - 1 }; self.cursor.y = y[0] as i16 - 1
};
if let Some(x) = piter.next() {
self.cursor.x = x[0] as i16 - 1
};
eprintln!("cursor at {:?}", self.cursor); eprintln!("cursor at {:?}", self.cursor);
}, }
'A' => { self.cursor.y -= piter.next().unwrap()[0] as i16; } 'A' => {
'B' => { self.cursor.y += piter.next().unwrap()[0] as i16; } self.cursor.y -= piter.next().unwrap()[0] as i16;
'C' => { self.cursor.x += piter.next().unwrap()[0] as i16; } }
'D' => { self.cursor.x -= piter.next().unwrap()[0] as i16; } 'B' => {
self.cursor.y += piter.next().unwrap()[0] as i16;
}
'C' => {
self.cursor.x += piter.next().unwrap()[0] as i16;
}
'D' => {
self.cursor.x -= piter.next().unwrap()[0] as i16;
}
'E' => { 'E' => {
self.cursor.x = 0; self.cursor.x = 0;
self.cursor.y += piter.next().unwrap()[0] as i16; self.cursor.y += piter.next().unwrap()[0] as i16;
@ -179,15 +232,11 @@ impl Perform for PerfAtom {
'J' => { 'J' => {
let x = piter.next().unwrap_or(&[0 as u16; 1]); let x = piter.next().unwrap_or(&[0 as u16; 1]);
match x[0] { match x[0] {
0 => { 0 => {}
1 => {}
},
1 => {
}
2 => { 2 => {
for y in 0 .. 100 { for y in 0..100 {
for x in 0 .. self.term_width { for x in 0..self.term_width {
self.write_atom(Point2::new(x, y), None); self.write_atom(Point2::new(x, y), None);
} }
} }
@ -201,27 +250,26 @@ impl Perform for PerfAtom {
'K' => { 'K' => {
let x = piter.next().unwrap(); let x = piter.next().unwrap();
match x[0] { match x[0] {
// clear cursor until end // clear cursor until end
0 => { 0 => {
for x in self.cursor.x .. self.term_width { for x in self.cursor.x..self.term_width {
self.write_atom(Point2::new(x, self.cursor.y), None); self.write_atom(Point2::new(x, self.cursor.y), None);
} }
}, }
// clear start until cursor // clear start until cursor
1 => { 1 => {
for x in 0 .. self.cursor.x { for x in 0..self.cursor.x {
self.write_atom(Point2::new(x, self.cursor.y), None); self.write_atom(Point2::new(x, self.cursor.y), None);
} }
}, }
// clear entire line // clear entire line
2 => { 2 => {
for x in 0 .. self.term_width { for x in 0..self.term_width {
self.write_atom(Point2::new(x, self.cursor.y), None); self.write_atom(Point2::new(x, self.cursor.y), None);
} }
}, }
// invalid // invalid
_ => {} _ => {}
@ -259,8 +307,8 @@ fn main() {
blue: (0, 111, 184), blue: (0, 111, 184),
magenta: (118, 38, 113), magenta: (118, 38, 113),
cyan: (44, 181, 233), cyan: (44, 181, 233),
white: (204, 204, 204) white: (204, 204, 204),
} },
}; };
let mut buf = [0; 2048]; let mut buf = [0; 2048];
@ -273,12 +321,11 @@ fn main() {
statemachine.advance(&mut performer, *byte); statemachine.advance(&mut performer, *byte);
performer.out.flush().unwrap(); performer.out.flush().unwrap();
} }
}, }
Err(err) => { Err(err) => {
println!("err: {}", err); println!("err: {}", err);
break; break;
}, }
} }
} }
} }

View file

@ -1,21 +1,20 @@
use { use {
std::{ cgmath::{Point2, Vector2},
io::{Read, Write, stdout} nested::terminal::{TerminalAtom, TerminalStyle},
}, std::io::{stdout, Read, Write},
nested::terminal::{
TerminalAtom,
TerminalStyle
},
termion::raw::IntoRawMode, termion::raw::IntoRawMode,
cgmath::{Point2, Vector2}
}; };
fn main() { fn main() {
let mut out = stdout().into_raw_mode().unwrap(); let mut out = stdout().into_raw_mode().unwrap();
write!(out, "{}{}{}", write!(
out,
"{}{}{}",
termion::cursor::Hide, termion::cursor::Hide,
termion::cursor::Goto(1, 1), termion::cursor::Goto(1, 1),
termion::style::Reset).unwrap(); termion::style::Reset
)
.unwrap();
let mut cur_pos = Point2::<i16>::new(0, 0); let mut cur_pos = Point2::<i16>::new(0, 0);
let mut cur_style = TerminalStyle::default(); let mut cur_style = TerminalStyle::default();
@ -26,7 +25,12 @@ fn main() {
match bincode::deserialize_from::<_, (Point2<i16>, Option<TerminalAtom>)>(input.by_ref()) { match bincode::deserialize_from::<_, (Point2<i16>, Option<TerminalAtom>)>(input.by_ref()) {
Ok((pos, atom)) => { Ok((pos, atom)) => {
if pos != cur_pos { if pos != cur_pos {
write!(out, "{}", termion::cursor::Goto(pos.x as u16 + 1, pos.y as u16 + 1)).unwrap(); write!(
out,
"{}",
termion::cursor::Goto(pos.x as u16 + 1, pos.y as u16 + 1)
)
.unwrap();
} }
if let Some(atom) = atom { if let Some(atom) = atom {
@ -47,9 +51,7 @@ fn main() {
} }
Err(err) => { Err(err) => {
match *err { match *err {
bincode::ErrorKind::Io(_io_error) => { bincode::ErrorKind::Io(_io_error) => break,
break
}
err => { err => {
eprintln!("deserialization error\n{:?}", err); eprintln!("deserialization error\n{:?}", err);
} }
@ -63,4 +65,3 @@ fn main() {
write!(out, "{}", termion::cursor::Show).unwrap(); write!(out, "{}", termion::cursor::Show).unwrap();
out.flush().unwrap(); out.flush().unwrap();
} }