move list editor module to nested crate
This commit is contained in:
parent
2d17254b2c
commit
07ee04bba4
6 changed files with 963 additions and 347 deletions
|
@ -10,6 +10,7 @@ pub mod sequence;
|
||||||
pub mod vec;
|
pub mod vec;
|
||||||
pub mod terminal;
|
pub mod terminal;
|
||||||
pub mod integer;
|
pub mod integer;
|
||||||
|
pub mod list;
|
||||||
|
|
||||||
pub mod string_editor;
|
pub mod string_editor;
|
||||||
pub mod leveled_term_view;
|
pub mod leveled_term_view;
|
||||||
|
|
427
nested/src/list/editor.rs
Normal file
427
nested/src/list/editor.rs
Normal file
|
@ -0,0 +1,427 @@
|
||||||
|
use {
|
||||||
|
std::sync::{Arc, RwLock},
|
||||||
|
termion::event::{Event, Key},
|
||||||
|
crate::{
|
||||||
|
core::{
|
||||||
|
View,
|
||||||
|
ViewPort,
|
||||||
|
OuterViewPort,
|
||||||
|
InnerViewPort,
|
||||||
|
ObserverBroadcast,
|
||||||
|
Observer,
|
||||||
|
ObserverExt,
|
||||||
|
context::{
|
||||||
|
ReprTree,
|
||||||
|
Object,
|
||||||
|
MorphismType,
|
||||||
|
MorphismMode,
|
||||||
|
Context
|
||||||
|
}
|
||||||
|
},
|
||||||
|
projection::ProjectionHelper,
|
||||||
|
singleton::{SingletonView, SingletonBuffer},
|
||||||
|
sequence::{SequenceView},
|
||||||
|
vec::{VecBuffer},
|
||||||
|
terminal::{
|
||||||
|
TerminalView,
|
||||||
|
TerminalStyle,
|
||||||
|
TerminalEvent,
|
||||||
|
TerminalEditor,
|
||||||
|
TerminalEditorResult,
|
||||||
|
make_label
|
||||||
|
},
|
||||||
|
string_editor::StringEditor,
|
||||||
|
leveled_term_view::LeveledTermView,
|
||||||
|
list::SExprView
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
enum ListEditorCursor {
|
||||||
|
None,
|
||||||
|
Insert(usize),
|
||||||
|
Select(usize),
|
||||||
|
Edit(usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ListEditorCursor {
|
||||||
|
fn default() -> Self {
|
||||||
|
ListEditorCursor::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ListEditor<SubEditor, FnMakeItemEditor>
|
||||||
|
where SubEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
|
||||||
|
FnMakeItemEditor: Fn() -> Arc<RwLock<SubEditor>>
|
||||||
|
{
|
||||||
|
cursor: SingletonBuffer<ListEditorCursor>,
|
||||||
|
data: VecBuffer<Arc<RwLock<SubEditor>>>,
|
||||||
|
data_sequence_port: OuterViewPort<dyn SequenceView<Item = Arc<RwLock<SubEditor>>>>,
|
||||||
|
make_item_editor: FnMakeItemEditor,
|
||||||
|
level: usize,
|
||||||
|
pub segment_seq: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<SubEditor, FnMakeItemEditor> TerminalEditor for ListEditor<SubEditor, FnMakeItemEditor>
|
||||||
|
where SubEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
|
||||||
|
FnMakeItemEditor: Fn() -> Arc<RwLock<SubEditor>>
|
||||||
|
{
|
||||||
|
fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> {
|
||||||
|
self.segment_seq.horizontal_sexpr_view(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
|
||||||
|
match self.cursor.get() {
|
||||||
|
ListEditorCursor::None => {
|
||||||
|
|
||||||
|
}
|
||||||
|
ListEditorCursor::Insert(idx) => {
|
||||||
|
match event {
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Insert)) => {
|
||||||
|
self.cursor.set(ListEditorCursor::Select(idx));
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Left)) => {
|
||||||
|
if idx > 0 {
|
||||||
|
self.cursor.set(ListEditorCursor::Insert(idx-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Right)) => {
|
||||||
|
if idx < self.data.len() {
|
||||||
|
self.cursor.set(ListEditorCursor::Insert(idx+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event => {
|
||||||
|
self.data.insert(idx, (self.make_item_editor)());
|
||||||
|
self.cursor.set(ListEditorCursor::Edit(idx));
|
||||||
|
self.data.get_mut(idx).write().unwrap().handle_terminal_event(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListEditorCursor::Select(idx) => {
|
||||||
|
match event {
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Insert)) => {
|
||||||
|
self.cursor.set(ListEditorCursor::Insert(idx));
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Delete)) => {
|
||||||
|
self.data.remove(idx);
|
||||||
|
if self.data.len() == 0 {
|
||||||
|
self.cursor.set(ListEditorCursor::Insert(0));
|
||||||
|
} else if idx == self.data.len() && idx > 0 {
|
||||||
|
self.cursor.set(ListEditorCursor::Select(idx-1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Home)) => {
|
||||||
|
if self.data.len() > 0 {
|
||||||
|
self.cursor.set(ListEditorCursor::Select(0))
|
||||||
|
} else {
|
||||||
|
self.cursor.set(ListEditorCursor::Insert(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::End)) => {
|
||||||
|
if self.data.len() > 0 {
|
||||||
|
self.cursor.set(ListEditorCursor::Select(self.data.len() - 1))
|
||||||
|
} else {
|
||||||
|
self.cursor.set(ListEditorCursor::Insert(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Left)) => {
|
||||||
|
if idx > 0 {
|
||||||
|
self.cursor.set(ListEditorCursor::Select(idx - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Right)) => {
|
||||||
|
if idx+1 < self.data.len() {
|
||||||
|
self.cursor.set(ListEditorCursor::Select(idx + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event => {
|
||||||
|
self.cursor.set(ListEditorCursor::Edit(idx));
|
||||||
|
self.data.get_mut(idx).write().unwrap().handle_terminal_event(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListEditorCursor::Edit(idx) => {
|
||||||
|
match event {
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Char('\t'))) => {
|
||||||
|
if idx > 0 {
|
||||||
|
self.cursor.set(ListEditorCursor::Edit(idx-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
|
||||||
|
if idx+1 < self.data.len() {
|
||||||
|
self.cursor.set(ListEditorCursor::Edit(idx+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Char(' '))) => {
|
||||||
|
// split..
|
||||||
|
self.data.insert(idx+1, (self.make_item_editor)());
|
||||||
|
self.data.get_mut(idx).write().unwrap().handle_terminal_event(&TerminalEvent::Input(Event::Key(Key::End)));
|
||||||
|
self.data.get_mut(idx+1).write().unwrap().handle_terminal_event(&TerminalEvent::Input(Event::Key(Key::Home)));
|
||||||
|
self.cursor.set(ListEditorCursor::Edit(idx+1));
|
||||||
|
}
|
||||||
|
event => {
|
||||||
|
let ce = self.data.get_mut(idx);
|
||||||
|
let mut cur_edit = ce.write().unwrap();
|
||||||
|
match cur_edit.handle_terminal_event(event) {
|
||||||
|
TerminalEditorResult::Exit => {
|
||||||
|
match event {
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Up)) => {
|
||||||
|
self.cursor.set(ListEditorCursor::Select(idx));
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Home)) => {
|
||||||
|
if idx > 0 {
|
||||||
|
self.cursor.set(ListEditorCursor::Edit(idx-1));
|
||||||
|
self.data.get_mut(idx-1).write().unwrap().handle_terminal_event(event);
|
||||||
|
} else {
|
||||||
|
cur_edit.handle_terminal_event(&TerminalEvent::Input(Event::Key(Key::Home)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Backspace)) | // -> join
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Left)) => {
|
||||||
|
if idx > 0 {
|
||||||
|
self.cursor.set(ListEditorCursor::Edit(idx-1));
|
||||||
|
self.data.get_mut(idx-1).write().unwrap().handle_terminal_event(&TerminalEvent::Input(Event::Key(Key::End)));
|
||||||
|
} else {
|
||||||
|
cur_edit.handle_terminal_event(&TerminalEvent::Input(Event::Key(Key::Home)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::End)) => {
|
||||||
|
if idx+1 < self.data.len() {
|
||||||
|
self.cursor.set(ListEditorCursor::Edit(idx+1));
|
||||||
|
self.data.get_mut(idx+1).write().unwrap().handle_terminal_event(event);
|
||||||
|
} else if idx+1 == self.data.len() {
|
||||||
|
cur_edit.handle_terminal_event(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Delete)) |
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Right)) => {
|
||||||
|
if idx+1 < self.data.len() {
|
||||||
|
self.cursor.set(ListEditorCursor::Edit(idx+1));
|
||||||
|
self.data.get_mut(idx+1).write().unwrap().handle_terminal_event(&TerminalEvent::Input(Event::Key(Key::Home)));
|
||||||
|
} else if idx+1 == self.data.len() {
|
||||||
|
cur_edit.handle_terminal_event(&TerminalEvent::Input(Event::Key(Key::End)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TerminalEditorResult::Continue => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TerminalEditorResult::Continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ListEditorViewSegment {
|
||||||
|
InsertCursor,
|
||||||
|
View(OuterViewPort<dyn TerminalView>),
|
||||||
|
Select(OuterViewPort<dyn TerminalView>),
|
||||||
|
Edit(OuterViewPort<dyn TerminalView>)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ListEditorView {
|
||||||
|
cursor: Arc<dyn SingletonView<Item = ListEditorCursor>>,
|
||||||
|
data: Arc<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
|
||||||
|
cur_cursor: ListEditorCursor,
|
||||||
|
|
||||||
|
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = ListEditorViewSegment>>>>,
|
||||||
|
proj_helper: ProjectionHelper<Self>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl View for ListEditorView {
|
||||||
|
type Msg = usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SequenceView for ListEditorView {
|
||||||
|
type Item = ListEditorViewSegment;
|
||||||
|
|
||||||
|
fn len(&self) -> Option<usize> {
|
||||||
|
match self.cur_cursor {
|
||||||
|
ListEditorCursor::None => self.data.len(),
|
||||||
|
ListEditorCursor::Select(_) => self.data.len(),
|
||||||
|
ListEditorCursor::Edit(_) => self.data.len(),
|
||||||
|
ListEditorCursor::Insert(_) => Some(self.data.len()? + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&self, idx: &usize) -> Option<Self::Item> {
|
||||||
|
Some(
|
||||||
|
match self.cur_cursor {
|
||||||
|
ListEditorCursor::None =>
|
||||||
|
ListEditorViewSegment::View(self.data.get(idx)?),
|
||||||
|
ListEditorCursor::Select(c) =>
|
||||||
|
if *idx == c {
|
||||||
|
ListEditorViewSegment::Select(self.data.get(idx)?)
|
||||||
|
} else {
|
||||||
|
ListEditorViewSegment::View(self.data.get(idx)?)
|
||||||
|
},
|
||||||
|
ListEditorCursor::Edit(c) =>
|
||||||
|
if *idx == c {
|
||||||
|
ListEditorViewSegment::Edit(self.data.get(idx)?)
|
||||||
|
} else {
|
||||||
|
ListEditorViewSegment::View(self.data.get(idx)?)
|
||||||
|
},
|
||||||
|
ListEditorCursor::Insert(c) =>
|
||||||
|
if *idx < c {
|
||||||
|
ListEditorViewSegment::View(self.data.get(idx)?)
|
||||||
|
} else if *idx == c {
|
||||||
|
ListEditorViewSegment::InsertCursor
|
||||||
|
} else {
|
||||||
|
ListEditorViewSegment::View(self.data.get(&(idx-1))?)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ListEditorView {
|
||||||
|
fn new(
|
||||||
|
cursor_port: OuterViewPort<dyn SingletonView<Item = ListEditorCursor>>,
|
||||||
|
data_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
|
||||||
|
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: ListEditorCursor::None,
|
||||||
|
cursor: proj_helper.new_singleton_arg(
|
||||||
|
cursor_port,
|
||||||
|
|s: &mut Self, _msg| {
|
||||||
|
let old_cursor = s.cur_cursor;
|
||||||
|
let new_cursor = s.cursor.get();
|
||||||
|
s.cur_cursor = new_cursor;
|
||||||
|
|
||||||
|
let mut begin = std::cmp::min(
|
||||||
|
match old_cursor {
|
||||||
|
ListEditorCursor::None => usize::MAX,
|
||||||
|
ListEditorCursor::Select(c) => c,
|
||||||
|
ListEditorCursor::Insert(c) => c,
|
||||||
|
ListEditorCursor::Edit(c) => c
|
||||||
|
},
|
||||||
|
match new_cursor {
|
||||||
|
ListEditorCursor::None => usize::MAX,
|
||||||
|
ListEditorCursor::Select(c) => c,
|
||||||
|
ListEditorCursor::Insert(c) => c,
|
||||||
|
ListEditorCursor::Edit(c) => c
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let mut end =
|
||||||
|
/*
|
||||||
|
match (old_cursor, new_cursor) {
|
||||||
|
(ListEditorCursor::None, ListEditorCursor::None) => usize::MAX,
|
||||||
|
(ListEditorCursor::Select(old_pos), ListEditorCursor::Select(new_pos)) => max(old_pos, new_pos),
|
||||||
|
(ListEditorCursor::Edit(old_pos), ListEditorCursor::Edit(new_pos)) => max(old_pos, new_pos),
|
||||||
|
(ListEditorCursor::Insert(old_pos), ListEditorCursor::Insert(new_pos)) => max(old_pos, new_pos),
|
||||||
|
(ListEditorCursor::)
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
std::cmp::max(
|
||||||
|
match old_cursor {
|
||||||
|
ListEditorCursor::None => 0,
|
||||||
|
ListEditorCursor::Select(c) => c,
|
||||||
|
ListEditorCursor::Insert(c) => c+1,
|
||||||
|
ListEditorCursor::Edit(c) => c
|
||||||
|
},
|
||||||
|
match new_cursor {
|
||||||
|
ListEditorCursor::None => 0,
|
||||||
|
ListEditorCursor::Select(c) => c,
|
||||||
|
ListEditorCursor::Insert(c) => c+1,
|
||||||
|
ListEditorCursor::Edit(c) => c
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
s.cast.notify_each(
|
||||||
|
begin ..= end
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
data: proj_helper.new_sequence_arg(
|
||||||
|
data_port,
|
||||||
|
|s: &mut Self, idx| {
|
||||||
|
match s.cur_cursor {
|
||||||
|
ListEditorCursor::None => s.cast.notify(idx),
|
||||||
|
ListEditorCursor::Select(c) => s.cast.notify(idx),
|
||||||
|
ListEditorCursor::Edit(c) => s.cast.notify(idx),
|
||||||
|
ListEditorCursor::Insert(c) =>
|
||||||
|
if *idx < c {
|
||||||
|
s.cast.notify(idx)
|
||||||
|
} else {
|
||||||
|
s.cast.notify(&(*idx + 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
cast: out_port.get_broadcast(),
|
||||||
|
proj_helper
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
proj.write().unwrap().proj_helper.set_proj(&proj);
|
||||||
|
out_port.set_view(Some(proj.clone()));
|
||||||
|
|
||||||
|
proj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<SubEditor, FnMakeItemEditor> ListEditor<SubEditor, FnMakeItemEditor>
|
||||||
|
where SubEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
|
||||||
|
FnMakeItemEditor: Fn() -> Arc<RwLock<SubEditor>>
|
||||||
|
{
|
||||||
|
pub fn new(make_item_editor: FnMakeItemEditor) -> Self {
|
||||||
|
let cursor_port = ViewPort::new();
|
||||||
|
let data_port = ViewPort::new();
|
||||||
|
|
||||||
|
let mut cursor = SingletonBuffer::new(ListEditorCursor::Insert(0), cursor_port.inner());
|
||||||
|
let mut data = VecBuffer::<Arc<RwLock<SubEditor>>>::new(data_port.inner());
|
||||||
|
|
||||||
|
let data_sequence_port = data_port.into_outer().to_sequence();
|
||||||
|
|
||||||
|
let segment_view_port = ViewPort::<dyn SequenceView<Item = ListEditorViewSegment>>::new();
|
||||||
|
let segment_view = ListEditorView::new(
|
||||||
|
cursor_port.outer(),
|
||||||
|
data_sequence_port.map(|ed| ed.read().unwrap().get_term_view()),
|
||||||
|
segment_view_port.inner()
|
||||||
|
);
|
||||||
|
|
||||||
|
ListEditor {
|
||||||
|
data,
|
||||||
|
data_sequence_port,
|
||||||
|
cursor,
|
||||||
|
make_item_editor,
|
||||||
|
level: 0,
|
||||||
|
segment_seq: segment_view_port
|
||||||
|
.outer()
|
||||||
|
.map(
|
||||||
|
|segment| match segment {
|
||||||
|
ListEditorViewSegment::InsertCursor =>
|
||||||
|
make_label("|")
|
||||||
|
.map_item(
|
||||||
|
|_pt, atom|
|
||||||
|
atom.add_style_back(TerminalStyle::fg_color((90,60,200)))
|
||||||
|
.add_style_back(TerminalStyle::bold(true))
|
||||||
|
),
|
||||||
|
ListEditorViewSegment::Select(sub_view) =>
|
||||||
|
sub_view.map_item(
|
||||||
|
|_pt, atom|
|
||||||
|
atom.add_style_back(TerminalStyle::bg_color((90,60,200)))
|
||||||
|
),
|
||||||
|
ListEditorViewSegment::Edit(sub_view) =>
|
||||||
|
sub_view.map_item(
|
||||||
|
|_pt, atom|
|
||||||
|
atom.add_style_back(TerminalStyle::bg_color((0,0,0)))
|
||||||
|
.add_style_back(TerminalStyle::bold(true))
|
||||||
|
),
|
||||||
|
ListEditorViewSegment::View(sub_view) =>
|
||||||
|
sub_view.clone()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = Arc<RwLock<SubEditor>>>> {
|
||||||
|
self.data_sequence_port.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
7
nested/src/list/mod.rs
Normal file
7
nested/src/list/mod.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
pub mod editor;
|
||||||
|
pub mod sexpr;
|
||||||
|
|
||||||
|
pub use editor::ListEditor;
|
||||||
|
pub use sexpr::SExprView;
|
||||||
|
|
283
nested/src/list/sexpr.rs
Normal file
283
nested/src/list/sexpr.rs
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
use {
|
||||||
|
std::sync::Arc,
|
||||||
|
std::sync::RwLock,
|
||||||
|
cgmath::{Point2},
|
||||||
|
crate::{
|
||||||
|
core::{
|
||||||
|
View,
|
||||||
|
ViewPort,
|
||||||
|
OuterViewPort,
|
||||||
|
InnerViewPort,
|
||||||
|
Observer,
|
||||||
|
ObserverBroadcast
|
||||||
|
},
|
||||||
|
sequence::{SequenceView},
|
||||||
|
terminal::{TerminalStyle, TerminalView, make_label},
|
||||||
|
projection::ProjectionHelper
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
pub struct ListDecorator {
|
||||||
|
opening_port: OuterViewPort<dyn TerminalView>,
|
||||||
|
closing_port: OuterViewPort<dyn TerminalView>,
|
||||||
|
delim_port: OuterViewPort<dyn TerminalView>,
|
||||||
|
items: Arc<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
|
||||||
|
|
||||||
|
list_style: TerminalStyle,
|
||||||
|
item_style: TerminalStyle,
|
||||||
|
|
||||||
|
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>>>,
|
||||||
|
proj_helper: ProjectionHelper<Self>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl View for ListDecorator {
|
||||||
|
type Msg = usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SequenceView for ListDecorator {
|
||||||
|
type Item = OuterViewPort<dyn TerminalView>;
|
||||||
|
|
||||||
|
fn len(&self) -> Option<usize> {
|
||||||
|
let l = self.items.len()?;
|
||||||
|
Some(if l == 0 { 2 } else { 2*l + 2 })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&self, idx: &usize) -> Option<Self::Item> {
|
||||||
|
let item_idx = idx / 2;
|
||||||
|
let list_style = self.list_style.clone();
|
||||||
|
let item_style = self.item_style.clone();
|
||||||
|
let l = self.items.len().unwrap_or(0);
|
||||||
|
Some(
|
||||||
|
if *idx == 0 {
|
||||||
|
self.opening_port.clone()
|
||||||
|
.map_item(move |_, atom| atom.add_style_back(list_style))
|
||||||
|
} else if (l == 0 && *idx == 1) || *idx == 2*l {
|
||||||
|
self.closing_port.clone()
|
||||||
|
.map_item(move |_, atom| atom.add_style_back(list_style))
|
||||||
|
} else if idx % 2 == 0 {
|
||||||
|
self.delim_port.clone()
|
||||||
|
.map_item(move |_, atom| atom.add_style_back(list_style))
|
||||||
|
} else {
|
||||||
|
self.items
|
||||||
|
.get(&item_idx)?
|
||||||
|
.map_item(move |_, atom| atom.add_style_back(item_style))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ListDecorator {
|
||||||
|
pub fn new(
|
||||||
|
opening: &str,
|
||||||
|
closing: &str,
|
||||||
|
delim: &str,
|
||||||
|
level: usize,
|
||||||
|
items_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
|
||||||
|
out_port: InnerViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>
|
||||||
|
) -> Arc<RwLock<Self>> {
|
||||||
|
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
|
||||||
|
|
||||||
|
let li = Arc::new(RwLock::new(ListDecorator {
|
||||||
|
opening_port: make_label(opening),
|
||||||
|
closing_port: make_label(closing),
|
||||||
|
delim_port: make_label(delim),
|
||||||
|
items: proj_helper.new_sequence_arg(
|
||||||
|
items_port,
|
||||||
|
|s: &mut Self, item_idx| {
|
||||||
|
s.cast.notify(
|
||||||
|
&(*item_idx * 2 + 1)
|
||||||
|
);
|
||||||
|
s.cast.notify(
|
||||||
|
&(*item_idx * 2 + 2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
list_style: TerminalStyle::fg_color(
|
||||||
|
match level {
|
||||||
|
0 => (200, 120, 10),
|
||||||
|
1 => (120, 200, 10),
|
||||||
|
_ => (255, 255, 255)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
item_style: TerminalStyle::fg_color(
|
||||||
|
match level {
|
||||||
|
_ => (255, 255, 255)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cast: out_port.get_broadcast(),
|
||||||
|
proj_helper
|
||||||
|
}));
|
||||||
|
|
||||||
|
li.write().unwrap().proj_helper.set_proj(&li);
|
||||||
|
|
||||||
|
out_port.set_view(Some(li.clone()));
|
||||||
|
li
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
use crate::{index::IndexView, grid::GridView};
|
||||||
|
|
||||||
|
pub struct VerticalSexprDecorator {
|
||||||
|
opening_port: OuterViewPort<dyn TerminalView>,
|
||||||
|
closing_port: OuterViewPort<dyn TerminalView>,
|
||||||
|
items: Arc<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
|
||||||
|
|
||||||
|
list_style: TerminalStyle,
|
||||||
|
item_style: TerminalStyle,
|
||||||
|
|
||||||
|
cast: Arc<RwLock<ObserverBroadcast<dyn GridView<Item = OuterViewPort<dyn TerminalView>>>>>,
|
||||||
|
proj_helper: ProjectionHelper<Self>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl View for VerticalSexprDecorator {
|
||||||
|
type Msg = Point2<i16>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexView<Point2<i16>> for VerticalSexprDecorator {
|
||||||
|
type Item = OuterViewPort<dyn TerminalView>;
|
||||||
|
|
||||||
|
fn area(&self) -> Option<Vec<Point2<i16>>> {
|
||||||
|
let mut area = (0 .. self.items.len()?).map(|i| Point2::new(1 as i16, i as i16)).collect::<Vec<_>>();
|
||||||
|
area.push(Point2::new(0, 0));
|
||||||
|
area.push(Point2::new(2, self.items.len()? as i16 - 1));
|
||||||
|
Some(area)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&self, pt: &Point2<i16>) -> Option<Self::Item> {
|
||||||
|
let item_idx = pt.y as usize;
|
||||||
|
let list_style = self.list_style.clone();
|
||||||
|
let item_style = self.item_style.clone();
|
||||||
|
let l = self.items.len().unwrap_or(0);
|
||||||
|
|
||||||
|
match pt.x {
|
||||||
|
0 => {
|
||||||
|
if pt.y == 0 {
|
||||||
|
Some(self.opening_port.clone()
|
||||||
|
.map_item(move |_, atom| atom.add_style_back(list_style)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
if item_idx < l {
|
||||||
|
Some(self.items.get(&item_idx)?.map_item(move |_, atom| atom.add_style_back(item_style)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
if (l == 0 && pt.y == 0) || (item_idx+1 == l) {
|
||||||
|
Some(self.closing_port.clone()
|
||||||
|
.map_item(move |_, atom| atom.add_style_back(list_style)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VerticalSexprDecorator {
|
||||||
|
pub fn new(
|
||||||
|
opening: &str,
|
||||||
|
closing: &str,
|
||||||
|
level: usize,
|
||||||
|
items_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
|
||||||
|
out_port: InnerViewPort<dyn GridView<Item = OuterViewPort<dyn TerminalView>>>
|
||||||
|
) -> Arc<RwLock<Self>> {
|
||||||
|
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
|
||||||
|
|
||||||
|
let li = Arc::new(RwLock::new(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(
|
||||||
|
&Point2::new(1, *item_idx as i16)
|
||||||
|
);
|
||||||
|
s.cast.notify(
|
||||||
|
&Point2::new(2, *item_idx as i16 - 1)
|
||||||
|
);
|
||||||
|
s.cast.notify(
|
||||||
|
&Point2::new(2, *item_idx as i16)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
list_style: TerminalStyle::fg_color(
|
||||||
|
match level {
|
||||||
|
0 => (200, 120, 10),
|
||||||
|
1 => (120, 200, 10),
|
||||||
|
_ => (255, 255, 255)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
item_style: TerminalStyle::fg_color(
|
||||||
|
match level {
|
||||||
|
_ => (255, 255, 255)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cast: out_port.get_broadcast(),
|
||||||
|
proj_helper
|
||||||
|
}));
|
||||||
|
|
||||||
|
li.write().unwrap().proj_helper.set_proj(&li);
|
||||||
|
|
||||||
|
out_port.set_view(Some(li.clone()));
|
||||||
|
li
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub trait SExprView {
|
||||||
|
fn horizontal_sexpr_view(&self, level: usize) -> OuterViewPort<dyn TerminalView>;
|
||||||
|
fn vertical_bar_view(&self, level: usize) -> OuterViewPort<dyn TerminalView>;
|
||||||
|
fn vertical_sexpr_view(&self, level: usize) -> OuterViewPort<dyn TerminalView>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SExprView for OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> {
|
||||||
|
fn horizontal_sexpr_view(&self, level: usize) -> OuterViewPort<dyn TerminalView> {
|
||||||
|
let port = ViewPort::new();
|
||||||
|
ListDecorator::new(
|
||||||
|
"(", ")", " ",
|
||||||
|
level,
|
||||||
|
self.clone(),
|
||||||
|
port.inner()
|
||||||
|
);
|
||||||
|
|
||||||
|
port.into_outer()
|
||||||
|
.to_grid_horizontal()
|
||||||
|
.flatten()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertical_bar_view(&self, level: usize) -> OuterViewPort<dyn TerminalView> {
|
||||||
|
let port = ViewPort::new();
|
||||||
|
ListDecorator::new(
|
||||||
|
"Λ", "V", "|",
|
||||||
|
level,
|
||||||
|
self.clone(),
|
||||||
|
port.inner()
|
||||||
|
);
|
||||||
|
|
||||||
|
port.into_outer()
|
||||||
|
.to_grid_vertical()
|
||||||
|
.flatten()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertical_sexpr_view(&self, level: usize) -> OuterViewPort<dyn TerminalView> {
|
||||||
|
let port = ViewPort::new();
|
||||||
|
VerticalSexprDecorator::new(
|
||||||
|
"(", ")",
|
||||||
|
level,
|
||||||
|
self.clone(),
|
||||||
|
port.inner()
|
||||||
|
);
|
||||||
|
port.into_outer()
|
||||||
|
.flatten()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,167 +0,0 @@
|
||||||
|
|
||||||
use {
|
|
||||||
std::sync::Arc,
|
|
||||||
std::sync::RwLock,
|
|
||||||
nested::{
|
|
||||||
core::{
|
|
||||||
View,
|
|
||||||
ViewPort,
|
|
||||||
OuterViewPort,
|
|
||||||
InnerViewPort,
|
|
||||||
Observer,
|
|
||||||
ObserverBroadcast
|
|
||||||
},
|
|
||||||
sequence::{SequenceView, VecBuffer},
|
|
||||||
terminal::{Terminal, TerminalAtom, TerminalStyle},
|
|
||||||
projection::ProjectionHelper
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct ListDecorator {
|
|
||||||
opening_port: OuterViewPort<dyn SequenceView<Item = char>>,
|
|
||||||
closing_port: OuterViewPort<dyn SequenceView<Item = char>>,
|
|
||||||
delim_port: OuterViewPort<dyn SequenceView<Item = char>>,
|
|
||||||
items: Arc<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>>,
|
|
||||||
list_style: TerminalStyle,
|
|
||||||
item_style: TerminalStyle,
|
|
||||||
|
|
||||||
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>>>>,
|
|
||||||
proj_helper: ProjectionHelper<Self>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl View for ListDecorator {
|
|
||||||
type Msg = usize;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SequenceView for ListDecorator {
|
|
||||||
type Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>;
|
|
||||||
|
|
||||||
fn len(&self) -> Option<usize> {
|
|
||||||
Some(self.items.len()? * 2 + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(&self, idx: &usize) -> Option<Self::Item> {
|
|
||||||
let item_idx = idx / 2;
|
|
||||||
let list_style = self.list_style.clone();
|
|
||||||
let item_style = self.item_style.clone();
|
|
||||||
Some(
|
|
||||||
if idx % 2 == 0 {
|
|
||||||
if item_idx == 0 {
|
|
||||||
self.opening_port.clone()
|
|
||||||
} else if item_idx == self.items.len().unwrap_or(0) {
|
|
||||||
self.closing_port.clone()
|
|
||||||
} else {
|
|
||||||
self.delim_port.clone()
|
|
||||||
}
|
|
||||||
.map(move |c| TerminalAtom::new(*c, list_style))
|
|
||||||
} else {
|
|
||||||
self.items
|
|
||||||
.get(&item_idx)?
|
|
||||||
.map(move |atom| atom.add_style_back(item_style))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ListDecorator {
|
|
||||||
pub fn new(
|
|
||||||
opening_port: OuterViewPort<dyn SequenceView<Item = char>>,
|
|
||||||
closing_port: OuterViewPort<dyn SequenceView<Item = char>>,
|
|
||||||
delim_port: OuterViewPort<dyn SequenceView<Item = char>>,
|
|
||||||
items_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>>,
|
|
||||||
list_style: TerminalStyle,
|
|
||||||
item_style: TerminalStyle,
|
|
||||||
out_port: InnerViewPort<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>>
|
|
||||||
) -> Arc<RwLock<Self>> {
|
|
||||||
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
|
|
||||||
|
|
||||||
let li = Arc::new(RwLock::new(ListDecorator {
|
|
||||||
opening_port,
|
|
||||||
closing_port,
|
|
||||||
delim_port,
|
|
||||||
items: proj_helper.new_sequence_arg(
|
|
||||||
items_port,
|
|
||||||
|s: &mut Self, item_idx| {
|
|
||||||
s.cast.notify(&(item_idx * 2));
|
|
||||||
s.cast.notify(&(item_idx * 2 + 1));
|
|
||||||
}
|
|
||||||
),
|
|
||||||
list_style,
|
|
||||||
item_style,
|
|
||||||
cast: out_port.get_broadcast(),
|
|
||||||
proj_helper
|
|
||||||
}));
|
|
||||||
|
|
||||||
out_port.set_view(Some(li.clone()));
|
|
||||||
li
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn lisp_style(
|
|
||||||
level: usize,
|
|
||||||
items_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>>,
|
|
||||||
out_port: InnerViewPort<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>>
|
|
||||||
) -> Arc<RwLock<Self>> {
|
|
||||||
let opening_port = ViewPort::new();
|
|
||||||
let opening = VecBuffer::<char>::with_data("(".chars().collect(), opening_port.inner());
|
|
||||||
|
|
||||||
let closing_port = ViewPort::new();
|
|
||||||
let closing = VecBuffer::<char>::with_data(")".chars().collect(), closing_port.inner());
|
|
||||||
|
|
||||||
let delim_port = ViewPort::new();
|
|
||||||
let delim = VecBuffer::<char>::with_data(" ".chars().collect(), delim_port.inner());
|
|
||||||
|
|
||||||
Self::new(
|
|
||||||
opening_port.outer().to_sequence(),
|
|
||||||
closing_port.outer().to_sequence(),
|
|
||||||
delim_port.outer().to_sequence(),
|
|
||||||
items_port,
|
|
||||||
TerminalStyle::fg_color(
|
|
||||||
match level {
|
|
||||||
0 => (200, 120, 10),
|
|
||||||
1 => (120, 200, 10),
|
|
||||||
_ => (255, 255, 255)
|
|
||||||
}
|
|
||||||
),
|
|
||||||
TerminalStyle::fg_color(
|
|
||||||
match level {
|
|
||||||
_ => (255, 255, 255)
|
|
||||||
}
|
|
||||||
),
|
|
||||||
out_port
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn c_style(
|
|
||||||
level: usize,
|
|
||||||
items_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>>,
|
|
||||||
out_port: InnerViewPort<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>>
|
|
||||||
) -> Arc<RwLock<Self>> {
|
|
||||||
let opening_port = ViewPort::new();
|
|
||||||
let opening = VecBuffer::<char>::with_data("{".chars().collect(), opening_port.inner());
|
|
||||||
|
|
||||||
let closing_port = ViewPort::new();
|
|
||||||
let closing = VecBuffer::<char>::with_data("}".chars().collect(), closing_port.inner());
|
|
||||||
|
|
||||||
let delim_port = ViewPort::new();
|
|
||||||
let delim = VecBuffer::<char>::with_data(", ".chars().collect(), delim_port.inner());
|
|
||||||
|
|
||||||
Self::new(
|
|
||||||
opening_port.outer().to_sequence(),
|
|
||||||
closing_port.outer().to_sequence(),
|
|
||||||
delim_port.outer().to_sequence(),
|
|
||||||
items_port,
|
|
||||||
TerminalStyle::fg_color(
|
|
||||||
match level {
|
|
||||||
_ => (255, 255, 255)
|
|
||||||
}
|
|
||||||
),
|
|
||||||
TerminalStyle::fg_color(
|
|
||||||
match level {
|
|
||||||
_ => (255, 255, 255)
|
|
||||||
}
|
|
||||||
),
|
|
||||||
out_port
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,30 +1,53 @@
|
||||||
use {
|
|
||||||
std::sync::RwLock,
|
//mod monstera;
|
||||||
cgmath::Point2,
|
|
||||||
|
use{
|
||||||
|
std::sync::{Arc, RwLock},
|
||||||
|
cgmath::{Point2, Vector2},
|
||||||
termion::event::{Event, Key},
|
termion::event::{Event, Key},
|
||||||
nested::{
|
nested::{
|
||||||
core::{
|
core::{
|
||||||
|
View,
|
||||||
ViewPort,
|
ViewPort,
|
||||||
OuterViewPort,
|
OuterViewPort,
|
||||||
context::{
|
Observer,
|
||||||
ReprTree,
|
ObserverExt,
|
||||||
Object,
|
context::{ReprTree, Object, MorphismType, MorphismMode, Context},
|
||||||
MorphismType,
|
port::{UpdateTask}},
|
||||||
MorphismMode,
|
index::{IndexView},
|
||||||
Context
|
sequence::{SequenceView},
|
||||||
},
|
vec::{VecBuffer},
|
||||||
port::{
|
|
||||||
UpdateTask
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sequence::{SequenceView, VecBuffer},
|
|
||||||
integer::{RadixProjection},
|
integer::{RadixProjection},
|
||||||
terminal::{Terminal, TerminalAtom, TerminalStyle, TerminalCompositor, TerminalEvent},
|
terminal::{
|
||||||
string_editor::StringEditor
|
Terminal,
|
||||||
|
TerminalStyle,
|
||||||
|
TerminalAtom,
|
||||||
|
TerminalCompositor,
|
||||||
|
TerminalEvent,
|
||||||
|
make_label,
|
||||||
|
TerminalView,
|
||||||
|
TerminalEditor},
|
||||||
|
string_editor::StringEditor,
|
||||||
|
list::{SExprView, ListEditor}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod list;
|
struct GridFill<T: Send + Sync + Clone>(T);
|
||||||
|
impl<T: Send + Sync + Clone> View for GridFill<T> {
|
||||||
|
type Msg = Point2<i16>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Send + Sync + Clone> IndexView<Point2<i16>> for GridFill<T> {
|
||||||
|
type Item = T;
|
||||||
|
|
||||||
|
fn area(&self) -> Option<Vec<Point2<i16>>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&self, _: &Point2<i16>) -> Option<T> {
|
||||||
|
Some(self.0.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
@ -58,25 +81,27 @@ write::
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let mut args = std::env::args();
|
let mut args = std::env::args();
|
||||||
|
/*
|
||||||
let arg0_port = ViewPort::new();
|
let arg0_port = ViewPort::new();
|
||||||
let _arg0 = VecBuffer::<char>::with_data(
|
let _arg0 = VecBuffer::<char>::with_data(
|
||||||
args.next().expect("Arg $0 missing!")
|
args.next().expect("Arg $0 missing!")
|
||||||
.chars().collect::<Vec<char>>(),
|
.chars().collect::<Vec<char>>(),
|
||||||
arg0_port.inner()
|
arg0_port.inner()
|
||||||
);
|
);
|
||||||
/*
|
*/
|
||||||
let arg1_vec_port = ViewPort::new();
|
let arg1_vec_port = ViewPort::new();
|
||||||
let mut arg1 = VecBuffer::<char>::with_data(
|
let mut arg1 = VecBuffer::<char>::with_data(
|
||||||
|
vec!['1'],
|
||||||
|
/*
|
||||||
args.next().expect("Arg $1 missing!")
|
args.next().expect("Arg $1 missing!")
|
||||||
.chars().collect::<Vec<char>>(),
|
.chars().collect::<Vec<char>>(),
|
||||||
|
*/
|
||||||
arg1_vec_port.inner()
|
arg1_vec_port.inner()
|
||||||
);
|
);
|
||||||
*/
|
/*
|
||||||
|
let _arg1_vec = args.next().expect("Arg $1 missing!")
|
||||||
let arg1_vec = args.next().expect("Arg $1 missing!")
|
|
||||||
.chars().collect::<Vec<char>>();
|
.chars().collect::<Vec<char>>();
|
||||||
|
*/
|
||||||
let term_port = ViewPort::new();
|
let term_port = ViewPort::new();
|
||||||
let compositor = TerminalCompositor::new(term_port.inner());
|
let compositor = TerminalCompositor::new(term_port.inner());
|
||||||
|
|
||||||
|
@ -247,12 +272,43 @@ write::
|
||||||
arg1_hex_unic_port.clone().into()
|
arg1_hex_unic_port.clone().into()
|
||||||
);
|
);
|
||||||
|
|
||||||
compositor.write().unwrap().push(
|
let magic = make_label("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>")
|
||||||
ed.insert_view()
|
.map_item(
|
||||||
.map_key(
|
|pos, atom|
|
||||||
|pt| Point2::new(40 as i16 - pt.x, 1 as i16),
|
atom.add_style_back(
|
||||||
|pt| if pt.y == 1 { Some(Point2::new(40 as i16 - pt.x, 0)) } else { None }
|
TerminalStyle::fg_color(
|
||||||
|
(5,
|
||||||
|
((80+(pos.x*30)%100) as u8),
|
||||||
|
(55+(pos.x*15)%180) as u8)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
compositor.write().unwrap().push(magic.offset(Vector2::new(40, 4)));
|
||||||
|
//compositor.write().unwrap().push(magic.offset(Vector2::new(40, 20)));
|
||||||
|
/*
|
||||||
|
let monstera_port = monstera::make_monstera();
|
||||||
|
compositor.write().unwrap().push(monstera_port.clone());
|
||||||
|
compositor.write().unwrap().push(monstera_port.offset(Vector2::new(83,0)));
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
// list views
|
||||||
|
{
|
||||||
|
let items_port = ViewPort::new();
|
||||||
|
let items = VecBuffer::with_data(
|
||||||
|
vec![
|
||||||
|
arg1_hex_unic_port.clone()
|
||||||
|
.map(|c| TerminalAtom::from(c))
|
||||||
|
.to_index()
|
||||||
|
.map_key(
|
||||||
|
|idx| Point2::new(*idx as i16, 0 as i16),
|
||||||
|
|pt| if pt.y == 0 { Some(pt.x as usize) } else { None }
|
||||||
|
),
|
||||||
|
ed.insert_view()
|
||||||
.map_item(
|
.map_item(
|
||||||
|_pos, atom|
|
|_pos, atom|
|
||||||
TerminalAtom::new(
|
TerminalAtom::new(
|
||||||
|
@ -269,180 +325,189 @@ write::
|
||||||
} else {
|
} else {
|
||||||
(0, 0, 0)
|
(0, 0, 0)
|
||||||
}
|
}
|
||||||
|
).add(
|
||||||
|
TerminalStyle::bg_color((0,0,0))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
),
|
||||||
);
|
|
||||||
|
|
||||||
let opening_port = ViewPort::new();
|
|
||||||
let opening = VecBuffer::<char>::with_data("]".chars().collect(), opening_port.inner());
|
|
||||||
|
|
||||||
let dec_label_port = ViewPort::new();
|
|
||||||
let dec_label = VecBuffer::<char>::with_data("d0".chars().collect(), dec_label_port.inner());
|
|
||||||
|
|
||||||
let hex_label_port = ViewPort::new();
|
|
||||||
let hex_label = VecBuffer::<char>::with_data("x0".chars().collect(), hex_label_port.inner());
|
|
||||||
|
|
||||||
let delim_port = ViewPort::new();
|
|
||||||
let delim = VecBuffer::<char>::with_data(",".chars().collect(), delim_port.inner());
|
|
||||||
|
|
||||||
let closing_port = ViewPort::new();
|
|
||||||
let closing = VecBuffer::<char>::with_data("[".chars().collect(), closing_port.inner());
|
|
||||||
for c in arg1_vec {
|
|
||||||
ed.insert(c);
|
|
||||||
ed.prev();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let tree_port = ViewPort::new();
|
|
||||||
let mut tree = VecBuffer::with_data(
|
|
||||||
vec![
|
|
||||||
opening_port.outer()
|
|
||||||
.to_sequence()
|
|
||||||
.map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((170, 170, 30)))),
|
|
||||||
|
|
||||||
arg1_dec_mint_port
|
|
||||||
.map(|val| char::from_digit(*val as u32, 16).unwrap())
|
|
||||||
.map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((255, 255, 255)))),
|
|
||||||
|
|
||||||
dec_label_port.outer()
|
|
||||||
.to_sequence()
|
|
||||||
.map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((170, 170, 170)))),
|
|
||||||
|
|
||||||
delim_port.outer()
|
|
||||||
.to_sequence()
|
|
||||||
.map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((170, 170, 30)))),
|
|
||||||
|
|
||||||
arg1_hex_unic_port.clone()
|
arg1_hex_unic_port.clone()
|
||||||
.map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((255, 255, 255)))),
|
.map(|c| TerminalAtom::from(c))
|
||||||
|
|
||||||
hex_label_port.outer()
|
|
||||||
.to_sequence()
|
|
||||||
.map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((170, 170, 170)))),
|
|
||||||
|
|
||||||
closing_port.outer()
|
|
||||||
.to_sequence()
|
|
||||||
.map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((170, 170, 30)))),
|
|
||||||
],
|
|
||||||
tree_port.inner()
|
|
||||||
);
|
|
||||||
|
|
||||||
compositor.write().unwrap().push(
|
|
||||||
tree_port.outer()
|
|
||||||
.to_sequence()
|
|
||||||
.flatten()
|
|
||||||
.to_index()
|
.to_index()
|
||||||
.map_key(
|
.map_key(
|
||||||
|idx| Point2::new(40 - *idx as i16, 2 as i16),
|
|idx| Point2::new(*idx as i16, 0 as i16),
|
||||||
|pt| if pt.y == 2 { Some(40 - pt.x as usize) } else { None }
|
|pt| if pt.y == 0 { Some(pt.x as usize) } else { None }
|
||||||
)
|
),
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let items_port = ViewPort::new();
|
|
||||||
let items = VecBuffer::with_data(
|
|
||||||
vec![
|
|
||||||
arg1_dec_mint_port
|
|
||||||
.map(|val| char::from_digit(*val as u32, 16).unwrap())
|
|
||||||
.map(|c| TerminalAtom::from(c)),
|
|
||||||
arg1_hex_unic_port.clone()
|
|
||||||
.map(|c| TerminalAtom::from(c)),
|
|
||||||
arg1_hex_unic_port.clone()
|
|
||||||
.map(|c| TerminalAtom::from(c)),
|
|
||||||
],
|
],
|
||||||
items_port.inner()
|
items_port.inner()
|
||||||
);
|
);
|
||||||
|
|
||||||
let liport = ViewPort::new();
|
|
||||||
let list_decorator = list::ListDecorator::lisp_style(
|
|
||||||
1,
|
|
||||||
items_port.outer().to_sequence(),
|
|
||||||
liport.inner()
|
|
||||||
);
|
|
||||||
|
|
||||||
let par_items_port = ViewPort::new();
|
let par_items_port = ViewPort::new();
|
||||||
let par_items = VecBuffer::with_data(
|
let par_items = VecBuffer::with_data(
|
||||||
vec![
|
vec![
|
||||||
liport.outer().flatten(),
|
items_port.outer().to_sequence().sexpr_view(1),
|
||||||
arg1_hex_unic_port.clone()
|
arg1_hex_unic_port.clone()
|
||||||
.map(|c| TerminalAtom::from(c)),
|
.map(|c| TerminalAtom::from(c))
|
||||||
|
.to_index()
|
||||||
|
.map_key(
|
||||||
|
|idx| Point2::new(*idx as i16, 0 as i16),
|
||||||
|
|pt| if pt.y == 0 { Some(pt.x as usize) } else { None }
|
||||||
|
),
|
||||||
],
|
],
|
||||||
par_items_port.inner()
|
par_items_port.inner()
|
||||||
);
|
);
|
||||||
|
|
||||||
let par_liport = ViewPort::new();
|
|
||||||
let par_list_decorator = list::ListDecorator::lisp_style(
|
|
||||||
0,
|
|
||||||
par_items_port.outer().to_sequence(),
|
|
||||||
par_liport.inner()
|
|
||||||
);
|
|
||||||
|
|
||||||
compositor.write().unwrap().push(
|
compositor.write().unwrap().push(
|
||||||
par_liport.outer()
|
par_items_port.outer()
|
||||||
.flatten()
|
.to_sequence()
|
||||||
.to_index()
|
.sexpr_view(0)
|
||||||
.map_key(
|
.offset(Vector2::new(45, 5))
|
||||||
|idx| Point2::new(*idx as i16, 3),
|
|
||||||
|pt| if pt.y == 3 { Some(pt.x as usize) } else { None }
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let magic_vec_port = ViewPort::new();
|
for c in _arg1_vec {
|
||||||
let _magic_vec = VecBuffer::with_data("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>".chars().collect::<Vec<char>>(), magic_vec_port.inner());
|
ed.insert(c);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
let cur_size_port = ViewPort::new();
|
||||||
|
let mut cur_size = nested::singleton::SingletonBuffer::new(Vector2::new(10, 10), cur_size_port.inner());
|
||||||
|
|
||||||
|
// compositor.write().unwrap()
|
||||||
|
// .push(
|
||||||
|
let label_port = cur_size_port.outer()
|
||||||
|
.map(
|
||||||
|
|size| make_label(format!("Current Size: {:?}", size).as_str())
|
||||||
|
);
|
||||||
|
// );
|
||||||
|
|
||||||
|
//term_port.update();
|
||||||
|
//eprintln!("start loop:");
|
||||||
|
|
||||||
|
{
|
||||||
|
// let history_port = ViewPort::new();
|
||||||
|
// let mut history = VecBuffer::new(history_port.inner());
|
||||||
|
/*
|
||||||
|
compositor.write().unwrap().push(
|
||||||
|
history_port.into_outer()
|
||||||
|
.to_sequence()
|
||||||
|
.map(
|
||||||
|
|
|
||||||
|
)
|
||||||
|
.to_grid_vertical()
|
||||||
|
.flatten()
|
||||||
|
.offset(Vector2::new(45, 5))
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
let mut y = 5;
|
||||||
|
|
||||||
|
|
||||||
|
// TypeEditor
|
||||||
|
|
||||||
|
let make_sub_editor = || {
|
||||||
|
std::sync::Arc::new(std::sync::RwLock::new(StringEditor::new()))
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut te = ListEditor::new(make_sub_editor.clone());
|
||||||
|
|
||||||
compositor.write().unwrap().push(
|
compositor.write().unwrap().push(
|
||||||
magic_vec_port.outer()
|
te.segment_seq.horizontal_sexpr_view(0).offset(cgmath::Vector2::new(40,y))
|
||||||
.to_sequence()
|
|
||||||
.to_index()
|
|
||||||
.map_item(
|
|
||||||
|idx, c| TerminalAtom::new(
|
|
||||||
*c,
|
|
||||||
TerminalStyle::fg_color((5, ((80+(idx*30)%100) as u8), (55+(idx*15)%180) as u8))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.map_key(
|
|
||||||
|idx| Point2::new(*idx as i16, 4),
|
|
||||||
|pt| if pt.y == 4 { Some(pt.x as usize) } else { None }
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
y += 1;
|
||||||
|
|
||||||
compositor.write().unwrap().push(
|
let mut p = te.get_data_port().map(|string_editor| string_editor.read().unwrap().get_data_port());
|
||||||
magic_vec_port.outer()
|
|
||||||
.to_sequence()
|
|
||||||
.to_index()
|
|
||||||
.map_item(
|
|
||||||
|idx, c| TerminalAtom::new(
|
|
||||||
*c,
|
|
||||||
TerminalStyle::fg_color((5, ((80+(idx*30)%100) as u8), (55+(idx*15)%180) as u8))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.map_key(
|
|
||||||
|idx| Point2::new(*idx as i16, 0),
|
|
||||||
|pt| if pt.y == 0 { Some(pt.x as usize) } else { None }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
term_port.update();
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match term.next_event().await {
|
|
||||||
TerminalEvent::Input(Event::Key(Key::Left)) => ed.next(),
|
|
||||||
TerminalEvent::Input(Event::Key(Key::Right)) => ed.prev(),
|
|
||||||
TerminalEvent::Input(Event::Key(Key::Home)) => ed.goto_end(),
|
|
||||||
TerminalEvent::Input(Event::Key(Key::End)) => ed.goto(0),
|
|
||||||
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {},
|
|
||||||
TerminalEvent::Input(Event::Key(Key::Char(c))) => { ed.insert(c); ed.prev(); },
|
|
||||||
TerminalEvent::Input(Event::Key(Key::Delete)) => ed.delete_prev(),
|
|
||||||
TerminalEvent::Input(Event::Key(Key::Backspace)) => ed.delete(),
|
|
||||||
TerminalEvent::Input(Event::Key(Key::Ctrl('c'))) => break,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
term_port.update();
|
term_port.update();
|
||||||
|
match term.next_event().await {
|
||||||
|
TerminalEvent::Resize(new_size) => {
|
||||||
|
cur_size.set(new_size);
|
||||||
|
term_port.inner().get_broadcast().notify_each(
|
||||||
|
nested::grid::GridWindowIterator::from(
|
||||||
|
Point2::new(0,0) .. Point2::new(new_size.x, new_size.y)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Ctrl('c'))) |
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Ctrl('g'))) |
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Ctrl('d'))) => break,
|
||||||
|
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
|
||||||
|
let mut strings = Vec::new();
|
||||||
|
|
||||||
|
let v = p.get_view().unwrap();
|
||||||
|
for i in 0 .. v.len().unwrap_or(0) {
|
||||||
|
strings.push(
|
||||||
|
v
|
||||||
|
.get(&i).unwrap()
|
||||||
|
.get_view().unwrap()
|
||||||
|
.read().unwrap()
|
||||||
|
.iter().collect::<String>()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(term);
|
if strings.len() == 0 { continue; }
|
||||||
|
|
||||||
|
if let Ok(output) =
|
||||||
|
std::process::Command::new(strings[0].as_str())
|
||||||
|
.args(&strings[1..])
|
||||||
|
.output()
|
||||||
|
{
|
||||||
|
// take output and update terminal view
|
||||||
|
let mut line_port = ViewPort::new();
|
||||||
|
let mut line = VecBuffer::new(line_port.inner());
|
||||||
|
for byte in output.stdout {
|
||||||
|
match byte {
|
||||||
|
b'\n' => {
|
||||||
|
compositor.write().unwrap().push(
|
||||||
|
line_port.outer()
|
||||||
|
.to_sequence()
|
||||||
|
.map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((130,90,90))))
|
||||||
|
.to_grid_horizontal()
|
||||||
|
.offset(Vector2::new(45, y))
|
||||||
|
);
|
||||||
|
y += 1;
|
||||||
|
line_port = ViewPort::new();
|
||||||
|
line = VecBuffer::new(line_port.inner());
|
||||||
|
}
|
||||||
|
byte => {
|
||||||
|
line.push(byte as char);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
compositor.write().unwrap().push(
|
||||||
|
make_label("Command not found")
|
||||||
|
.map_item(|idx, a| a.add_style_back(TerminalStyle::fg_color((200,0,0))))
|
||||||
|
.offset(Vector2::new(45, y))
|
||||||
|
);
|
||||||
|
y+=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
te.handle_terminal_event(
|
||||||
|
&TerminalEvent::Input(Event::Key(Key::Up))
|
||||||
|
);
|
||||||
|
te.handle_terminal_event(
|
||||||
|
&TerminalEvent::Input(Event::Key(Key::Home))
|
||||||
|
);
|
||||||
|
te = ListEditor::new(make_sub_editor.clone());
|
||||||
|
|
||||||
|
compositor.write().unwrap().push(magic.offset(Vector2::new(40, y)));
|
||||||
|
y += 1;
|
||||||
|
compositor.write().unwrap().push(
|
||||||
|
te.segment_seq.horizontal_sexpr_view(0).offset(cgmath::Vector2::new(40,y))
|
||||||
|
);
|
||||||
|
y += 1;
|
||||||
|
|
||||||
|
p = te.get_data_port().map(|string_editor| string_editor.read().unwrap().get_data_port());
|
||||||
|
},
|
||||||
|
ev => {
|
||||||
|
te.handle_terminal_event(&ev);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//drop(term);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue