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::{
fs::File,
io::{Read, Write},
os::unix::io::FromRawFd
os::unix::io::FromRawFd,
};
fn fib(n: u64) -> u64 {
@ -10,7 +9,7 @@ fn fib(n: u64) -> u64 {
let mut y1 = 1;
let mut y2 = 0;
for _ in 0 .. n {
for _ in 0..n {
y = y1 + y2;
y2 = y1;
y1 = y;
@ -26,26 +25,32 @@ fn main() {
nested::magic_header();
eprintln!("
interface (Sequence ) 0 1");
eprintln!(
"
interface (Sequence ) 0 1"
);
let mut f0 = unsafe { File::from_raw_fd(0) };
eprintln!("
eprintln!(
"
>0: n
( )
( MachineInt )
( MachineWord )
( Stream MachineSyllab )
");
"
);
let mut f1 = unsafe { File::from_raw_fd(1) };
eprintln!("
eprintln!(
"
<1: n'th fibonacci number
( )
( MachineInt )
( MachineWord )
( Stream MachineSyllab )
");
"
);
nested::magic_header();
@ -55,4 +60,3 @@ interface (Sequence ) 0 1");
bytes = fib(n).to_le_bytes();
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() {
nested::magic_header();
@ -11,15 +6,18 @@ fn main() {
nested::magic_header();
let mut f0 = unsafe { File::from_raw_fd(0) };
eprintln!("
eprintln!(
"
>0:
( )
( MachineInt )
( MachineWord )
( Stream MachineSyllab )
");
"
);
eprintln!("
eprintln!(
"
<1:
( )
( PositionalInt 10 BigEndian )
@ -27,7 +25,8 @@ fn main() {
( Sequence UTF-8-Char )
( Stream UTF-8-Char )
( Stream MachineSyllab )
");
"
);
nested::magic_header();
@ -35,4 +34,3 @@ fn main() {
f0.read_exact(&mut bytes).expect("");
println!("{}", u64::from_le_bytes(bytes));
}

View file

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

View file

@ -1,8 +1,7 @@
use std::{
fs::File,
io::{Read, Write},
os::unix::io::FromRawFd
os::unix::io::FromRawFd,
};
fn main() {
@ -10,16 +9,19 @@ fn main() {
eprintln!(" Parse MachineInt from String");
nested::magic_header();
eprintln!("
eprintln!(
"
$1: radix
( )
( PositionalInt 10 BigEndian )
( Sequence ( Digit 10 ) )
( Sequence UTF-8-Char )
( Sequence MachineSyllab )
");
"
);
eprintln!("
eprintln!(
"
>0: n
( )
( PositionalInt $radix BigEndian )
@ -27,15 +29,18 @@ $1: radix
( Sequence UTF-8-Char )
( Stream UTF-8-Char )
( Stream MachineSyllab )
");
"
);
eprintln!("
eprintln!(
"
<1: n
( )
( MachineInt )
( MachineWord )
( Stream MachineSyllab )
");
"
);
nested::magic_header();
@ -55,6 +60,10 @@ $1: radix
let mut chars = Vec::new();
f0.read_to_end(&mut chars).expect("");
chars.retain(|c| (*c as char).is_alphanumeric());
f1.write(&u64::from_str_radix(&String::from_utf8_lossy(&chars), radix).unwrap().to_le_bytes()).expect("");
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::{
collections::HashMap,
hash::Hash
};
use std::{collections::HashMap, hash::Hash};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct Bimap<V: Eq + Hash, Λ: Eq + Hash> {
pub : HashMap::<V, Λ>,
pub my: HashMap::<Λ, V>
pub : HashMap<V, Λ>,
pub my: HashMap<Λ, V>,
}
impl<V: Eq + Hash + Clone, Λ: Eq + Hash + Clone> Bimap<V, Λ> {
pub fn new() -> Self {
Bimap {
: 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 {
crate::core::Observer,
async_std::stream::Stream,
core::{
task::{Poll, Context, Waker},
pin::Pin
pin::Pin,
task::{Context, Poll, Waker},
},
std::{
sync::{Arc, Mutex},
collections::HashSet,
hash::Hash
hash::Hash,
sync::{Arc, Mutex},
},
async_std::{
stream::Stream
},
crate::{
core::{Observer}
}
};
/*\
/*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Traits
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/
pub trait ChannelData : Default + IntoIterator + Send + Sync {
pub trait ChannelData: Default + IntoIterator + Send + Sync {
fn channel_insert(&mut self, x: Self::Item);
}
/*\
/*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Queue Channel
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/
impl<T> ChannelData for Vec<T>
where T: Send + Sync {
where
T: Send + Sync,
{
fn channel_insert(&mut self, x: T) {
self.push(x);
}
}
/*\
/*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Set Channel
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/
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) {
self.insert(x);
}
}
/*\
/*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Singleton Channel
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/
impl<T> ChannelData for Option<T>
where T: Send + Sync {
where
T: Send + Sync,
{
fn channel_insert(&mut self, x: T) {
*self = Some(x);
}
}
/*\
/*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Channel
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -73,7 +72,7 @@ struct ChannelState<Data: ChannelData> {
send_buf: Option<Data>,
recv_iter: Option<Data::IntoIter>,
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>
where Data::IntoIter: Send + Sync {
where
Data::IntoIter: Send + Sync,
{
pub fn send(&self, msg: Data::Item) {
let mut state = self.0.lock().unwrap();
@ -102,7 +103,10 @@ where Data::IntoIter: Send + Sync {
use crate::core::View;
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) {
self.send(msg.clone());
}
@ -164,15 +168,12 @@ impl<Data: ChannelData> std::future::Future for ChannelRead<Data> {
impl<Data: ChannelData> Stream for ChannelReceiver<Data> {
type Item = Data::Item;
fn poll_next(
self: Pin<&mut Self>,
cx: &mut Context<'_>
) -> Poll<Option<Self::Item>> {
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let mut state = self.0.lock().unwrap();
if let Some(recv_iter) = state.recv_iter.as_mut() {
if let Some(val) = recv_iter.next() {
return Poll::Ready(Some(val))
return Poll::Ready(Some(val));
} else {
state.recv_iter = None
}
@ -191,23 +192,24 @@ impl<Data: ChannelData> Stream for ChannelReceiver<Data> {
}
}
/*\
/*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
Factory Functions
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/
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,
recv_iter: None,
num_senders: 1,
waker: None
waker: None,
}));
(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>>()
}
@ -215,7 +217,7 @@ pub fn queue_channel<T: Send + Sync>() -> (ChannelSender<Vec<T>>, ChannelReceive
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>>()
}

View file

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

View file

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

View file

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

View file

@ -1,22 +1,15 @@
use {
std::sync::Arc,
crate::core::{NotifyFnObserver, Observer, ObserverBroadcast, ResetFnObserver, View},
std::any::Any,
std::sync::Arc,
std::sync::RwLock,
crate::core::{
View,
Observer,
ObserverBroadcast,
NotifyFnObserver,
ResetFnObserver
}
};
pub trait UpdateTask : Send + Sync {
pub trait UpdateTask: Send + Sync {
fn update(&self);
}
/*\
/*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
View Port
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -24,16 +17,18 @@ pub trait UpdateTask : Send + Sync {
pub struct ViewPort<V: View + ?Sized> {
view: Arc<RwLock<Option<Arc<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>
where V::Msg: Clone {
where
V::Msg: Clone,
{
pub fn new() -> Self {
ViewPort {
view: Arc::new(RwLock::new(None)),
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>>>) {
self.update();
self.cast.write().unwrap().add_observer(Arc::downgrade(&observer));
observer.write().unwrap().reset(self.view.read().unwrap().clone());
self.cast
.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>) {
@ -60,47 +61,42 @@ where V::Msg: Clone {
}
pub fn inner(&self) -> InnerViewPort<V> {
InnerViewPort(
ViewPort{
view: self.view.clone(),
cast: self.cast.clone(),
update_hooks: self.update_hooks.clone()
}
)
InnerViewPort(ViewPort {
view: self.view.clone(),
cast: self.cast.clone(),
update_hooks: self.update_hooks.clone(),
})
}
pub fn outer(&self) -> OuterViewPort<V> {
OuterViewPort(
ViewPort{
view: self.view.clone(),
cast: self.cast.clone(),
update_hooks: self.update_hooks.clone()
}
)
OuterViewPort(ViewPort {
view: self.view.clone(),
cast: self.cast.clone(),
update_hooks: self.update_hooks.clone(),
})
}
pub fn into_inner(self) -> InnerViewPort<V> {
InnerViewPort(
ViewPort{
view: self.view,
cast: self.cast,
update_hooks: self.update_hooks
}
)
InnerViewPort(ViewPort {
view: self.view,
cast: self.cast,
update_hooks: self.update_hooks,
})
}
pub fn into_outer(self) -> OuterViewPort<V> {
OuterViewPort(
ViewPort{
view: self.view,
cast: self.cast,
update_hooks: self.update_hooks
}
)
OuterViewPort(ViewPort {
view: self.view,
cast: self.cast,
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) {
let v = {
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>
where V::Msg: Clone {
where
V::Msg: Clone,
{
fn clone(&self) -> Self {
ViewPort {
view: self.view.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 OuterViewPort<V: View + ?Sized>(pub ViewPort<V>) where V::Msg: Clone;
pub struct InnerViewPort<V: View + ?Sized>(pub ViewPort<V>)
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>>> {
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>
where V::Msg: Clone {
where
V::Msg: Clone,
{
fn clone(&self) -> Self {
InnerViewPort(self.0.clone())
}
@ -163,7 +169,9 @@ where V::Msg: Clone {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<V: View + ?Sized + 'static> OuterViewPort<V>
where V::Msg: Clone {
where
V::Msg: Clone,
{
pub fn get_view(&self) -> Option<Arc<V>> {
self.0.view.read().unwrap().clone()
}
@ -172,18 +180,27 @@ where V::Msg: 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.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)));
self.add_observer(obs.clone());
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)));
self.add_observer(obs.clone());
obs
@ -191,7 +208,9 @@ where V::Msg: Clone {
}
impl<V: View + ?Sized> Clone for OuterViewPort<V>
where V::Msg: Clone {
where
V::Msg: Clone,
{
fn clone(&self) -> Self {
OuterViewPort(self.0.clone())
}
@ -223,7 +242,7 @@ where V::Msg: Clone {
pub struct AnyViewPort {
view: 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 {
@ -231,10 +250,14 @@ impl AnyViewPort {
match (
self.view.clone().downcast::<RwLock<Option<Arc<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}),
_ => Err(self)
(Ok(view), Ok(cast), update_hooks) => Ok(ViewPort {
view,
cast,
update_hooks,
}),
_ => Err(self),
}
}
}
@ -244,7 +267,7 @@ impl<V: View + ?Sized + 'static> From<ViewPort<V>> for AnyViewPort {
AnyViewPort {
view: port.view 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);
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>()?))
}
}
impl<V: View + ?Sized + 'static> From<OuterViewPort<V>> for AnyOuterViewPort
where V::Msg: Clone {
where
V::Msg: Clone,
{
fn from(port: OuterViewPort<V>) -> Self {
AnyOuterViewPort(AnyViewPort{
AnyOuterViewPort(AnyViewPort {
view: port.0.view 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 {
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>()?))
}
}
impl<V: View + ?Sized + 'static> From<InnerViewPort<V>> for AnyInnerViewPort
where V::Msg: Clone {
where
V::Msg: Clone,
{
fn from(port: InnerViewPort<V>) -> Self {
AnyInnerViewPort(AnyViewPort{
AnyInnerViewPort(AnyViewPort {
view: port.0.view 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 {
std::{
collections::HashMap
},
crate::{
bimap::Bimap,
}
};
use {crate::bimap::Bimap, std::collections::HashMap};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -15,20 +8,17 @@ pub type TypeID = u64;
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum TypeTerm {
Type {
id: TypeID,
args: Vec<TypeTerm>
},
Num(i64)
Type { id: TypeID, args: Vec<TypeTerm> },
Num(i64),
}
impl TypeTerm {
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 {
if let TypeTerm::Type{ id: _, args } = self {
if let TypeTerm::Type { id: _, args } = self {
args.push(t);
}
@ -46,7 +36,7 @@ impl TypeTerm {
match token {
"(" => {
term_stack.push(None);
},
}
")" => {
let t = term_stack.pop().unwrap();
if term_stack.len() > 0 {
@ -59,19 +49,24 @@ impl TypeTerm {
} else {
return t;
}
},
}
atom => {
let f = term_stack.last_mut().unwrap();
match f {
Some(f) =>
Some(f) => {
if atom.chars().nth(0).unwrap().is_numeric() {
f.num_arg(i64::from_str_radix(atom, 10).unwrap());
} 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 => {
*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
pub fn to_str1(&self, names: &HashMap<u64, String>) -> String {
match self {
TypeTerm::Type{ id, args } =>
TypeTerm::Type { id, args } => {
if args.len() > 0 {
format!(
"( {} {})",
names[id],
if args.len() > 0 {
args.iter().fold(
String::new(),
|str, term| format!("{}{} ", str, term.to_str1(names) )
)
args.iter().fold(String::new(), |str, term| {
format!("{}{} ", str, term.to_str1(names))
})
} else {
String::new()
}
)
} else {
names[id].clone()
},
}
}
TypeTerm::Num(n) =>
format!("{}", n)
TypeTerm::Num(n) => format!("{}", n),
}
}
// always adds an enclosing pair of parenthesis
pub fn to_str(&self, names: &HashMap<u64, String>) -> String {
match self {
TypeTerm::Type{ id, args } =>
format!(
"( {} {})",
names[id],
if args.len() > 0 {
args.iter().fold(
String::new(),
|str, term| format!("{}{} ", str, term.to_str1(names) )
)
} else {
String::new()
}),
TypeTerm::Type { id, args } => format!(
"( {} {})",
names[id],
if args.len() > 0 {
args.iter().fold(String::new(), |str, term| {
format!("{}{} ", str, term.to_str1(names))
})
} else {
String::new()
}
),
TypeTerm::Num(n) =>
format!("{}", n)
TypeTerm::Num(n) => format!("{}", n),
}
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct TypeDict {
typenames: Bimap::<String, u64>,
type_id_counter: u64
typenames: Bimap<String, u64>,
type_id_counter: u64,
}
impl TypeDict {
pub fn new() -> Self {
TypeDict {
typenames: Bimap::new(),
type_id_counter: 0
type_id_counter: 0,
}
}
@ -160,4 +151,3 @@ impl TypeDict {
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>

View file

@ -1,12 +1,11 @@
/*\
/*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
View
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
\*/
pub trait View : Send + Sync {
pub trait View: Send + Sync {
/// 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> {
type Msg = V::Msg;
}

View file

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

View file

@ -1,11 +1,10 @@
use {
crate::index::{IndexArea, IndexView},
cgmath::Point2,
std::{
cmp::{max, min},
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 offset;
pub mod window_iterator;
pub use window_iterator::GridWindowIterator;
@ -23,7 +22,6 @@ pub use window_iterator::GridWindowIterator;
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl IndexArea<Point2<i16>> {
// todo: this is not perfect (e.g. diagonals are inefficient)
pub fn iter(&self) -> GridWindowIterator {
GridWindowIterator::from(self.range())
@ -31,52 +29,46 @@ impl IndexArea<Point2<i16>> {
pub fn range(&self) -> RangeInclusive<Point2<i16>> {
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::Set(v) =>
IndexArea::Set(v) => {
Point2::new(
v.iter().map(|p| p.x).min().unwrap_or(0),
v.iter().map(|p| p.y).min().unwrap_or(0)
) ..=
Point2::new(
v.iter().map(|p| p.x).max().unwrap_or(0),
v.iter().map(|p| p.y).max().unwrap_or(0)
),
IndexArea::Range(r) => r.clone()
v.iter().map(|p| p.y).min().unwrap_or(0),
)
..=Point2::new(
v.iter().map(|p| p.x).max().unwrap_or(0),
v.iter().map(|p| p.y).max().unwrap_or(0),
)
}
IndexArea::Range(r) => r.clone(),
}
}
pub fn union(self, other: IndexArea<Point2<i16>>) -> IndexArea<Point2<i16>> {
match (self, other) {
(IndexArea::Empty, a) |
(a, IndexArea::Empty) => 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());
IndexArea::Set(va)
},
}
(IndexArea::Range(r), IndexArea::Set(mut v)) |
(IndexArea::Set(mut v), IndexArea::Range(r)) => {
(IndexArea::Range(r), IndexArea::Set(mut v))
| (IndexArea::Set(mut v), IndexArea::Range(r)) => {
v.extend(GridWindowIterator::from(r));
IndexArea::Set(v)
},
}
(IndexArea::Range(ra), IndexArea::Range(rb)) => IndexArea::Range(
Point2::new(
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 {
crate::{core::OuterViewPort, grid::GridView},
cgmath::Vector2,
crate::{
core::OuterViewPort,
grid::GridView
}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
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>> {
self.map_key(
move |pt| pt + offset,
move |pt| Some(pt - offset)
)
self.map_key(move |pt| pt + offset, move |pt| Some(pt - offset))
}
}

View file

@ -1,14 +1,13 @@
use {
cgmath::Point2,
std::ops::{Range, RangeInclusive},
cgmath::{Point2}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct GridWindowIterator {
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 {
GridWindowIterator {
next: range.start,
range
range,
}
}
}
@ -26,7 +25,7 @@ impl From<RangeInclusive<Point2<i16>>> for GridWindowIterator {
fn from(range: RangeInclusive<Point2<i16>>) -> Self {
GridWindowIterator {
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 {
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;
} else {
self.next.x = self.range.start.x;
@ -57,4 +56,3 @@ impl Iterator for GridWindowIterator {
}
}
}

View file

@ -1,36 +1,29 @@
use {
std::{
sync::Arc,
collections::HashMap,
hash::Hash
crate::{
core::{InnerViewPort, Observer, ObserverBroadcast, View},
index::{IndexArea, IndexView},
},
std::sync::RwLock,
crate::{
core::{
Observer,
ObserverBroadcast,
View,
InnerViewPort
},
index::{IndexArea, IndexView}
}
std::{collections::HashMap, hash::Hash, sync::Arc},
};
pub struct IndexBufferView<Key, Item>(Arc<RwLock<HashMap<Key, Item>>>)
where Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static;
where
Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static;
impl<Key, Item> View for IndexBufferView<Key, Item>
where Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static
where
Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static,
{
type Msg = IndexArea<Key>;
}
impl<Key, Item> IndexView<Key> for IndexBufferView<Key, Item>
where Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static
where
Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static,
{
type Item = Item;
@ -44,16 +37,18 @@ where Key: Clone + Hash + Eq + Send + Sync + 'static,
}
pub struct IndexBuffer<Key, Item>
where Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static
where
Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static,
{
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>
where Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static
where
Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static,
{
pub fn new(port: InnerViewPort<dyn IndexView<Key, Item = Item>>) -> Self {
let data = Arc::new(RwLock::new(HashMap::<Key, Item>::new()));
@ -61,17 +56,19 @@ where Key: Clone + Hash + Eq + Send + Sync + 'static,
IndexBuffer {
data,
cast: port.get_broadcast()
cast: port.get_broadcast(),
}
}
pub fn insert(&mut self, key: Key, item: 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)
where T: IntoIterator<Item = (Key, Item)> {
where
T: IntoIterator<Item = (Key, Item)>,
{
for (key, item) in iter {
self.insert(key, item);
}
@ -79,7 +76,6 @@ where Key: Clone + Hash + Eq + Send + Sync + 'static,
pub fn remove(&mut self, key: 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 {
std::{
sync::Arc,
boxed::Box
},
std::sync::RwLock,
crate::{
core::{
View,
Observer,
ObserverExt,
ObserverBroadcast,
ViewPort,
InnerViewPort,
OuterViewPort
InnerViewPort, Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View, ViewPort,
},
index::{IndexArea, IndexView}
}
index::{IndexArea, IndexView},
},
std::sync::RwLock,
std::{boxed::Box, sync::Arc},
};
impl<Key, Item> OuterViewPort<dyn IndexView<Key, Item = Item>>
where Key: Clone + Send + Sync + 'static,
Item: Send + Sync + 'static
where
Key: Clone + Send + Sync + 'static,
Item: Send + Sync + 'static,
{
pub fn map_item<
DstItem: 'static,
F: Fn(&Key, &Item) -> DstItem + Send + Sync + 'static
>(
pub fn map_item<DstItem: 'static, F: Fn(&Key, &Item) -> DstItem + Send + Sync + 'static>(
&self,
f: F
f: F,
) -> OuterViewPort<dyn IndexView<Key, Item = DstItem>> {
let port = ViewPort::new();
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>
where Key: Clone + Send + Sync,
SrcView: IndexView<Key> + ?Sized,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync
where
Key: Clone + Send + Sync,
SrcView: IndexView<Key> + ?Sized,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync,
{
src_view: Option<Arc<SrcView>>,
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>
where Key: Clone + Send + Sync + 'static,
DstItem: 'static,
SrcView: IndexView<Key> + ?Sized + 'static,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync + 'static
where
Key: Clone + Send + Sync + 'static,
DstItem: 'static,
SrcView: IndexView<Key> + ?Sized + 'static,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync + 'static,
{
fn new(
port: InnerViewPort<dyn IndexView<Key, Item = DstItem>>,
f: F
) -> Arc<RwLock<Self>> {
let map = Arc::new(RwLock::new(
MapIndexItem {
src_view: None,
f,
cast: port.get_broadcast()
}
));
fn new(port: InnerViewPort<dyn IndexView<Key, Item = DstItem>>, f: F) -> Arc<RwLock<Self>> {
let map = Arc::new(RwLock::new(MapIndexItem {
src_view: None,
f,
cast: port.get_broadcast(),
}));
port.set_view(Some(map.clone()));
map
@ -72,22 +58,27 @@ where Key: Clone + Send + Sync + 'static,
}
impl<Key, DstItem, SrcView, F> View for MapIndexItem<Key, DstItem, SrcView, F>
where Key: Clone + Send + Sync,
SrcView: IndexView<Key> + ?Sized,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync
where
Key: Clone + Send + Sync,
SrcView: IndexView<Key> + ?Sized,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync,
{
type Msg = IndexArea<Key>;
}
impl<Key, DstItem, SrcView, F> IndexView<Key> for MapIndexItem<Key, DstItem, SrcView, F>
where Key: Clone + Send + Sync,
SrcView: IndexView<Key> + ?Sized,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync
where
Key: Clone + Send + Sync,
SrcView: IndexView<Key> + ?Sized,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync,
{
type Item = DstItem;
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> {
@ -96,9 +87,10 @@ where Key: Clone + Send + Sync,
}
impl<Key, DstItem, SrcView, F> Observer<SrcView> for MapIndexItem<Key, DstItem, SrcView, F>
where Key: Clone + Send + Sync,
SrcView: IndexView<Key> + ?Sized,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync
where
Key: Clone + Send + Sync,
SrcView: IndexView<Key> + ?Sized,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync,
{
fn reset(&mut self, view: Option<Arc<SrcView>>) {
let old_area = self.area();
@ -113,4 +105,3 @@ where Key: Clone + Send + Sync,
self.cast.notify(area);
}
}

View file

@ -1,27 +1,19 @@
pub use {
std::{
sync::Arc,
boxed::Box
},
std::sync::RwLock,
crate::{
core::{
View,
Observer,
ObserverExt,
ObserverBroadcast,
ViewPort,
InnerViewPort,
OuterViewPort
InnerViewPort, Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View, ViewPort,
},
grid::GridView,
index::{IndexArea, IndexView},
grid::{GridView}
}
},
std::sync::RwLock,
std::{boxed::Box, sync::Arc},
};
impl<SrcKey, Item> OuterViewPort<dyn IndexView<SrcKey, Item = Item>>
where SrcKey: Clone + Send + Sync + 'static,
Item: 'static
where
SrcKey: Clone + Send + Sync + 'static,
Item: 'static,
{
pub fn map_key<
DstKey: Clone + Send + Sync + 'static,
@ -30,7 +22,7 @@ where SrcKey: Clone + Send + Sync + 'static,
>(
&self,
f1: F1,
f2: F2
f2: F2,
) -> OuterViewPort<dyn IndexView<DstKey, Item = Item>> {
let port = ViewPort::new();
port.add_update_hook(Arc::new(self.0.clone()));
@ -42,57 +34,58 @@ where SrcKey: Clone + Send + Sync + 'static,
}
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>> {
self.map_key(
|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>> {
self.map_key(
|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>
where DstKey: Clone + Send + Sync,
SrcKey: Clone + Send + Sync,
SrcView: IndexView<SrcKey> + ?Sized,
F1: Fn(&SrcKey) -> DstKey + Send + Sync,
F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync,
where
DstKey: Clone + Send + Sync,
SrcKey: Clone + Send + Sync,
SrcView: IndexView<SrcKey> + ?Sized,
F1: Fn(&SrcKey) -> DstKey + Send + Sync,
F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync,
{
src_view: Option<Arc<SrcView>>,
f1: F1,
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>
where DstKey: Clone + Send + Sync + 'static,
SrcKey: Clone + Send + Sync + 'static,
SrcView: IndexView<SrcKey> + ?Sized + 'static,
SrcView::Item: 'static,
F1: Fn(&SrcKey) -> DstKey + Send + Sync + 'static,
F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync + 'static,
where
DstKey: Clone + Send + Sync + 'static,
SrcKey: Clone + Send + Sync + 'static,
SrcView: IndexView<SrcKey> + ?Sized + 'static,
SrcView::Item: 'static,
F1: Fn(&SrcKey) -> DstKey + Send + Sync + 'static,
F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync + 'static,
{
fn new(
port: InnerViewPort<dyn IndexView<DstKey, Item = SrcView::Item>>,
f1: F1,
f2: F2
f2: F2,
) -> Arc<RwLock<Self>> {
let map = Arc::new(RwLock::new(
MapIndexKey {
src_view: None,
f1,
f2,
cast: port.get_broadcast()
}
));
let map = Arc::new(RwLock::new(MapIndexKey {
src_view: None,
f1,
f2,
cast: port.get_broadcast(),
}));
port.set_view(Some(map.clone()));
map
@ -100,21 +93,24 @@ where DstKey: Clone + Send + Sync + 'static,
}
impl<DstKey, SrcKey, SrcView, F1, F2> View for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
where DstKey: Clone + Send + Sync,
SrcKey: Clone + Send + Sync,
SrcView: IndexView<SrcKey> + ?Sized,
F1: Fn(&SrcKey) -> DstKey + Send + Sync,
F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync,
where
DstKey: Clone + Send + Sync,
SrcKey: Clone + Send + Sync,
SrcView: IndexView<SrcKey> + ?Sized,
F1: Fn(&SrcKey) -> DstKey + Send + Sync,
F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync,
{
type Msg = IndexArea<DstKey>;
}
impl<DstKey, SrcKey, SrcView, F1, F2> IndexView<DstKey> for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
where DstKey: Clone + Send + Sync,
SrcKey: Clone + Send + Sync,
SrcView: IndexView<SrcKey> + ?Sized,
F1: Fn(&SrcKey) -> DstKey + Send + Sync,
F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync,
impl<DstKey, SrcKey, SrcView, F1, F2> IndexView<DstKey>
for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
where
DstKey: Clone + Send + Sync,
SrcKey: Clone + Send + Sync,
SrcView: IndexView<SrcKey> + ?Sized,
F1: Fn(&SrcKey) -> DstKey + Send + Sync,
F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync,
{
type Item = SrcView::Item;
@ -127,12 +123,14 @@ where DstKey: Clone + Send + Sync,
}
}
impl<DstKey, SrcKey, SrcView, F1, F2> Observer<SrcView> for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
where DstKey: Clone + Send + Sync,
SrcKey: Clone + Send + Sync,
SrcView: IndexView<SrcKey> + ?Sized,
F1: Fn(&SrcKey) -> DstKey + Send + Sync,
F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync,
impl<DstKey, SrcKey, SrcView, F1, F2> Observer<SrcView>
for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
where
DstKey: Clone + Send + Sync,
SrcKey: Clone + Send + Sync,
SrcView: IndexView<SrcKey> + ?Sized,
F1: Fn(&SrcKey) -> DstKey + Send + Sync,
F2: Fn(&DstKey) -> Option<SrcKey> + Send + Sync,
{
fn reset(&mut self, view: Option<Arc<SrcView>>) {
let old_area = self.area();
@ -145,4 +143,3 @@ where DstKey: Clone + Send + Sync,
self.cast.notify(&msg.map(&self.f1));
}
}

View file

@ -1,15 +1,14 @@
pub mod buffer;
pub mod map_item;
pub mod map_key;
pub mod buffer;
use {
std::{
sync::Arc,
ops::{Deref, RangeInclusive},
},
crate::core::View,
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::Full => IndexArea::Full,
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>>
where Key: Send + Sync {
pub trait IndexView<Key>: View<Msg = IndexArea<Key>>
where
Key: Send + Sync,
{
type 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>
where Key: Send + Sync,
V: IndexView<Key> + ?Sized
where
Key: Send + Sync,
V: IndexView<Key> + ?Sized,
{
type Item = V::Item;
@ -63,8 +65,9 @@ where Key: Send + Sync,
}
impl<Key, V> IndexView<Key> for Arc<V>
where Key: Send + Sync,
V: IndexView<Key> + ?Sized
where
Key: Send + Sync,
V: IndexView<Key> + ?Sized,
{
type Item = V::Item;
@ -78,8 +81,9 @@ where Key: Send + Sync,
}
impl<Key, V> IndexView<Key> for Option<V>
where Key: Send + Sync,
V: IndexView<Key>
where
Key: Send + Sync,
V: IndexView<Key>,
{
type Item = V::Item;

View file

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

View file

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

View file

@ -1,21 +1,17 @@
use {
std::sync::{Arc, RwLock},
crate::{
core::{
Observer,
InnerViewPort,
OuterViewPort
},
core::{InnerViewPort, Observer, OuterViewPort},
sequence::SequenceView,
vec::VecBuffer
}
vec::VecBuffer,
},
std::sync::{Arc, RwLock},
};
pub struct RadixProjection {
src_radix: usize,
dst_radix: usize,
src_digits: Option<Arc<dyn SequenceView<Item = usize>>>,
dst_digits: RwLock<VecBuffer<usize>>
dst_digits: RwLock<VecBuffer<usize>>,
}
impl RadixProjection {
@ -23,17 +19,15 @@ impl RadixProjection {
src_radix: usize,
dst_radix: usize,
src_digits: OuterViewPort<dyn SequenceView<Item = usize>>,
dst_digits: InnerViewPort<RwLock<Vec<usize>>>
dst_digits: InnerViewPort<RwLock<Vec<usize>>>,
) -> Arc<RwLock<Self>> {
dst_digits.0.add_update_hook(Arc::new(src_digits.0.clone()));
let proj = Arc::new(RwLock::new(
RadixProjection {
src_radix,
dst_radix,
src_digits: None,
dst_digits: RwLock::new(VecBuffer::new(dst_digits))
}
));
let proj = Arc::new(RwLock::new(RadixProjection {
src_radix,
dst_radix,
src_digits: None,
dst_digits: RwLock::new(VecBuffer::new(dst_digits)),
}));
src_digits.add_observer(proj.clone());
proj
}
@ -41,7 +35,7 @@ impl RadixProjection {
fn machine_int(&self) -> usize {
let mut val = 0;
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();
r *= self.src_radix;
}
@ -64,18 +58,18 @@ impl RadixProjection {
fn _update_dst_digit(&mut self, _idx: usize) {
/*
let v = 0; // calculate new digit value
let v = 0; // calculate new digit value
// which src-digits are responsible?
// which src-digits are responsible?
if idx < self.dst_digits.len() {
self.dst_digits.get_mut(idx) = v;
} else if idx == self.dst_digits.len() {
self.dst_digits.push(v);
} else {
// error
}
*/
if idx < self.dst_digits.len() {
self.dst_digits.get_mut(idx) = v;
} else if idx == self.dst_digits.len() {
self.dst_digits.push(v);
} else {
// error
}
*/
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,37 +1,34 @@
use {
std::{
sync::Arc
},
std::sync::RwLock,
crate::{
core::{
View, Observer, ObserverBroadcast,
ViewPort, InnerViewPort, OuterViewPort
},
sequence::SequenceView,
core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View, ViewPort},
grid::GridView,
index::{IndexArea, IndexView},
grid::GridView
}
sequence::SequenceView,
},
std::sync::Arc,
std::sync::RwLock,
};
/// Transforms a SequenceView into IndexView<usize>
pub struct Sequence2Index<SrcView>
where SrcView: SequenceView + ?Sized + 'static {
where
SrcView: SequenceView + ?Sized + 'static,
{
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>
where SrcView: SequenceView + ?Sized + 'static {
where
SrcView: SequenceView + ?Sized + 'static,
{
pub fn new(
port: InnerViewPort<dyn IndexView<usize, Item = SrcView::Item>>
port: InnerViewPort<dyn IndexView<usize, Item = SrcView::Item>>,
) -> Arc<RwLock<Self>> {
let s2i = Arc::new(RwLock::new(
Sequence2Index {
src_view: None,
cast: port.get_broadcast()
}
));
let s2i = Arc::new(RwLock::new(Sequence2Index {
src_view: None,
cast: port.get_broadcast(),
}));
port.set_view(Some(s2i.clone()));
s2i
}
@ -55,12 +52,16 @@ impl<Item: 'static> OuterViewPort<dyn SequenceView<Item = Item>> {
}
impl<SrcView> View for Sequence2Index<SrcView>
where SrcView: SequenceView + ?Sized + 'static {
where
SrcView: SequenceView + ?Sized + 'static,
{
type Msg = IndexArea<usize>;
}
impl<SrcView> IndexView<usize> for Sequence2Index<SrcView>
where SrcView: SequenceView + ?Sized + 'static {
where
SrcView: SequenceView + ?Sized + 'static,
{
type Item = SrcView::Item;
fn get(&self, key: &usize) -> Option<Self::Item> {
@ -70,7 +71,7 @@ where SrcView: SequenceView + ?Sized + 'static {
fn area(&self) -> IndexArea<usize> {
if let Some(len) = self.src_view.len() {
if len > 0 {
IndexArea::Range(0 ..= len-1)
IndexArea::Range(0..=len - 1)
} else {
IndexArea::Empty
}
@ -81,7 +82,9 @@ where SrcView: SequenceView + ?Sized + 'static {
}
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>>) {
let old_area = self.area();
self.src_view = view;
@ -91,7 +94,6 @@ where SrcView: SequenceView + ?Sized + 'static {
}
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 {
std::{
sync::{Arc},
ops::{Deref, DerefMut}
crate::{
core::{InnerViewPort, Observer, ObserverBroadcast, View},
singleton::SingletonView,
},
std::sync::RwLock,
crate::{
core::{
Observer,
ObserverBroadcast,
View,
InnerViewPort
},
singleton::{SingletonView}
}
std::{
ops::{Deref, DerefMut},
sync::Arc,
},
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -20,12 +15,16 @@ use {
pub struct SingletonBufferView<T: Clone + Send + Sync + 'static>(Arc<RwLock<T>>);
impl<T> View for SingletonBufferView<T>
where T: Clone + Send + Sync + 'static {
where
T: Clone + Send + Sync + 'static,
{
type Msg = ();
}
impl<T> SingletonView for SingletonBufferView<T>
where T: Clone + Send + Sync + 'static {
where
T: Clone + Send + Sync + 'static,
{
type Item = T;
fn get(&self) -> Self::Item {
@ -37,23 +36,24 @@ where T: Clone + Send + Sync + 'static {
#[derive(Clone)]
pub struct SingletonBuffer<T>
where T: Clone + Send + Sync + 'static {
where
T: Clone + Send + Sync + 'static,
{
value: Arc<RwLock<T>>,
cast: Arc<RwLock<ObserverBroadcast<dyn SingletonView<Item = T>>>>
cast: Arc<RwLock<ObserverBroadcast<dyn SingletonView<Item = T>>>>,
}
impl<T> SingletonBuffer<T>
where T: Clone + Send + Sync + 'static {
pub fn new(
value: T,
port: InnerViewPort<dyn SingletonView<Item = T>>
) -> Self {
where
T: Clone + Send + Sync + 'static,
{
pub fn new(value: T, port: InnerViewPort<dyn SingletonView<Item = T>>) -> Self {
let value = Arc::new(RwLock::new(value));
port.set_view(Some(Arc::new(SingletonBufferView(value.clone()))));
SingletonBuffer {
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> {
MutableSingletonAccess {
buf: self.clone(),
val: self.get()
val: self.get(),
}
}
@ -79,13 +79,17 @@ where T: Clone + Send + Sync + 'static {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct MutableSingletonAccess<T>
where T: Clone + Send + Sync + 'static {
where
T: Clone + Send + Sync + 'static,
{
buf: SingletonBuffer<T>,
val: T,
}
impl<T> Deref for MutableSingletonAccess<T>
where T: Clone + Send + Sync + 'static {
where
T: Clone + Send + Sync + 'static,
{
type Target = T;
fn deref(&self) -> &T {
@ -94,17 +98,19 @@ where T: Clone + Send + Sync + 'static {
}
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 {
&mut self.val
}
}
impl<T> Drop for MutableSingletonAccess<T>
where T: Clone + Send + Sync + 'static {
where
T: Clone + Send + Sync + 'static,
{
fn drop(&mut self) {
self.buf.set(self.val.clone());
}
}

View file

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

View file

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

View file

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

View file

@ -1,30 +1,32 @@
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::RwLock,
termion::event::{Key, Event},
crate::{
core::{ViewPort, OuterViewPort},
singleton::{SingletonView, SingletonBuffer},
sequence::{SequenceView},
terminal::{TerminalView, TerminalStyle, TerminalEvent, TerminalEditor, TerminalEditorResult},
list::{ListEditor, sexpr::ListDecoration},
tree_nav::{TreeNav, TreeNavResult, TreeCursor}
}
termion::event::{Event, Key},
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct CharEditor {
data: SingletonBuffer<Option<char>>,
data_port: ViewPort<dyn SingletonView<Item = Option<char>>>
data_port: ViewPort<dyn SingletonView<Item = Option<char>>>,
}
impl CharEditor {
pub fn new() -> Self {
let mut data_port = ViewPort::new();
let data_port = ViewPort::new();
CharEditor {
data: SingletonBuffer::new(None, data_port.inner()),
data_port
data_port,
}
}
@ -36,28 +38,26 @@ impl CharEditor {
impl TreeNav for CharEditor {}
impl TerminalEditor for CharEditor {
fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> {
crate::terminal::make_label(
&if let Some(c) = self.data.get() {
c.to_string()
} else {
"".to_string()
})
crate::terminal::make_label(&if let Some(c) = self.data.get() {
c.to_string()
} else {
"".to_string()
})
}
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
match event {
TerminalEvent::Input(Event::Key(Key::Char('\n'))) =>
TerminalEditorResult::Continue,
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => TerminalEditorResult::Continue,
TerminalEvent::Input(Event::Key(Key::Char(c))) => {
self.data.set(Some(*c));
TerminalEditorResult::Exit
}
TerminalEvent::Input(Event::Key(Key::Backspace)) |
TerminalEvent::Input(Event::Key(Key::Delete)) => {
TerminalEvent::Input(Event::Key(Key::Backspace))
| TerminalEvent::Input(Event::Key(Key::Delete)) => {
self.data.set(None);
TerminalEditorResult::Exit
}
_ => TerminalEditorResult::Continue
_ => TerminalEditorResult::Continue,
}
}
}
@ -65,41 +65,52 @@ impl TerminalEditor for CharEditor {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct StringEditor {
chars_editor: ListEditor< CharEditor,
Box<dyn Fn() -> Arc<RwLock<CharEditor>> + Send + Sync + 'static> >
chars_editor:
ListEditor<CharEditor, Box<dyn Fn() -> Arc<RwLock<CharEditor>> + Send + Sync + 'static>>,
}
impl StringEditor {
pub fn new() -> Self {
StringEditor {
chars_editor: ListEditor::new(
Box::new(
move || {
Arc::new(RwLock::new(CharEditor::new()))
}
),
crate::list::ListEditorStyle::String
)
Box::new(move || Arc::new(RwLock::new(CharEditor::new()))),
crate::list::ListEditorStyle::String,
),
}
}
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = char>> {
self.chars_editor.get_data_port()
.map(
|char_editor| char_editor.read().unwrap().data.get().unwrap()
)
self.chars_editor
.get_data_port()
.map(|char_editor| char_editor.read().unwrap().data.get().unwrap())
}
}
impl TreeNav for StringEditor {
fn get_cursor(&self) -> TreeCursor { self.chars_editor.get_cursor() }
fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { self.chars_editor.goto(cur) }
fn goto_home(&mut self) -> TreeNavResult { 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 }
fn get_cursor(&self) -> TreeCursor {
self.chars_editor.get_cursor()
}
fn goto(&mut self, cur: TreeCursor) -> TreeNavResult {
self.chars_editor.goto(cur)
}
fn goto_home(&mut self) -> TreeNavResult {
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 {
@ -109,10 +120,7 @@ impl TerminalEditor for StringEditor {
.decorate("\"", "\"", "", 1)
.to_grid_horizontal()
.flatten()
.map_item(
|_idx, atom|
atom.add_style_back(TerminalStyle::fg_color((120, 200, 10)))
)
.map_item(|_idx, atom| atom.add_style_back(TerminalStyle::fg_color((120, 200, 10))))
}
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
@ -121,8 +129,7 @@ impl TerminalEditor for StringEditor {
self.chars_editor.up();
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 {
std::{
sync::{Arc, RwLock},
pin::Pin,
fs::File,
os::unix::io::FromRawFd
},
std::io::Read,
//async_std::{io::{Read, ReadExt}},
crate::{
core::{View, InnerViewPort, OuterViewPort, ViewPort, Observer, ObserverBroadcast},
core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View, ViewPort},
index::{buffer::IndexBuffer, IndexArea, IndexView},
projection::ProjectionHelper,
terminal::{
TerminalAtom,
TerminalStyle,
TerminalView
},
singleton::{
SingletonBuffer,
SingletonView
},
index::{
buffer::IndexBuffer,
IndexView,
IndexArea
}
singleton::{SingletonBuffer, SingletonView},
terminal::{TerminalAtom, TerminalStyle, TerminalView},
},
cgmath::{Vector2, Point2},
vte::{Params, Parser, Perform}
cgmath::{Point2, Vector2},
std::io::Read,
std::sync::{Arc, RwLock},
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 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),
magenta: (118, 38, 113),
cyan: (44, 181, 233),
white: (204, 204, 204)
white: (204, 204, 204),
},
pty_proj: PtyView::new(
_pty_proj: PtyView::new(
buf_port.outer(),
cursor_port.outer().map(|x| Some(x)),
offset_port.outer().map(|x| Some(x)),
size_port.outer().map(|x| Some(x)),
port
)
port,
),
};
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] {
statemachine.advance(&mut performer, *byte);
}
},
Err(err) => {
}
Err(_err) => {
//println!("err: {}", err);
break;
},
}
}
}
}
@ -93,14 +80,22 @@ enum TTYColor {
Rgb(u8, u8, u8),
// 3-Bit/4-Bit colors
Black, LightBlack,
Red, LightRed,
Green, LightGreen,
Yellow, LightYellow,
Blue, LightBlue,
Magenta,LightMagenta,
Cyan, LightCyan,
White, LightWhite,
Black,
LightBlack,
Red,
LightRed,
Green,
LightGreen,
Yellow,
LightYellow,
Blue,
LightBlue,
Magenta,
LightMagenta,
Cyan,
LightCyan,
White,
LightWhite,
}
struct ColorPalett {
@ -117,7 +112,7 @@ struct ColorPalett {
impl ColorPalett {
fn get_rgb(&self, col: &TTYColor) -> (u8, u8, u8) {
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::Red | TTYColor::LightRed => self.red,
TTYColor::Green | TTYColor::LightGreen => self.green,
@ -146,7 +141,7 @@ struct PtyView {
max_pt: Point2<i16>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
proj_helper: ProjectionHelper<usize, Self>
proj_helper: ProjectionHelper<usize, Self>,
}
impl View for PtyView {
@ -160,13 +155,16 @@ impl IndexView<Point2<i16>> for PtyView {
let atom = self.buf.get(&(pt + self.old_offset));
if self.old_curpos == *pt {
if let Some(mut a) = atom {
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 bg_col = a.style.fg_color.unwrap_or((255, 255, 255));
let fg_col = a.style.bg_color.unwrap_or((0, 0, 0));
a.style.fg_color = Some(fg_col);
a.style.bg_color = Some(bg_col);
Some(a)
} else {
Some(TerminalAtom::new(' ', TerminalStyle::bg_color((255, 255, 255))))
Some(TerminalAtom::new(
' ',
TerminalStyle::bg_color((255, 255, 255)),
))
}
} else {
atom
@ -174,10 +172,13 @@ impl IndexView<Point2<i16>> for PtyView {
}
fn area(&self) -> IndexArea<Point2<i16>> {
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.y, self.max_pt.y)
))
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.y, self.max_pt.y),
),
)
}
}
@ -188,85 +189,67 @@ impl PtyView {
offset_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>> {
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
let proj = Arc::new(RwLock::new(
PtyView {
old_curpos: Point2::new(0, 0),
old_size: Vector2::new(0, 0),
old_offset: Vector2::new(0, 0),
max_pt: Point2::new(0, 0),
let proj = Arc::new(RwLock::new(PtyView {
old_curpos: Point2::new(0, 0),
old_size: Vector2::new(0, 0),
old_offset: Vector2::new(0, 0),
max_pt: Point2::new(0, 0),
curpos: proj_helper.new_singleton_arg(
0,
curpos_port,
|s: &mut Self, _msg| {
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 ]));
}),
curpos: proj_helper.new_singleton_arg(0, curpos_port, |s: &mut Self, _msg| {
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(
1,
offset_port,
|s: &mut Self, _msg| {
// todo
let new_offset = s.offset.get().unwrap_or(Vector2::new(0, 0));
if s.old_offset != new_offset {
s.old_offset = new_offset;
s.cast.notify(&s.area());
}
}),
size: proj_helper.new_singleton_arg(
2,
size_port,
|s: &mut Self, _msg| {
let new_size = s.size.get().unwrap_or(Vector2::new(0, 0));
if s.old_size != new_size {
s.old_size = new_size;
s.cast.notify(&s.area());
}
}),
buf: proj_helper.new_index_arg(
3,
buf_port,
|s: &mut Self, area| {
let size = s.old_size;
let area = area.map(
|pt| {
*pt - s.old_offset
}
);
if s.max_pt.x < size.x || s.max_pt.y < size.y {
match &area {
IndexArea::Empty => {}
IndexArea::Full => {}
IndexArea::Range(_) => {}
IndexArea::Set(v) => {
let mx = v.iter().map(|pt| pt.x).max().unwrap_or(0);
if mx > s.max_pt.x && mx < size.x {
s.max_pt.x = mx;
}
let my = v.iter().map(|pt| pt.y).max().unwrap_or(0);
if my > s.max_pt.y && my < size.y {
s.max_pt.y = my;
}
}
}
}
s.cast.notify(&area);
}),
cast: out_port.get_broadcast(),
proj_helper
offset: proj_helper.new_singleton_arg(1, offset_port, |s: &mut Self, _msg| {
// todo
let new_offset = s.offset.get().unwrap_or(Vector2::new(0, 0));
if s.old_offset != new_offset {
s.old_offset = new_offset;
s.cast.notify(&s.area());
}
));
}),
size: proj_helper.new_singleton_arg(2, size_port, |s: &mut Self, _msg| {
let new_size = s.size.get().unwrap_or(Vector2::new(0, 0));
if s.old_size != new_size {
s.old_size = new_size;
s.cast.notify(&s.area());
}
}),
buf: proj_helper.new_index_arg(3, buf_port, |s: &mut Self, area| {
let size = s.old_size;
let area = area.map(|pt| *pt - s.old_offset);
if s.max_pt.x < size.x || s.max_pt.y < size.y {
match &area {
IndexArea::Empty => {}
IndexArea::Full => {}
IndexArea::Range(_) => {}
IndexArea::Set(v) => {
let mx = v.iter().map(|pt| pt.x).max().unwrap_or(0);
if mx > s.max_pt.x && mx < size.x {
s.max_pt.x = mx;
}
let my = v.iter().map(|pt| pt.y).max().unwrap_or(0);
if my > s.max_pt.y && my < size.y {
s.max_pt.y = my;
}
}
}
}
s.cast.notify(&area);
}),
cast: out_port.get_broadcast(),
proj_helper,
}));
proj.write().unwrap().proj_helper.set_proj(&proj);
out_port.set_view(Some(proj.clone()));
@ -288,12 +271,12 @@ struct PerfAtom {
colors: ColorPalett,
pty_proj: Arc<RwLock<PtyView>>
_pty_proj: Arc<RwLock<PtyView>>,
}
impl PerfAtom {
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);
} else {
self.buf.remove(pos);
@ -310,11 +293,15 @@ impl PerfAtom {
}
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) {
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) {
@ -322,7 +309,7 @@ impl PerfAtom {
let mut c = self.cursor.get_mut();
c.x = 0;
if c.y+1 >= size.y {
if c.y + 1 >= size.y {
self.scroll_up(1);
} else {
c.y += 1;
@ -365,14 +352,14 @@ impl PerfAtom {
c.y += n as i16;
} else {
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);
}
}
fn cursor_pxev(&mut self, n: usize) {
let mut c = self.cursor.get_mut();
let s = self.size.get();
let _s = self.size.get();
if c.y - (n as i16) >= 0 {
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");
}
@ -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!(
"[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);
*/
@ -456,7 +443,7 @@ impl Perform for PerfAtom {
//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);
match params[0] {
@ -465,97 +452,99 @@ impl Perform for PerfAtom {
// Reset background color
b"111" => self.set_bg_color(&TTYColor::Black),
// 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();
match c {
// Set SGR
'm' => while let Some(n) = piter.next() {
match n[0] {
0 => {
self.cursty = TerminalStyle::default();
self.curinv = false;
'm' => {
while let Some(n) = piter.next() {
match n[0] {
0 => {
self.cursty = TerminalStyle::default();
self.curinv = false;
}
1 => self.cursty = self.cursty.add(TerminalStyle::bold(true)),
3 => self.cursty = self.cursty.add(TerminalStyle::italic(true)),
4 => self.cursty = self.cursty.add(TerminalStyle::underline(true)),
7 => self.curinv = true,
27 => self.curinv = false,
30 => self.set_fg_color(&TTYColor::Black),
40 => self.set_bg_color(&TTYColor::Black),
90 => self.set_fg_color(&TTYColor::LightBlack),
100 => self.set_bg_color(&TTYColor::LightBlack),
31 => self.set_fg_color(&TTYColor::Red),
41 => self.set_bg_color(&TTYColor::Red),
91 => self.set_fg_color(&TTYColor::LightRed),
101 => self.set_bg_color(&TTYColor::LightRed),
32 => self.set_fg_color(&TTYColor::Green),
42 => self.set_bg_color(&TTYColor::Green),
92 => self.set_fg_color(&TTYColor::LightGreen),
102 => self.set_bg_color(&TTYColor::LightGreen),
33 => self.set_fg_color(&TTYColor::Yellow),
43 => self.set_bg_color(&TTYColor::Yellow),
93 => self.set_fg_color(&TTYColor::LightYellow),
103 => self.set_bg_color(&TTYColor::LightYellow),
34 => self.set_fg_color(&TTYColor::Blue),
44 => self.set_bg_color(&TTYColor::Blue),
94 => self.set_fg_color(&TTYColor::LightBlue),
104 => self.set_bg_color(&TTYColor::LightBlue),
35 => self.set_fg_color(&TTYColor::Magenta),
45 => self.set_bg_color(&TTYColor::Magenta),
95 => self.set_fg_color(&TTYColor::LightMagenta),
105 => self.set_bg_color(&TTYColor::LightMagenta),
36 => self.set_fg_color(&TTYColor::Cyan),
46 => self.set_bg_color(&TTYColor::Cyan),
96 => self.set_fg_color(&TTYColor::LightCyan),
106 => self.set_bg_color(&TTYColor::LightCyan),
37 => self.set_fg_color(&TTYColor::White),
47 => self.set_bg_color(&TTYColor::White),
97 => self.set_fg_color(&TTYColor::LightWhite),
107 => self.set_bg_color(&TTYColor::LightWhite),
38 => {
let x = piter.next().unwrap();
match x[0] {
2 => {
let r = piter.next().unwrap()[0] as u8;
let g = piter.next().unwrap()[0] as u8;
let b = piter.next().unwrap()[0] as u8;
self.set_fg_color(&TTYColor::Rgb(r, g, b));
}
5 => {
let v = piter.next().unwrap();
let rgb = ansi_colours::rgb_from_ansi256(v[0] as u8);
self.set_fg_color(&TTYColor::Rgb(rgb.0, rgb.1, rgb.2));
}
_ => {}
}
}
48 => {
let x = piter.next().unwrap();
match x[0] {
2 => {
let r = piter.next().unwrap()[0] as u8;
let g = piter.next().unwrap()[0] as u8;
let b = piter.next().unwrap()[0] as u8;
self.set_bg_color(&TTYColor::Rgb(r, g, b));
}
5 => {
let v = piter.next().unwrap();
let rgb = ansi_colours::rgb_from_ansi256(v[0] as u8);
self.set_bg_color(&TTYColor::Rgb(rgb.0, rgb.1, rgb.2));
}
_ => {}
}
}
_ => {}
}
1 => self.cursty = self.cursty.add(TerminalStyle::bold(true)),
3 => self.cursty = self.cursty.add(TerminalStyle::italic(true)),
4 => self.cursty = self.cursty.add(TerminalStyle::underline(true)),
7 => self.curinv = true,
27 => self.curinv = false,
30 => self.set_fg_color(&TTYColor::Black),
40 => self.set_bg_color(&TTYColor::Black),
90 => self.set_fg_color(&TTYColor::LightBlack),
100 => self.set_bg_color(&TTYColor::LightBlack),
31 => self.set_fg_color(&TTYColor::Red),
41 => self.set_bg_color(&TTYColor::Red),
91 => self.set_fg_color(&TTYColor::LightRed),
101 => self.set_bg_color(&TTYColor::LightRed),
32 => self.set_fg_color(&TTYColor::Green),
42 => self.set_bg_color(&TTYColor::Green),
92 => self.set_fg_color(&TTYColor::LightGreen),
102 => self.set_bg_color(&TTYColor::LightGreen),
33 => self.set_fg_color(&TTYColor::Yellow),
43 => self.set_bg_color(&TTYColor::Yellow),
93 => self.set_fg_color(&TTYColor::LightYellow),
103 => self.set_bg_color(&TTYColor::LightYellow),
34 => self.set_fg_color(&TTYColor::Blue),
44 => self.set_bg_color(&TTYColor::Blue),
94 => self.set_fg_color(&TTYColor::LightBlue),
104 => self.set_bg_color(&TTYColor::LightBlue),
35 => self.set_fg_color(&TTYColor::Magenta),
45 => self.set_bg_color(&TTYColor::Magenta),
95 => self.set_fg_color(&TTYColor::LightMagenta),
105 => self.set_bg_color(&TTYColor::LightMagenta),
36 => self.set_fg_color(&TTYColor::Cyan),
46 => self.set_bg_color(&TTYColor::Cyan),
96 => self.set_fg_color(&TTYColor::LightCyan),
106 => self.set_bg_color(&TTYColor::LightCyan),
37 => self.set_fg_color(&TTYColor::White),
47 => self.set_bg_color(&TTYColor::White),
97 => self.set_fg_color(&TTYColor::LightWhite),
107 => self.set_bg_color(&TTYColor::LightWhite),
38 => {
let x = piter.next().unwrap();
match x[0] {
2 => {
let r = piter.next().unwrap()[0] as u8;
let g = piter.next().unwrap()[0] as u8;
let b = piter.next().unwrap()[0] as u8;
self.set_fg_color(&TTYColor::Rgb(r,g,b));
},
5 => {
let v = piter.next().unwrap();
let rgb = ansi_colours::rgb_from_ansi256(v[0] as u8);
self.set_fg_color(&TTYColor::Rgb(rgb.0, rgb.1, rgb.2));
},
_ => {}
}
},
48 => {
let x = piter.next().unwrap();
match x[0] {
2 => {
let r = piter.next().unwrap()[0] as u8;
let g = piter.next().unwrap()[0] as u8;
let b = piter.next().unwrap()[0] as u8;
self.set_bg_color(&TTYColor::Rgb(r,g,b));
},
5 => {
let v = piter.next().unwrap();
let rgb = ansi_colours::rgb_from_ansi256(v[0] as u8);
self.set_bg_color(&TTYColor::Rgb(rgb.0, rgb.1, rgb.2));
},
_ => {}
}
},
_ => {}
}
}
'@' => {
@ -564,8 +553,12 @@ impl Perform for PerfAtom {
self.print(' ');
}
}
'A' => { self.cursor_up(piter.next().unwrap_or(&[1])[0] as usize); }
'B' => { self.cursor_dn(piter.next().unwrap_or(&[1])[0] as usize); }
'A' => {
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' => {
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();
c.x = 0;
c.y -= piter.next().unwrap_or(&[1])[0] as i16;
}
'G' | '`' => {
self.cursor.get_mut().x = piter.next().unwrap_or(&[1])[0] as i16 - 1;
@ -600,7 +592,6 @@ impl Perform for PerfAtom {
'J' => {
let x = piter.next().unwrap_or(&[0 as u16; 1]);
match x[0] {
// clear from cursor until end of screen
0 => {
let mut pos = self.cursor.get();
@ -613,7 +604,7 @@ impl Perform for PerfAtom {
pos.y += 1;
}
}
},
}
// clear from cursor to begin
1 => {
@ -633,8 +624,8 @@ impl Perform for PerfAtom {
// erase entire screen
2 => {
for y in 0 .. 100 {
for x in 0 .. self.size.get().x {
for y in 0..100 {
for x in 0..self.size.get().x {
self.write_atom(Point2::new(x, y), None);
}
}
@ -649,30 +640,38 @@ impl Perform for PerfAtom {
'K' => {
let x = piter.next().unwrap_or(&[0]);
match x[0] {
// clear from cursor until end of line
0 => {
let c = self.cursor.get();
for x in c.x .. self.size.get().x {
self.write_atom(Point2::new(x, c.y), Some(TerminalAtom::new(' ', self.get_style())));
for x in c.x..self.size.get().x {
self.write_atom(
Point2::new(x, c.y),
Some(TerminalAtom::new(' ', self.get_style())),
);
}
},
}
// clear from start of line until cursor
1 => {
let c = self.cursor.get();
for x in 0 .. c.x {
self.write_atom(Point2::new(x, c.y), Some(TerminalAtom::new(' ', self.get_style())));
for x in 0..c.x {
self.write_atom(
Point2::new(x, c.y),
Some(TerminalAtom::new(' ', self.get_style())),
);
}
},
}
// clear entire line
2 => {
let c = self.cursor.get();
for x in 0 .. self.size.get().x {
self.write_atom(Point2::new(x, c.y), Some(TerminalAtom::new(' ', self.get_style())));
for x in 0..self.size.get().x {
self.write_atom(
Point2::new(x, c.y),
Some(TerminalAtom::new(' ', self.get_style())),
);
}
},
}
// invalid
_ => {}
@ -685,80 +684,89 @@ impl Perform for PerfAtom {
'M' => {
//eprintln!("delete lines");
/*
let n = piter.next().unwrap_or(&[1])[0] as i16;
for y in 0 .. n {
for x in 0 .. self.size.get().x {
self.write_atom(Point2::new(x, self.cursor.y+y), None);
}
}
*/
let n = piter.next().unwrap_or(&[1])[0] as i16;
for y in 0 .. n {
for x in 0 .. self.size.get().x {
self.write_atom(Point2::new(x, self.cursor.y+y), None);
}
}
*/
}
/*
'P' => {
for x in 0 .. piter.next().unwrap_or(&[1])[0] {
self.backspace();
}
}
*/
'P' => {
for x in 0 .. piter.next().unwrap_or(&[1])[0] {
self.backspace();
}
}
*/
'X' => {
//eprintln!("delete chars");
let c = self.cursor.get();
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())));
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())),
);
}
}
'S' => { self.scroll_up(piter.next().unwrap_or(&[1])[0] as usize); }
'T' => { self.scroll_dn(piter.next().unwrap_or(&[1])[0] as usize); }
's' => { self.save_cursor_position(); }
'u' => { self.restore_cursor_position(); }
'S' => {
self.scroll_up(piter.next().unwrap_or(&[1])[0] as usize);
}
'T' => {
self.scroll_dn(piter.next().unwrap_or(&[1])[0] as usize);
}
's' => {
self.save_cursor_position();
}
'u' => {
self.restore_cursor_position();
}
_ => {
/*
eprintln!(
"[csi_dispatch] params={:#?}, intermediates={:?}, ignore={:?}, char={:?}",
params, intermediates, ignore, c
);
*/
eprintln!(
"[csi_dispatch] params={:#?}, intermediates={:?}, ignore={:?}, char={:?}",
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) {
//(b'B', intermediates) => configure_charset!(StandardCharset::Ascii, intermediates),
(b'D', []) => self.linefeed(),
(b'E', []) => {
self.linefeed();
self.carriage_return();
},
}
/*
(b'H', []) => self.handler.set_horizontal_tabstop(),
(b'M', []) => self.handler.reverse_index(),
(b'Z', []) => self.handler.identify_terminal(None),
(b'c', []) => self.handler.reset_state(),
(b'0', intermediates) => {
configure_charset!(StandardCharset::SpecialCharacterAndLineDrawing, intermediates)
},
*/
(b'H', []) => self.handler.set_horizontal_tabstop(),
(b'M', []) => self.handler.reverse_index(),
(b'Z', []) => self.handler.identify_terminal(None),
(b'c', []) => self.handler.reset_state(),
(b'0', intermediates) => {
configure_charset!(StandardCharset::SpecialCharacterAndLineDrawing, intermediates)
},
*/
(b'7', []) => self.save_cursor_position(),
//(b'8', [b'#']) => self.handler.decaln(),
(b'8', []) => self.restore_cursor_position(),
/*
(b'=', []) => self.handler.set_keypad_application_mode(),
(b'>', []) => self.handler.unset_keypad_application_mode(),
**/
/*
(b'=', []) => self.handler.set_keypad_application_mode(),
(b'>', []) => self.handler.unset_keypad_application_mode(),
**/
// String terminator, do nothing (parser handles as string terminator).
(b'\\', []) => (),
_ => {
/*
eprintln!(
"unhandled esc_dispatch intermediates={:?}, ignore={:?}, byte={:02x}",
intermediates, ignore, byte
);
*/
eprintln!(
"unhandled esc_dispatch intermediates={:?}, ignore={:?}, byte={:02x}",
intermediates, ignore, byte
);
*/
}
}
}
}

View file

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

View file

@ -1,15 +1,13 @@
use {
std::{
sync::{Arc}
},
std::sync::RwLock,
cgmath::Point2,
crate::{
core::{InnerViewPort, OuterViewPort, View, Observer, ObserverBroadcast},
core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View},
index::{IndexArea, IndexView},
projection::ProjectionHelper,
terminal::{TerminalAtom, TerminalView},
projection::ProjectionHelper
}
},
cgmath::Point2,
std::sync::Arc,
std::sync::RwLock,
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -17,22 +15,18 @@ use {
pub struct TerminalCompositor {
layers: Vec<Arc<dyn TerminalView>>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
proj_helper: ProjectionHelper<usize, Self>
proj_helper: ProjectionHelper<usize, Self>,
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl TerminalCompositor {
pub fn new(
port: InnerViewPort<dyn TerminalView>
) -> Arc<RwLock<Self>> {
let comp = Arc::new(RwLock::new(
TerminalCompositor {
layers: Vec::new(),
cast: port.get_broadcast(),
proj_helper: ProjectionHelper::new(port.0.update_hooks.clone())
}
));
pub fn new(port: InnerViewPort<dyn TerminalView>) -> Arc<RwLock<Self>> {
let comp = Arc::new(RwLock::new(TerminalCompositor {
layers: Vec::new(),
cast: port.get_broadcast(),
proj_helper: ProjectionHelper::new(port.0.update_hooks.clone()),
}));
comp.write().unwrap().proj_helper.set_proj(&comp);
port.set_view(Some(comp.clone()));
@ -43,13 +37,10 @@ impl TerminalCompositor {
pub fn push(&mut self, v: OuterViewPort<dyn TerminalView>) {
let idx = self.layers.len();
self.layers.push(
self.proj_helper.new_index_arg(
idx,
v,
|s: &mut Self, area| {
self.proj_helper
.new_index_arg(idx, v, |s: &mut Self, area| {
s.cast.notify(area);
}
)
}),
);
}
}
@ -87,4 +78,3 @@ impl IndexView<Point2<i16>> for TerminalCompositor {
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 atom;
pub mod compositor;
pub mod style;
pub mod terminal;
pub use {
style::{TerminalStyle},
atom::{TerminalAtom},
terminal::{Terminal, TerminalEvent},
atom::TerminalAtom,
compositor::TerminalCompositor,
style::TerminalStyle,
terminal::{Terminal, TerminalEvent},
};
use {
crate::{
grid::GridView
}
};
use crate::grid::GridView;
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -25,7 +21,7 @@ pub trait TerminalView = GridView<Item = TerminalAtom>;
pub enum TerminalEditorResult {
Continue,
Exit
Exit,
}
pub trait TerminalEditor {
@ -37,25 +33,25 @@ pub trait TerminalEditor {
use {
crate::{
core::{OuterViewPort, ViewPort},
vec::VecBuffer,
core::{ViewPort, OuterViewPort}
},
cgmath::Point2
cgmath::Point2,
};
pub fn make_label(s: &str) -> OuterViewPort<dyn TerminalView> {
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()
.map(|c| TerminalAtom::from(c))
.to_index()
.map_key(
|idx| Point2::new(*idx as i16, 0),
|pt| if pt.y == 0 { Some(pt.x as usize) } else { None }
|pt| if pt.y == 0 { Some(pt.x as usize) } else { None },
);
v
}

View file

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

View file

@ -1,44 +1,32 @@
use {
std::{
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}
},
super::{TerminalStyle, TerminalView},
crate::{
core::{
OuterViewPort,
Observer,
channel::{
ChannelReceiver,
ChannelSender,
queue_channel,
set_channel
}
channel::{queue_channel, set_channel, ChannelReceiver, ChannelSender},
Observer, OuterViewPort,
},
index::{IndexArea},
grid::{GridWindowIterator}
grid::GridWindowIterator,
index::IndexArea,
},
super::{
TerminalStyle,
TerminalView
async_std::{stream::StreamExt, task},
cgmath::{Point2, Vector2},
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 {
Resize(Vector2<i16>),
Input(termion::event::Event)
Input(termion::event::Event),
}
pub struct Terminal {
@ -46,24 +34,22 @@ pub struct Terminal {
_observer: Arc<RwLock<TermOutObserver>>,
events: ChannelReceiver<Vec<TerminalEvent>>,
_signal_handle: signal_hook_async_std::Handle
_signal_handle: signal_hook_async_std::Handle,
}
impl Terminal {
pub fn new(
port: OuterViewPort<dyn TerminalView>
) -> Self {
pub fn new(port: OuterViewPort<dyn TerminalView>) -> Self {
let (dirty_pos_tx, dirty_pos_rx) = set_channel();
let writer = Arc::new(TermOutWriter {
out: RwLock::new(MouseTerminal::from(stdout().into_raw_mode().unwrap())),
dirty_pos_rx,
view: port.get_view_arc()
view: port.get_view_arc(),
});
let observer = Arc::new(RwLock::new(TermOutObserver {
dirty_pos_tx,
writer: writer.clone()
writer: writer.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)));
// 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();
task::spawn(async move {
@ -90,9 +76,9 @@ impl Terminal {
while let Some(signal) = signals.next().await {
match signal {
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)));
},
}
_ => unreachable!(),
}
}
@ -102,7 +88,7 @@ impl Terminal {
writer,
_observer: observer,
events: event_rx,
_signal_handle: handle
_signal_handle: handle,
}
}
@ -117,16 +103,18 @@ impl Terminal {
struct TermOutObserver {
dirty_pos_tx: ChannelSender<HashSet<Point2<i16>>>,
writer: Arc<TermOutWriter>
writer: Arc<TermOutWriter>,
}
impl TermOutObserver {
fn send_area(&mut self, area: IndexArea<Point2<i16>>) {
match area {
IndexArea::Empty => {},
IndexArea::Empty => {}
IndexArea::Full => {
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);
}
}
@ -160,7 +148,7 @@ impl Observer<dyn TerminalView> for TermOutObserver {
pub struct TermOutWriter {
out: RwLock<MouseTerminal<termion::raw::RawTerminal<std::io::Stdout>>>,
dirty_pos_rx: ChannelReceiver<HashSet<Point2<i16>>>,
view: Arc<RwLock<Option<Arc<dyn TerminalView>>>>
view: Arc<RwLock<Option<Arc<dyn TerminalView>>>>,
}
impl TermOutWriter {
@ -173,36 +161,45 @@ impl TermOutWriter {
impl TermOutWriter {
pub async fn show(&self) -> std::io::Result<()> {
// init
write!(self.out.write().unwrap(), "{}{}{}",
termion::cursor::Hide,
termion::cursor::Goto(1, 1),
termion::style::Reset)?;
write!(
self.out.write().unwrap(),
"{}{}{}",
termion::cursor::Hide,
termion::cursor::Goto(1, 1),
termion::style::Reset
)?;
let mut cur_pos = Point2::<i16>::new(0, 0);
let mut cur_style = TerminalStyle::default();
// draw atoms until view port is destroyed
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() {
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<_>>();
/*
d.sort_by(|a,b| {
if a.y < b.y {
std::cmp::Ordering::Less
} else if a.y == b.y {
a.x.cmp(&b.x)
} else {
std::cmp::Ordering::Greater
}
});
*/
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| {
if a.y < b.y {
std::cmp::Ordering::Less
} else if a.y == b.y {
a.x.cmp(&b.x)
} else {
std::cmp::Ordering::Greater
}
});
*/
for pos in d {
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) {
@ -232,4 +229,3 @@ impl TermOutWriter {
std::io::Result::Ok(())
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -1,56 +1,71 @@
use {
std::{
sync::Arc,
io::Write
},
std::sync::RwLock,
async_std::{
io::{Read, ReadExt},
stream::{StreamExt}
},
serde::{Serialize, de::DeserializeOwned},
crate::{
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>
where T: Clone + Send + Sync + 'static,
W: Write + Send + Sync {
where
T: Clone + Send + Sync + 'static,
W: Write + Send + Sync,
{
data: Option<Arc<RwLock<Vec<T>>>>,
out: RwLock<W>
out: RwLock<W>,
}
impl<T> OuterViewPort<RwLock<Vec<T>>>
where T: Clone + Serialize + Send + Sync + 'static {
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,
out: RwLock::new(out),
}
));
where
T: Clone + Serialize + Send + Sync + 'static,
{
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,
out: RwLock::new(out),
}));
self.add_observer(writer.clone());
writer
}
}
impl<T, W> Observer<RwLock<Vec<T>>> for VecJsonWriter<T, W>
where T: Clone + Serialize + Send + Sync + 'static,
W: Write + Send + Sync
where
T: Clone + Serialize + Send + Sync + 'static,
W: Write + Send + Sync,
{
fn reset(&mut self, view: Option<Arc<RwLock<Vec<T>>>>) {
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("");
if let Some(data) = self.data.as_ref() {
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("");
}
}
@ -59,14 +74,19 @@ where T: Clone + Serialize + Send + Sync + 'static,
}
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().flush().expect("");
}
}
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) {
let mut bytes = read.bytes();
@ -75,11 +95,12 @@ where T: DeserializeOwned + Clone + Send + Sync + 'static
match b {
b'\n' => {
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);
s.clear();
}
},
}
c => {
s.push(c as char);
}
@ -87,5 +108,3 @@ where T: DeserializeOwned + Clone + Send + Sync + 'static
}
}
}

View file

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

View file

@ -1,52 +1,38 @@
use{
std::sync::{Arc, RwLock},
use {
cgmath::{Point2, Vector2},
nested::{
core::{
View,
ViewPort,
InnerViewPort,
OuterViewPort,
Observer,
ObserverExt,
ObserverBroadcast,
context::{ReprTree, Object, MorphismType, MorphismMode, Context},
port::{UpdateTask}},
core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View},
index::{IndexArea, IndexView},
grid::{GridWindowIterator},
terminal::{
Terminal,
TerminalStyle,
TerminalAtom,
TerminalCompositor,
TerminalEvent,
make_label,
TerminalView,
TerminalEditor},
}
terminal::{TerminalAtom, TerminalView},
},
std::sync::{Arc, RwLock},
};
pub struct AsciiBox {
content: Option<Arc<dyn TerminalView>>,
extent: Vector2<i16>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
}
impl AsciiBox {
pub fn new(
extent: Vector2<i16>,
content_port: OuterViewPort<dyn TerminalView>,
output_port: InnerViewPort<dyn TerminalView>
output_port: InnerViewPort<dyn TerminalView>,
) -> Arc<RwLock<Self>> {
let ascii_box = Arc::new(RwLock::new(AsciiBox {
content: None,
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()));
content_port.add_observer(ascii_box.clone());
@ -57,19 +43,20 @@ impl AsciiBox {
if self.extent != new_extent {
let old_extent = self.extent;
self.extent = new_extent;
self.cast.notify(
&IndexArea::Range(
Point2::new(0, 0) ..=
Point2::new(
1+std::cmp::max(old_extent.x, new_extent.x),
1+std::cmp::max(old_extent.y, new_extent.y))));
self.cast.notify(&IndexArea::Range(
Point2::new(0, 0)
..=Point2::new(
1 + std::cmp::max(old_extent.x, new_extent.x),
1 + std::cmp::max(old_extent.y, new_extent.y),
),
));
}
}
pub fn fit_content(&mut self) {
if let Some(c) = self.content.as_ref() {
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 {
self.resize(Vector2::new(0, 0));
}
@ -96,42 +83,40 @@ impl IndexView<Point2<i16>> for AsciiBox {
type Item = 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
if pt.y == 0 && pt.x == 0 {
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('╮'))
} 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('│'))
} 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('╰'))
} 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('╯'))
} else {
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
if pt.x > 0 && pt.x < self.extent.x+1 {
if pt.x > 0 && pt.x < self.extent.x + 1 {
Some(TerminalAtom::from('─'))
} else {
None
}
} else if
pt.x > 0 &&
pt.y > 0 &&
pt.x < self.extent.x+1 &&
pt.y < self.extent.y+1
{
Some(self.content.get(&(pt - Vector2::new(1, 1))).unwrap_or(TerminalAtom::from(' ')))
} else if pt.x > 0 && pt.y > 0 && pt.x < self.extent.x + 1 && pt.y < self.extent.y + 1 {
Some(
self.content
.get(&(pt - Vector2::new(1, 1)))
.unwrap_or(TerminalAtom::from(' ')),
)
} else {
None
}
}
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;
mod ascii_box;
mod monstera;
mod process;
mod pty;
mod ascii_box;
mod plot;
use{
std::sync::{Arc, RwLock},
use {
crate::process::ProcessLauncher,
cgmath::{Point2, Vector2},
termion::event::{Event, Key},
nested::{
core::{
View,
ViewPort,
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},
core::{port::UpdateTask, Observer, OuterViewPort, ViewPort},
index::IndexArea,
list::{ListCursorMode, ListEditor, ListEditorStyle},
terminal::{
Terminal,
TerminalStyle,
TerminalAtom,
TerminalCompositor,
TerminalEvent,
make_label,
TerminalView,
TerminalEditor,
TerminalEditorResult
make_label, Terminal, TerminalAtom, TerminalCompositor, TerminalEditor,
TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView,
},
string_editor::{StringEditor},
tree_nav::{TreeNav, TreeNavResult, TreeCursor, TerminalTreeEditor},
list::{SExprView, ListCursorMode, ListEditor, ListEditorStyle},
projection::ProjectionHelper
tree_nav::{TerminalTreeEditor, TreeCursor, TreeNavResult},
vec::VecBuffer,
},
crate::{
process::ProcessLauncher
}
std::sync::{Arc, RwLock},
termion::event::{Event, Key},
};
#[async_std::main]
@ -57,223 +33,252 @@ async fn main() {
let mut term = Terminal::new(term_port.outer());
let term_writer = term.get_writer();
async_std::task::spawn(
async move {
let table_port = ViewPort::<dyn nested::grid::GridView<Item = OuterViewPort<dyn TerminalView>>>::new();
let mut table_buf = nested::index::buffer::IndexBuffer::new(table_port.inner());
async_std::task::spawn(async move {
let table_port =
ViewPort::<dyn nested::grid::GridView<Item = OuterViewPort<dyn TerminalView>>>::new();
let mut table_buf = nested::index::buffer::IndexBuffer::new(table_port.inner());
let magic =
make_label("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>")
.map_item(
|pos, atom|
atom.add_style_back(
TerminalStyle::fg_color(
(5,
((80+(pos.x*30)%100) as u8),
(55+(pos.x*15)%180) as u8)
)
)
);
let cur_size_port = ViewPort::new();
let mut cur_size = nested::singleton::SingletonBuffer::new(Vector2::new(10, 10), cur_size_port.inner());
let status_chars_port = ViewPort::new();
let mut status_chars = VecBuffer::new(status_chars_port.inner());
let mut process_list_editor = ListEditor::new(
Box::new(|| {
Arc::new(RwLock::new(
ProcessLauncher::new()
))
}),
ListEditorStyle::VerticalSexpr
);
let plist_vec_port = ViewPort::new();
let mut plist = VecBuffer::new(plist_vec_port.inner());
async_std::task::spawn(async move {
let (w, h) = termion::terminal_size().unwrap();
let mut x : usize = 0;
loop {
let val =
(
5.0 + (x as f32 / 3.0).sin() * 5.0 +
2.0 + ((7+x) as f32 / 5.0).sin() * 2.0 +
2.0 + ((9+x) as f32 / 10.0).cos() * 3.0
) as usize;
if x < w as usize {
plist.push(val);
} else {
*plist.get_mut(x % (w as usize)) = val;
}
x+=1;
async_std::task::sleep(std::time::Duration::from_millis(10)).await;
if x%(w as usize) == 0 {
async_std::task::sleep(std::time::Duration::from_secs(3)).await;
}
}
let magic =
make_label("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>").map_item(|pos, atom| {
atom.add_style_back(TerminalStyle::fg_color((
5,
((80 + (pos.x * 30) % 100) as u8),
(55 + (pos.x * 15) % 180) as u8,
)))
});
let plot_port = ViewPort::new();
let plot = crate::plot::Plot::new(plist_vec_port.outer().to_sequence(), plot_port.inner());
let cur_size_port = ViewPort::new();
let mut cur_size =
nested::singleton::SingletonBuffer::new(Vector2::new(10, 10), cur_size_port.inner());
table_buf.insert_iter(vec![
(Point2::new(0, 0), magic.clone()),
(Point2::new(0, 1), status_chars_port.outer().to_sequence().to_grid_horizontal()),
(Point2::new(0, 2), magic.clone()),
(Point2::new(0, 3), process_list_editor.get_term_view()),
]);
let status_chars_port = ViewPort::new();
let mut status_chars = VecBuffer::new(status_chars_port.inner());
let (w, h) = termion::terminal_size().unwrap();
let mut process_list_editor = ListEditor::new(
Box::new(|| Arc::new(RwLock::new(ProcessLauncher::new()))),
ListEditorStyle::VerticalSexpr,
);
compositor.write().unwrap().push(
plot_port.outer()
.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))
);
compositor.write().unwrap().push(
monstera::make_monstera()
.offset(Vector2::new(w as i16-38, 0)));
compositor.write().unwrap().push(
table_port.outer()
.flatten()
.offset(Vector2::new(3, 0))
);
process_list_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Insert,
tree_addr: vec![ 0 ]
});
let tp = term_port.clone();
async_std::task::spawn(
async move {
loop {
tp.update();
async_std::task::sleep(std::time::Duration::from_millis(10)).await;
}
}
);
let plist_vec_port = ViewPort::new();
let mut plist = VecBuffer::new(plist_vec_port.inner());
async_std::task::spawn(async move {
let (w, _h) = termion::terminal_size().unwrap();
let mut x: usize = 0;
loop {
status_chars.clear();
let cur = process_list_editor.get_cursor();
let val = (5.0
+ (x as f32 / 3.0).sin() * 5.0
+ 2.0
+ ((7 + x) as f32 / 5.0).sin() * 2.0
+ 2.0
+ ((9 + x) as f32 / 10.0).cos() * 3.0) as usize;
if cur.tree_addr.len() > 0 {
status_chars.push(TerminalAtom::new('@', TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true))));
for x in cur.tree_addr {
for c in format!("{}", x).chars() {
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)).add(TerminalStyle::bold(true))));
for c in
match cur.leaf_mode {
ListCursorMode::Insert => "INSERT",
ListCursorMode::Select => "SELECT",
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))));
if x < w as usize {
plist.push(val);
} else {
for c in "Press <DN> to enter".chars() {
status_chars.push(TerminalAtom::new(c, TerminalStyle::fg_color((200, 200, 20))));
}
*plist.get_mut(x % (w as usize)) = val;
}
let ev = term.next_event().await;
x += 1;
async_std::task::sleep(std::time::Duration::from_millis(10)).await;
if let TerminalEvent::Resize(new_size) = ev {
cur_size.set(new_size);
term_port.inner().get_broadcast().notify(&IndexArea::Full);
continue;
if x % (w as usize) == 0 {
async_std::task::sleep(std::time::Duration::from_secs(3)).await;
}
}
});
let plot_port = ViewPort::new();
let _plot = crate::plot::Plot::new(plist_vec_port.outer().to_sequence(), plot_port.inner());
table_buf.insert_iter(vec![
(Point2::new(0, 0), magic.clone()),
(
Point2::new(0, 1),
status_chars_port.outer().to_sequence().to_grid_horizontal(),
),
(Point2::new(0, 2), magic.clone()),
(Point2::new(0, 3), process_list_editor.get_term_view()),
]);
let (w, h) = termion::terminal_size().unwrap();
compositor.write().unwrap().push(
plot_port
.outer()
.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)),
);
compositor
.write()
.unwrap()
.push(monstera::make_monstera().offset(Vector2::new(w as i16 - 38, 0)));
compositor
.write()
.unwrap()
.push(table_port.outer().flatten().offset(Vector2::new(3, 0)));
process_list_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Insert,
tree_addr: vec![0],
});
let tp = term_port.clone();
async_std::task::spawn(async move {
loop {
tp.update();
async_std::task::sleep(std::time::Duration::from_millis(10)).await;
}
});
loop {
status_chars.clear();
let cur = process_list_editor.get_cursor();
if cur.tree_addr.len() > 0 {
status_chars.push(TerminalAtom::new(
'@',
TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true)),
));
for x in cur.tree_addr {
for c in format!("{}", x).chars() {
status_chars
.push(TerminalAtom::new(c, TerminalStyle::fg_color((0, 100, 20))));
}
status_chars.push(TerminalAtom::new(
'.',
TerminalStyle::fg_color((120, 80, 80)),
));
}
if let Some(process_editor) = process_list_editor.get_item() {
let mut pe = process_editor.write().unwrap();
if pe.is_captured() {
if let TerminalEditorResult::Exit = pe.handle_terminal_event(&ev) {
drop(pe);
process_list_editor.up();
process_list_editor.nexd();
}
continue;
}
status_chars.push(TerminalAtom::new(
':',
TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true)),
));
for c in match cur.leaf_mode {
ListCursorMode::Insert => "INSERT",
ListCursorMode::Select => "SELECT",
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)),
));
} else {
for c in "Press <DN> to enter".chars() {
status_chars.push(TerminalAtom::new(
c,
TerminalStyle::fg_color((200, 200, 20)),
));
}
}
match ev {
TerminalEvent::Input(Event::Key(Key::Ctrl('d'))) => break,
TerminalEvent::Input(Event::Key(Key::Ctrl('l'))) => {
process_list_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Insert,
tree_addr: vec![ 0 ]
});
process_list_editor.data.clear();
},
TerminalEvent::Input(Event::Key(Key::Left)) => {
process_list_editor.pxev();
}
TerminalEvent::Input(Event::Key(Key::Right)) => {
let ev = term.next_event().await;
if let TerminalEvent::Resize(new_size) = ev {
cur_size.set(new_size);
term_port.inner().get_broadcast().notify(&IndexArea::Full);
continue;
}
if let Some(process_editor) = process_list_editor.get_item() {
let mut pe = process_editor.write().unwrap();
if pe.is_captured() {
if let TerminalEditorResult::Exit = pe.handle_terminal_event(&ev) {
drop(pe);
process_list_editor.up();
process_list_editor.nexd();
}
TerminalEvent::Input(Event::Key(Key::Up)) => {
if process_list_editor.up() == TreeNavResult::Exit {
process_list_editor.dn();
process_list_editor.goto_home();
}
}
TerminalEvent::Input(Event::Key(Key::Down)) => {
if process_list_editor.dn() == TreeNavResult::Continue {
process_list_editor.goto_home();
}
}
TerminalEvent::Input(Event::Key(Key::Home)) => {
continue;
}
}
match ev {
TerminalEvent::Input(Event::Key(Key::Ctrl('d'))) => break,
TerminalEvent::Input(Event::Key(Key::Ctrl('l'))) => {
process_list_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Insert,
tree_addr: vec![0],
});
process_list_editor.clear();
}
TerminalEvent::Input(Event::Key(Key::Left)) => {
process_list_editor.pxev();
}
TerminalEvent::Input(Event::Key(Key::Right)) => {
process_list_editor.nexd();
}
TerminalEvent::Input(Event::Key(Key::Up)) => {
if process_list_editor.up() == TreeNavResult::Exit {
process_list_editor.dn();
process_list_editor.goto_home();
}
TerminalEvent::Input(Event::Key(Key::End)) => {
process_list_editor.goto_end();
}
TerminalEvent::Input(Event::Key(Key::Down)) => {
if process_list_editor.dn() == TreeNavResult::Continue {
process_list_editor.goto_home();
}
ev => {
if process_list_editor.get_cursor().leaf_mode == ListCursorMode::Select {
match ev {
TerminalEvent::Input(Event::Key(Key::Char('l'))) => { process_list_editor.up(); },
TerminalEvent::Input(Event::Key(Key::Char('a'))) => { process_list_editor.dn(); },
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);
}
}
TerminalEvent::Input(Event::Key(Key::Home)) => {
process_list_editor.goto_home();
}
TerminalEvent::Input(Event::Key(Key::End)) => {
process_list_editor.goto_end();
}
ev => {
if process_list_editor.get_cursor().leaf_mode == ListCursorMode::Select {
match ev {
TerminalEvent::Input(Event::Key(Key::Char('l'))) => {
process_list_editor.up();
}
} else {
if let TerminalEditorResult::Exit = process_list_editor.handle_terminal_event(&ev) {
TerminalEvent::Input(Event::Key(Key::Char('a'))) => {
process_list_editor.dn();
}
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);
}
}
} else {
if let TerminalEditorResult::Exit =
process_list_editor.handle_terminal_event(&ev)
{
process_list_editor.nexd();
}
}
}
}
drop(term);
drop(term_port);
}
);
drop(term);
drop(term_port);
});
term_writer.show().await.expect("output error!");
}

View file

@ -1,18 +1,15 @@
use {
cgmath::Point2,
nested::{
core::{ViewPort, OuterViewPort},
core::{OuterViewPort, ViewPort},
terminal::{make_label, TerminalStyle, TerminalView},
vec::VecBuffer,
terminal::{
TerminalStyle, TerminalView, make_label
},
}
},
};
pub fn make_monstera() -> OuterViewPort<dyn TerminalView> {
let monstera_lines_port = ViewPort::new();
let monstera_lines = VecBuffer::with_data(
let _monstera_lines = VecBuffer::with_data(
vec![
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(" ."),
],
monstera_lines_port.inner()
monstera_lines_port.inner(),
);
monstera_lines_port.outer()
monstera_lines_port
.outer()
.to_sequence()
.to_index()
.map_key(
|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()
.map_item(
|p, at| at.add_style_back(TerminalStyle::fg_color((0,100,10)))
)
.map_item(|_p, at| at.add_style_back(TerminalStyle::fg_color((0, 100, 10))))
}

View file

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

View file

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

View file

@ -1,13 +1,12 @@
use {
std::sync::{Arc, Mutex},
termion::event::{Key, Event},
cgmath::Vector2,
nested::{
core::{InnerViewPort},
singleton::{SingletonView, SingletonBuffer},
terminal::{TerminalView, TerminalEvent, TerminalEditorResult}
}
core::InnerViewPort,
singleton::{SingletonBuffer, SingletonView},
terminal::{TerminalEditorResult, TerminalEvent, TerminalView},
},
std::sync::{Arc, Mutex},
termion::event::{Event, Key},
};
pub use portable_pty::CommandBuilder;
@ -16,15 +15,13 @@ pub use portable_pty::CommandBuilder;
#[derive(Clone)]
pub enum PTYStatus {
Running{ pid: u32 },
Done{ status: portable_pty::ExitStatus }
Running { pid: u32 },
Done { status: portable_pty::ExitStatus },
}
impl Default for PTYStatus {
fn default() -> Self {
PTYStatus::Running {
pid: 0
}
PTYStatus::Running { pid: 0 }
}
}
@ -32,7 +29,7 @@ impl Default for PTYStatus {
pub struct PTY {
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 {
@ -40,51 +37,54 @@ impl PTY {
cmd: portable_pty::CommandBuilder,
max_size: Vector2<i16>,
term_port: InnerViewPort<dyn TerminalView>,
status_port: InnerViewPort<dyn SingletonView<Item = PTYStatus>>
status_port: InnerViewPort<dyn SingletonView<Item = PTYStatus>>,
) -> Option<Self> {
// Create a new pty
let mut pair = portable_pty::native_pty_system().openpty(portable_pty::PtySize {
rows: max_size.y as u16,
cols: max_size.x as u16,
let pair = portable_pty::native_pty_system()
.openpty(portable_pty::PtySize {
rows: max_size.y as u16,
cols: max_size.x as u16,
// Not all systems support pixel_width, pixel_height,
// but it is good practice to set it to something
// that matches the size of the selected font. That
// is more complex than can be shown here in this
// brief example though!
pixel_width: 0,
pixel_height: 0,
}).unwrap();
// Not all systems support pixel_width, pixel_height,
// but it is good practice to set it to something
// that matches the size of the selected font. That
// is more complex than can be shown here in this
// brief example though!
pixel_width: 0,
pixel_height: 0,
})
.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 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));
async_std::task::spawn_blocking(
move || {
nested::terminal::ansi_parser::read_ansi_from(&mut reader, max_size, term_port);
});
async_std::task::spawn_blocking(move || {
nested::terminal::ansi_parser::read_ansi_from(&mut reader, max_size, term_port);
});
async_std::task::spawn_blocking({
let child = child.clone();
move || {
loop {
if let Ok(Some(status)) = child.lock().unwrap().try_wait() {
status_buf.set(PTYStatus::Done{ status });
break;
}
std::thread::sleep(std::time::Duration::from_millis(10));
move || loop {
if let Ok(Some(status)) = child.lock().unwrap().try_wait() {
status_buf.set(PTYStatus::Done { status });
break;
}
std::thread::sleep(std::time::Duration::from_millis(10));
}
});
Some(PTY {
master: Mutex::new(pair.master),
child
child,
})
} else {
None
@ -92,7 +92,7 @@ impl PTY {
}
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 {
@ -100,11 +100,11 @@ impl PTY {
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
self.master.lock().unwrap().write(&[13]).unwrap();
TerminalEditorResult::Continue
},
}
TerminalEvent::Input(Event::Key(Key::Char(c))) => {
write!(self.master.lock().unwrap(), "{}", c);
write!(self.master.lock().unwrap(), "{}", c).unwrap();
TerminalEditorResult::Continue
},
}
TerminalEvent::Input(Event::Key(Key::Esc)) => {
self.master.lock().unwrap().write(&[0x1b]).unwrap();
TerminalEditorResult::Continue
@ -114,37 +114,54 @@ impl PTY {
TerminalEditorResult::Continue
}
TerminalEvent::Input(Event::Key(Key::F(n))) => {
self.master.lock().unwrap().write(&[
0x1b,
0x0a,
match n {
11 => 133,
12 => 134,
n => 58 + n
}
]).unwrap();
self.master
.lock()
.unwrap()
.write(&[
0x1b,
0x0a,
match n {
11 => 133,
12 => 134,
n => 58 + n,
},
])
.unwrap();
TerminalEditorResult::Continue
}
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
}
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
}
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
}
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::Exit
}
_ => TerminalEditorResult::Exit,
}
}
}

View file

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

View file

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