factor out r3vi and shell crates
This commit is contained in:
parent
d43d99c6d3
commit
6f942c8940
83 changed files with 1294 additions and 6389 deletions
14
Cargo.toml
14
Cargo.toml
|
@ -1,12 +1,10 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"nested",
|
||||
"terminal/display_server",
|
||||
"terminal/ansi_parser",
|
||||
"shell",
|
||||
"sdf_editor",
|
||||
"math/str2int",
|
||||
"math/int2str",
|
||||
"math/radix_transform",
|
||||
"math/fib"
|
||||
# "terminal/display_server",
|
||||
# "terminal/ansi_parser",
|
||||
# "math/str2int",
|
||||
# "math/int2str",
|
||||
# "math/radix_transform",
|
||||
# "math/fib"
|
||||
]
|
||||
|
|
|
@ -5,6 +5,7 @@ name = "nested"
|
|||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
r3vi = { git = "https://git.exobiont.de/senvas/r3vi.git" }
|
||||
no_deadlocks = "*"
|
||||
cgmath = { version = "0.18.0", features = ["serde"] }
|
||||
termion = "1.5.5"
|
||||
|
|
|
@ -7,9 +7,9 @@ pub trait Commander {
|
|||
|
||||
use std::sync::{Arc, RwLock};
|
||||
use crate::{
|
||||
type_system::ReprTree,
|
||||
singleton::SingletonView
|
||||
type_system::ReprTree
|
||||
};
|
||||
use r3vi::view::singleton::*;
|
||||
|
||||
pub trait ObjCommander {
|
||||
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>);
|
||||
|
|
|
@ -1,223 +0,0 @@
|
|||
use {
|
||||
crate::core::Observer,
|
||||
async_std::stream::Stream,
|
||||
core::{
|
||||
pin::Pin,
|
||||
task::{Context, Poll, Waker},
|
||||
},
|
||||
std::{
|
||||
collections::HashSet,
|
||||
hash::Hash,
|
||||
sync::{Arc, Mutex},
|
||||
},
|
||||
};
|
||||
|
||||
/*\
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
Traits
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
\*/
|
||||
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,
|
||||
{
|
||||
fn channel_insert(&mut self, x: T) {
|
||||
self.push(x);
|
||||
}
|
||||
}
|
||||
|
||||
/*\
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
Set Channel
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
\*/
|
||||
impl<T> ChannelData for HashSet<T>
|
||||
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,
|
||||
{
|
||||
fn channel_insert(&mut self, x: T) {
|
||||
*self = Some(x);
|
||||
}
|
||||
}
|
||||
|
||||
/*\
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
Channel
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
\*/
|
||||
struct ChannelState<Data: ChannelData> {
|
||||
send_buf: Option<Data>,
|
||||
recv_iter: Option<Data::IntoIter>,
|
||||
num_senders: usize,
|
||||
waker: Option<Waker>,
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub struct ChannelSender<Data: ChannelData>(Arc<Mutex<ChannelState<Data>>>);
|
||||
pub struct ChannelReceiver<Data: ChannelData>(Arc<Mutex<ChannelState<Data>>>);
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl<Data: ChannelData> ChannelSender<Data>
|
||||
where
|
||||
Data::IntoIter: Send + Sync,
|
||||
{
|
||||
pub fn send(&self, msg: Data::Item) {
|
||||
let mut state = self.0.lock().unwrap();
|
||||
|
||||
if state.send_buf.is_none() {
|
||||
state.send_buf = Some(Data::default());
|
||||
}
|
||||
|
||||
state.send_buf.as_mut().unwrap().channel_insert(msg);
|
||||
|
||||
if let Some(waker) = state.waker.take() {
|
||||
waker.wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
{
|
||||
fn notify(&mut self, msg: &V::Msg) {
|
||||
self.send(msg.clone());
|
||||
}
|
||||
}
|
||||
|
||||
impl<Data: ChannelData> Clone for ChannelSender<Data> {
|
||||
fn clone(&self) -> Self {
|
||||
self.0.lock().unwrap().num_senders += 1;
|
||||
ChannelSender(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Data: ChannelData> Drop for ChannelSender<Data> {
|
||||
fn drop(&mut self) {
|
||||
let mut state = self.0.lock().unwrap();
|
||||
state.num_senders -= 1;
|
||||
if let Some(waker) = state.waker.take() {
|
||||
waker.wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl<Data: ChannelData> ChannelReceiver<Data> {
|
||||
pub async fn recv(&self) -> Option<Data> {
|
||||
ChannelRead(self.0.clone()).await
|
||||
}
|
||||
|
||||
pub fn try_recv(&self) -> Option<Data> {
|
||||
let mut state = self.0.lock().unwrap();
|
||||
if let Some(buf) = state.send_buf.take() {
|
||||
Some(buf)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ChannelRead<Data: ChannelData>(Arc<Mutex<ChannelState<Data>>>);
|
||||
impl<Data: ChannelData> std::future::Future for ChannelRead<Data> {
|
||||
type Output = Option<Data>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
let mut state = self.0.lock().unwrap();
|
||||
if let Some(buf) = state.send_buf.take() {
|
||||
Poll::Ready(Some(buf))
|
||||
} else if state.num_senders == 0 {
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
state.waker = Some(cx.waker().clone());
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
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>> {
|
||||
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));
|
||||
} else {
|
||||
state.recv_iter = None
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(send_buf) = state.send_buf.take() {
|
||||
state.recv_iter = Some(send_buf.into_iter());
|
||||
// recv_iter.next() is guaranteed to be Some(x)
|
||||
Poll::Ready(state.recv_iter.as_mut().unwrap().next())
|
||||
} else if state.num_senders == 0 {
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
state.waker = Some(cx.waker().clone());
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*\
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
Factory Functions
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
\*/
|
||||
pub fn channel<Data: ChannelData>() -> (ChannelSender<Data>, ChannelReceiver<Data>) {
|
||||
let state = Arc::new(Mutex::new(ChannelState {
|
||||
send_buf: None,
|
||||
recv_iter: None,
|
||||
num_senders: 1,
|
||||
waker: None,
|
||||
}));
|
||||
|
||||
(ChannelSender(state.clone()), ChannelReceiver(state))
|
||||
}
|
||||
|
||||
pub fn set_channel<T: Eq + Hash + Send + Sync>(
|
||||
) -> (ChannelSender<HashSet<T>>, ChannelReceiver<HashSet<T>>) {
|
||||
channel::<HashSet<T>>()
|
||||
}
|
||||
|
||||
pub fn queue_channel<T: Send + Sync>() -> (ChannelSender<Vec<T>>, ChannelReceiver<Vec<T>>) {
|
||||
channel::<Vec<T>>()
|
||||
}
|
||||
|
||||
pub fn singleton_channel<T: Send + Sync>() -> (ChannelSender<Option<T>>, ChannelReceiver<Option<T>>)
|
||||
{
|
||||
channel::<Option<T>>()
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
pub mod channel;
|
||||
pub mod observer;
|
||||
pub mod port;
|
||||
pub mod view;
|
||||
|
||||
pub use {
|
||||
channel::{queue_channel, set_channel, singleton_channel, ChannelReceiver, ChannelSender},
|
||||
observer::{NotifyFnObserver, Observer, ObserverBroadcast, ObserverExt, ResetFnObserver},
|
||||
port::{AnyInnerViewPort, AnyOuterViewPort, AnyViewPort, InnerViewPort, OuterViewPort, ViewPort},
|
||||
view::View
|
||||
};
|
||||
|
|
@ -1,179 +0,0 @@
|
|||
use {
|
||||
crate::core::{
|
||||
channel::{channel, ChannelReceiver, ChannelSender},
|
||||
View,
|
||||
},
|
||||
std::sync::RwLock,
|
||||
std::sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
/*\
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
Observer
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
\*/
|
||||
pub trait Observer<V: View + ?Sized>: Send + Sync {
|
||||
fn reset(&mut self, _view: Option<Arc<V>>) {}
|
||||
fn notify(&mut self, msg: &V::Msg);
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl<V: View + ?Sized, O: Observer<V>> Observer<V> for Arc<RwLock<O>> {
|
||||
fn reset(&mut self, view: Option<Arc<V>>) {
|
||||
self.write().unwrap().reset(view);
|
||||
}
|
||||
|
||||
fn notify(&mut self, msg: &V::Msg) {
|
||||
self.write().unwrap().notify(msg);
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub trait ObserverExt<V: View + ?Sized>: Observer<V> {
|
||||
fn notify_each(&mut self, it: impl IntoIterator<Item = V::Msg>);
|
||||
}
|
||||
|
||||
impl<V: View + ?Sized, T: Observer<V>> ObserverExt<V> for T {
|
||||
fn notify_each(&mut self, it: impl IntoIterator<Item = V::Msg>) {
|
||||
for msg in it {
|
||||
self.notify(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*\
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
Broadcast
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
\*/
|
||||
pub struct ObserverBroadcast<V: View + ?Sized>
|
||||
where
|
||||
V::Msg: Send + Sync,
|
||||
{
|
||||
rx: ChannelReceiver<Vec<V::Msg>>,
|
||||
tx: ChannelSender<Vec<V::Msg>>,
|
||||
observers: Vec<Weak<RwLock<dyn Observer<V>>>>,
|
||||
}
|
||||
|
||||
impl<V: View + ?Sized> ObserverBroadcast<V>
|
||||
where
|
||||
V::Msg: Clone + Send + Sync,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
let (tx, rx) = channel::<Vec<V::Msg>>();
|
||||
ObserverBroadcast {
|
||||
rx,
|
||||
tx,
|
||||
observers: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_observer(&mut self, obs: Weak<RwLock<dyn Observer<V>>>) {
|
||||
self.cleanup();
|
||||
self.observers.push(obs);
|
||||
}
|
||||
|
||||
fn cleanup(&mut self) {
|
||||
self.observers.retain(|o| o.strong_count() > 0);
|
||||
}
|
||||
|
||||
fn iter(&self) -> impl Iterator<Item = Arc<RwLock<dyn Observer<V>>>> + '_ {
|
||||
self.observers.iter().filter_map(|o| o.upgrade())
|
||||
}
|
||||
|
||||
pub fn update(&self) {
|
||||
if let Some(msg_vec) = self.rx.try_recv() {
|
||||
for msg in msg_vec {
|
||||
for o in self.iter() {
|
||||
o.write().unwrap().notify(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: View + ?Sized> Observer<V> for ObserverBroadcast<V>
|
||||
where
|
||||
V::Msg: Clone,
|
||||
{
|
||||
fn reset(&mut self, view: Option<Arc<V>>) {
|
||||
for o in self.iter() {
|
||||
o.write().unwrap().reset(view.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn notify(&mut self, msg: &V::Msg) {
|
||||
self.tx.send(msg.clone());
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub struct NotifyFnObserver<V, F>
|
||||
where
|
||||
V: View + ?Sized,
|
||||
F: Fn(&V::Msg) + Send + Sync,
|
||||
{
|
||||
f: F,
|
||||
_phantom: std::marker::PhantomData<V>,
|
||||
}
|
||||
|
||||
impl<V, F> NotifyFnObserver<V, F>
|
||||
where
|
||||
V: View + ?Sized,
|
||||
F: Fn(&V::Msg) + Send + Sync,
|
||||
{
|
||||
pub fn new(f: F) -> Self {
|
||||
NotifyFnObserver {
|
||||
f,
|
||||
_phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, F> Observer<V> for NotifyFnObserver<V, F>
|
||||
where
|
||||
V: View + ?Sized,
|
||||
F: Fn(&V::Msg) + Send + Sync,
|
||||
{
|
||||
fn notify(&mut self, msg: &V::Msg) {
|
||||
(self.f)(msg);
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub struct ResetFnObserver<V, F>
|
||||
where
|
||||
V: View + ?Sized,
|
||||
F: Fn(Option<Arc<V>>) + Send + Sync,
|
||||
{
|
||||
f: F,
|
||||
_phantom: std::marker::PhantomData<V>,
|
||||
}
|
||||
|
||||
impl<V, F> ResetFnObserver<V, F>
|
||||
where
|
||||
V: View + ?Sized,
|
||||
F: Fn(Option<Arc<V>>) + Send + Sync,
|
||||
{
|
||||
pub fn new(f: F) -> Self {
|
||||
ResetFnObserver {
|
||||
f,
|
||||
_phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, F> Observer<V> for ResetFnObserver<V, F>
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -1,341 +0,0 @@
|
|||
use {
|
||||
crate::core::{NotifyFnObserver, Observer, ObserverBroadcast, ResetFnObserver, View},
|
||||
std::any::Any,
|
||||
std::sync::Arc,
|
||||
std::sync::RwLock,
|
||||
};
|
||||
|
||||
pub trait UpdateTask: Send + Sync {
|
||||
fn update(&self);
|
||||
}
|
||||
|
||||
/*\
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
View Port
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
\*/
|
||||
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>>>>,
|
||||
}
|
||||
|
||||
impl<V: View + ?Sized> ViewPort<V>
|
||||
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())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_view(view: Arc<V>) -> Self {
|
||||
let port = ViewPort::new();
|
||||
port.set_view(Some(view));
|
||||
port
|
||||
}
|
||||
|
||||
pub fn set_view(&self, view: Option<Arc<V>>) {
|
||||
self.update();
|
||||
*self.view.write().unwrap() = view.clone();
|
||||
self.cast.write().unwrap().reset(view);
|
||||
}
|
||||
|
||||
pub fn get_cast(&self) -> Arc<RwLock<ObserverBroadcast<V>>> {
|
||||
self.cast.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());
|
||||
}
|
||||
|
||||
pub fn add_update_hook(&self, hook_cast: Arc<dyn UpdateTask>) {
|
||||
self.update_hooks.write().unwrap().push(hook_cast);
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> InnerViewPort<V> {
|
||||
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(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> InnerViewPort<V> {
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
t.iter().cloned().collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
for hook in v {
|
||||
hook.update();
|
||||
}
|
||||
|
||||
self.cast.read().unwrap().update();
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: View + ?Sized> Clone for ViewPort<V>
|
||||
where
|
||||
V::Msg: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
ViewPort {
|
||||
view: self.view.clone(),
|
||||
cast: self.cast.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;
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl<V: View + ?Sized> InnerViewPort<V>
|
||||
where
|
||||
V::Msg: Clone,
|
||||
{
|
||||
pub fn get_broadcast(&self) -> Arc<RwLock<ObserverBroadcast<V>>> {
|
||||
self.0.cast.clone()
|
||||
}
|
||||
|
||||
pub fn set_view(&self, view: Option<Arc<V>>) -> Arc<RwLock<ObserverBroadcast<V>>> {
|
||||
self.0.set_view(view);
|
||||
self.get_broadcast()
|
||||
}
|
||||
|
||||
pub fn get_view(&self) -> Option<Arc<V>> {
|
||||
self.0.view.read().unwrap().clone()
|
||||
}
|
||||
|
||||
pub fn notify(&self, msg: &V::Msg) {
|
||||
self.0.cast.write().unwrap().notify(msg);
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: View + ?Sized> Clone for InnerViewPort<V>
|
||||
where
|
||||
V::Msg: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
InnerViewPort(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl<V: View + ?Sized + 'static> OuterViewPort<V>
|
||||
where
|
||||
V::Msg: Clone,
|
||||
{
|
||||
pub fn get_view(&self) -> Option<Arc<V>> {
|
||||
self.0.view.read().unwrap().clone()
|
||||
}
|
||||
|
||||
pub fn get_view_arc(&self) -> Arc<RwLock<Option<Arc<V>>>> {
|
||||
self.0.view.clone()
|
||||
}
|
||||
|
||||
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>>> {
|
||||
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>>> {
|
||||
let obs = Arc::new(RwLock::new(NotifyFnObserver::new(notify)));
|
||||
self.add_observer(obs.clone());
|
||||
obs
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: View + ?Sized> Clone for OuterViewPort<V>
|
||||
where
|
||||
V::Msg: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
OuterViewPort(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: View + ?Sized> Default for OuterViewPort<V>
|
||||
where V::Msg: Clone
|
||||
{
|
||||
fn default() -> Self {
|
||||
ViewPort::new().into_outer()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl<V: View + ?Sized + 'static> OuterViewPort<V>
|
||||
where V::Msg: Clone {
|
||||
pub fn into_stream<Data>(
|
||||
self,
|
||||
reset: impl Fn(Option<Arc<V>>, ChannelSender<Data>) + Send + Sync + 'static
|
||||
) -> ChannelReceiver<Data>
|
||||
where Data: ChannelData<Item = V::Msg> + 'static,
|
||||
Data::IntoIter: Send + Sync + 'static
|
||||
{
|
||||
let (s, r) = crate::core::channel::channel::<Data>();
|
||||
self.add_observer(Arc::new(s.clone()));
|
||||
self.add_reset_fn(
|
||||
move |view| { reset(view, s.clone()); }
|
||||
);
|
||||
r
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
#[derive(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>>>>,
|
||||
}
|
||||
|
||||
impl AnyViewPort {
|
||||
pub fn downcast<V: View + ?Sized + 'static>(self) -> Result<ViewPort<V>, AnyViewPort> {
|
||||
match (
|
||||
self.view.clone().downcast::<RwLock<Option<Arc<V>>>>(),
|
||||
self.cast.clone().downcast::<RwLock<ObserverBroadcast<V>>>(),
|
||||
self.update_hooks.clone(),
|
||||
) {
|
||||
(Ok(view), Ok(cast), update_hooks) => Ok(ViewPort {
|
||||
view,
|
||||
cast,
|
||||
update_hooks,
|
||||
}),
|
||||
_ => Err(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: View + ?Sized + 'static> From<ViewPort<V>> for AnyViewPort {
|
||||
fn from(port: ViewPort<V>) -> Self {
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AnyOuterViewPort(AnyViewPort);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AnyInnerViewPort(AnyViewPort);
|
||||
|
||||
impl AnyOuterViewPort {
|
||||
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,
|
||||
{
|
||||
fn from(port: OuterViewPort<V>) -> Self {
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AnyInnerViewPort {
|
||||
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,
|
||||
{
|
||||
fn from(port: InnerViewPort<V>) -> Self {
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/*\
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
View
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
\*/
|
||||
pub trait View: Send + Sync {
|
||||
/// Notification message for the observers
|
||||
type Msg: Send + Sync;
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
|
||||
impl<V: View + ?Sized> View for RwLock<V> {
|
||||
type Msg = V::Msg;
|
||||
}
|
||||
|
||||
impl<V: View + ?Sized> View for Arc<V> {
|
||||
type Msg = V::Msg;
|
||||
}
|
||||
|
||||
impl<V: View> View for Option<V> {
|
||||
type Msg = V::Msg;
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{OuterViewPort, sequence::*},
|
||||
buffer::{vec::*, index_hashmap::*}
|
||||
},
|
||||
crate::{
|
||||
core::{OuterViewPort},
|
||||
sequence::{SequenceView},
|
||||
vec::{VecBuffer},
|
||||
index::{buffer::IndexBuffer},
|
||||
terminal::{
|
||||
TerminalView, TerminalStyle, make_label
|
||||
}
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{
|
||||
OuterViewPort,
|
||||
singleton::*,
|
||||
},
|
||||
buffer::singleton::*
|
||||
},
|
||||
crate::{
|
||||
core::{OuterViewPort},
|
||||
type_system::{Context},
|
||||
singleton::{SingletonBuffer, SingletonView},
|
||||
terminal::{TerminalAtom, TerminalEvent, TerminalStyle},
|
||||
tree::NestedNode,
|
||||
commander::Commander
|
||||
|
@ -70,11 +75,11 @@ impl CharEditor {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
use crate::StringGen;
|
||||
impl StringGen for CharEditor {
|
||||
fn get_string(&self) -> String {
|
||||
String::from(self.get())
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
|
@ -1,9 +1,13 @@
|
|||
use {
|
||||
crate::{
|
||||
core::{InnerViewPort, OuterViewPort},
|
||||
projection::ProjectionHelper,
|
||||
sequence::SequenceView,
|
||||
vec::VecBuffer,
|
||||
r3vi::{
|
||||
view::{
|
||||
InnerViewPort, OuterViewPort,
|
||||
sequence::*,
|
||||
},
|
||||
buffer::{
|
||||
vec::*
|
||||
},
|
||||
projection::projection_helper::*,
|
||||
},
|
||||
std::sync::{Arc, RwLock},
|
||||
};
|
|
@ -1,26 +1,29 @@
|
|||
use {
|
||||
crate::{
|
||||
core::{OuterViewPort},
|
||||
type_system::{Context, TypeTerm},
|
||||
list::{PTYListEditor},
|
||||
sequence::{SequenceView, SequenceViewExt, decorator::{PTYSeqDecorate, SeqDecorStyle}},
|
||||
singleton::{SingletonBuffer, SingletonView},
|
||||
vec::{VecBuffer},
|
||||
index::{buffer::IndexBuffer},
|
||||
terminal::{
|
||||
TerminalAtom, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle,
|
||||
TerminalView, make_label
|
||||
r3vi::{
|
||||
view::{
|
||||
OuterViewPort,
|
||||
singleton::*,
|
||||
},
|
||||
tree::{TreeCursor, TreeNav, TreeNavResult},
|
||||
diagnostics::{Diagnostics, Message},
|
||||
buffer::{
|
||||
singleton::*,
|
||||
vec::*,
|
||||
index_hashmap::*
|
||||
}
|
||||
},
|
||||
crate::{
|
||||
type_system::{Context, TypeTerm, ReprTree},
|
||||
editors::list::{PTYListEditor, ListStyle},
|
||||
terminal::{
|
||||
TerminalAtom, TerminalEvent, TerminalStyle, make_label
|
||||
},
|
||||
diagnostics::{Message},
|
||||
tree::NestedNode,
|
||||
Nested,
|
||||
commander::Commander
|
||||
},
|
||||
std::sync::Arc,
|
||||
std::sync::RwLock,
|
||||
termion::event::{Event, Key},
|
||||
cgmath::{Vector2, Point2}
|
||||
cgmath::{Point2}
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
@ -74,13 +77,15 @@ impl DigitEditor {
|
|||
}
|
||||
|
||||
pub fn into_node(self) -> NestedNode {
|
||||
let data = self.get_data();
|
||||
let editor = Arc::new(RwLock::new(self));
|
||||
let ed = editor.read().unwrap();
|
||||
let mut ed = editor.write().unwrap();
|
||||
let r = ed.radix;
|
||||
|
||||
NestedNode::new()
|
||||
.set_ctx(ed.ctx.clone())
|
||||
.set_cmd(editor.clone())
|
||||
.set_data(data)
|
||||
.set_view(
|
||||
ed.data
|
||||
.get_port()
|
||||
|
@ -106,6 +111,26 @@ impl DigitEditor {
|
|||
let radix = self.radix;
|
||||
self.data.get_port().map(move |c| c?.to_digit(radix))
|
||||
}
|
||||
|
||||
pub fn get_type(&self) -> TypeTerm {
|
||||
TypeTerm::Type {
|
||||
id: self.ctx.read().unwrap().get_typeid("Digit").unwrap(),
|
||||
args: vec![
|
||||
TypeTerm::Num(self.radix as i64)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
|
||||
let data_view = self.get_data_port();
|
||||
ReprTree::ascend(
|
||||
&ReprTree::new_leaf(
|
||||
self.ctx.read().unwrap().type_term_from_str("( u32 )").unwrap(),
|
||||
data_view.into()
|
||||
),
|
||||
self.get_type()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PosIntEditor {
|
||||
|
@ -115,24 +140,40 @@ pub struct PosIntEditor {
|
|||
|
||||
impl PosIntEditor {
|
||||
pub fn new(ctx: Arc<RwLock<Context>>, radix: u32) -> Self {
|
||||
let mut node = PTYListEditor::new(
|
||||
ctx.clone(),
|
||||
TypeTerm::Type {
|
||||
id: ctx.read().unwrap().get_typeid("Digit").unwrap(),
|
||||
args: vec![
|
||||
TypeTerm::Num(radix as i64)
|
||||
]
|
||||
},
|
||||
match radix {
|
||||
16 => ListStyle::Hex,
|
||||
_ => ListStyle::Plain
|
||||
},
|
||||
0
|
||||
).into_node();
|
||||
|
||||
// Set Type
|
||||
let data = node.data.clone().unwrap();
|
||||
node = node.set_data(ReprTree::ascend(
|
||||
&data,
|
||||
TypeTerm::Type {
|
||||
id: ctx.read().unwrap().get_typeid("PosInt").unwrap(),
|
||||
args: vec![
|
||||
TypeTerm::Num(radix as i64),
|
||||
TypeTerm::Type {
|
||||
id: ctx.read().unwrap().get_typeid("BigEndian").unwrap(),
|
||||
args: vec![]
|
||||
}
|
||||
]
|
||||
}
|
||||
));
|
||||
|
||||
PosIntEditor {
|
||||
radix,
|
||||
digits: PTYListEditor::new(
|
||||
ctx.clone(),
|
||||
TypeTerm::Type {
|
||||
id: ctx.read().unwrap().get_typeid("Digit").unwrap(),
|
||||
args: vec![
|
||||
TypeTerm::Num(radix as i64)
|
||||
]
|
||||
},
|
||||
None,
|
||||
0
|
||||
).into_node(
|
||||
match radix {
|
||||
16 => SeqDecorStyle::Hex,
|
||||
_ => SeqDecorStyle::Plain
|
||||
}
|
||||
)
|
||||
digits: node
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
use {
|
||||
crate::{
|
||||
core::{InnerViewPort, Observer, OuterViewPort},
|
||||
sequence::SequenceView,
|
||||
vec::VecBuffer,
|
||||
r3vi::{
|
||||
view::{
|
||||
InnerViewPort, Observer, OuterViewPort,
|
||||
sequence::*,
|
||||
},
|
||||
buffer::{vec::*}
|
||||
},
|
||||
std::sync::{Arc, RwLock},
|
||||
};
|
43
nested/src/editors/list/commander.rs
Normal file
43
nested/src/editors/list/commander.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
|
||||
use {
|
||||
crate::{
|
||||
editors::list::ListEditor
|
||||
},
|
||||
std::sync::{Arc, RwLock}
|
||||
};
|
||||
|
||||
pub enum ListEditorCmd {
|
||||
ItemCmd(Arc<RwLock<ReprTree>>)
|
||||
Split,
|
||||
Join
|
||||
}
|
||||
|
||||
impl ObjCommander for ListEditor {
|
||||
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) {
|
||||
let cmd_repr = cmd_obj.read().unrwap();
|
||||
|
||||
if let Some(cmd) = cmd_repr.get_view<dyn SingletonView<ListEditorCmd>>() {
|
||||
match cmd.get() {
|
||||
ListEditorCmd::Split => {
|
||||
|
||||
}
|
||||
ListEditorCmd::Join => {
|
||||
|
||||
}
|
||||
ListEditorCmd::ItemCmd => {
|
||||
if let Some(cur_item) = self.get_item_mut() {
|
||||
drop(cmd);
|
||||
drop(cmd_repr);
|
||||
cur_item.send_cmd_obj(cmd_obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let Some(cur_item) = self.get_item_mut() {
|
||||
drop(cmd_repr);
|
||||
cur_item.send_cmd_obj(cmd_obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
280
nested/src/editors/list/editor.rs
Normal file
280
nested/src/editors/list/editor.rs
Normal file
|
@ -0,0 +1,280 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{
|
||||
OuterViewPort,
|
||||
singleton::*,
|
||||
sequence::*,
|
||||
},
|
||||
buffer::{
|
||||
singleton::*,
|
||||
vec::*,
|
||||
}
|
||||
},
|
||||
crate::{
|
||||
type_system::{Context, TypeTerm, ReprTree},
|
||||
editors::list::{
|
||||
ListCursor,
|
||||
ListCursorMode
|
||||
},
|
||||
tree::{NestedNode, TreeNav}
|
||||
},
|
||||
std::sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub struct ListEditor {
|
||||
pub(super) cursor: SingletonBuffer<ListCursor>,
|
||||
pub(crate) data: VecBuffer<NestedNode>,
|
||||
|
||||
pub(super) addr_port: OuterViewPort<dyn SequenceView<Item = isize>>,
|
||||
pub(super) mode_port: OuterViewPort<dyn SingletonView<Item = ListCursorMode>>,
|
||||
|
||||
pub(crate) ctx: Arc<RwLock<Context>>,
|
||||
|
||||
/// item type
|
||||
pub(super) typ: TypeTerm,
|
||||
}
|
||||
|
||||
impl ListEditor {
|
||||
pub fn new(
|
||||
ctx: Arc<RwLock<Context>>,
|
||||
typ: TypeTerm,
|
||||
) -> Self {
|
||||
let cursor = SingletonBuffer::new(ListCursor::default());
|
||||
let data = VecBuffer::<NestedNode>::new();
|
||||
|
||||
ListEditor {
|
||||
mode_port: cursor
|
||||
.get_port()
|
||||
.map({
|
||||
let data = data.clone();
|
||||
move |c| {
|
||||
let ip = SingletonBuffer::new(c.mode).get_port();
|
||||
match c.mode {
|
||||
ListCursorMode::Insert => ip,
|
||||
ListCursorMode::Select => {
|
||||
if let Some(idx) = c.idx {
|
||||
data.get(idx as usize).get_mode_view()
|
||||
} else {
|
||||
ip
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.flatten(),
|
||||
|
||||
addr_port: VecBuffer::<OuterViewPort<dyn SequenceView<Item = isize>>>::with_data(
|
||||
vec![
|
||||
cursor.get_port()
|
||||
.to_sequence()
|
||||
.filter_map(|cur| cur.idx),
|
||||
cursor.get_port()
|
||||
.map({
|
||||
let data = data.clone();
|
||||
move |cur| {
|
||||
if cur.mode == ListCursorMode::Select {
|
||||
if let Some(idx) = cur.idx {
|
||||
if idx >= 0 && idx < data.len() as isize {
|
||||
return data.get(idx as usize).get_addr_view();
|
||||
}
|
||||
}
|
||||
}
|
||||
OuterViewPort::default()
|
||||
}
|
||||
})
|
||||
.to_sequence()
|
||||
.flatten()
|
||||
])
|
||||
.get_port()
|
||||
.to_sequence()
|
||||
.flatten(),
|
||||
cursor,
|
||||
data,
|
||||
ctx,
|
||||
typ,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_item_type(&self) -> TypeTerm {
|
||||
self.typ.clone()
|
||||
}
|
||||
|
||||
pub fn get_seq_type(&self) -> TypeTerm {
|
||||
TypeTerm::Type {
|
||||
id: self.ctx.read().unwrap().get_typeid("Sequence").unwrap(),
|
||||
args: vec![ self.get_item_type() ]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_node(self) -> NestedNode {
|
||||
let data = self.get_data();
|
||||
let editor = Arc::new(RwLock::new(self));
|
||||
|
||||
NestedNode::new()
|
||||
.set_data(data)
|
||||
.set_editor(editor.clone())
|
||||
.set_nav(editor.clone())
|
||||
// .set_cmd(editor.clone())
|
||||
}
|
||||
|
||||
pub fn get_cursor_port(&self) -> OuterViewPort<dyn SingletonView<Item = ListCursor>> {
|
||||
self.cursor.get_port()
|
||||
}
|
||||
|
||||
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = NestedNode>> {
|
||||
self.data.get_port().to_sequence()
|
||||
}
|
||||
|
||||
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
|
||||
let data_view = self.get_data_port();
|
||||
ReprTree::new_leaf(
|
||||
self.get_seq_type(),
|
||||
data_view.into()
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_item(&self) -> Option<NestedNode> {
|
||||
if let Some(idx) = self.cursor.get().idx {
|
||||
let idx = crate::utils::modulo(idx as isize, self.data.len() as isize) as usize;
|
||||
if idx < self.data.len() {
|
||||
Some(self.data.get(idx))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_item_mut(&mut self) -> Option<MutableVecAccess<NestedNode>> {
|
||||
if let Some(idx) = self.cursor.get().idx {
|
||||
let idx = crate::utils::modulo(idx as isize, self.data.len() as isize) as usize;
|
||||
if idx < self.data.len() {
|
||||
Some(self.data.get_mut(idx))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_listlist(&self) -> bool {
|
||||
self.ctx.read().unwrap().is_list_type(&self.typ)
|
||||
/*
|
||||
match self.typ.clone() {
|
||||
TypeTerm::Type { id, args } => {
|
||||
id == self.ctx.read().unwrap().get_typeid("List").unwrap()
|
||||
},
|
||||
TypeTerm::Num(_) => false
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/// delete all items
|
||||
pub fn clear(&mut self) {
|
||||
self.data.clear();
|
||||
self.cursor.set(ListCursor::home());
|
||||
}
|
||||
|
||||
/// delete item before the cursor
|
||||
pub fn delete_pxev(&mut self) {
|
||||
let mut cur = self.cursor.get();
|
||||
if let Some(idx) = cur.idx {
|
||||
if idx > 0 && idx <= self.data.len() as isize {
|
||||
cur.idx = Some(idx as isize - 1);
|
||||
self.cursor.set(cur);
|
||||
self.data.remove(idx as usize - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// delete item after the cursor
|
||||
pub fn delete_nexd(&mut self) {
|
||||
if let Some(idx) = self.cursor.get().idx {
|
||||
if idx < self.data.len() as isize {
|
||||
self.data.remove(idx as usize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// insert a new element
|
||||
pub fn insert(&mut self, item: NestedNode) {
|
||||
let mut cur = self.cursor.get();
|
||||
if let Some(idx) = cur.idx {
|
||||
|
||||
match cur.mode {
|
||||
|