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 terminal;
|
||||
pub mod integer;
|
||||
pub mod list;
|
||||
|
||||
pub mod string_editor;
|
||||
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 @@
|
|||
|
||||
//mod monstera;
|
||||
|
||||
use{
|
||||
std::sync::RwLock,
|
||||
cgmath::Point2,
|
||||
std::sync::{Arc, RwLock},
|
||||
cgmath::{Point2, Vector2},
|
||||
termion::event::{Event, Key},
|
||||
nested::{
|
||||
core::{
|
||||
View,
|
||||
ViewPort,
|
||||
OuterViewPort,
|
||||
context::{
|
||||
ReprTree,
|
||||
Object,
|
||||
MorphismType,
|
||||
MorphismMode,
|
||||
Context
|
||||
},
|
||||
port::{
|
||||
UpdateTask
|
||||
}
|
||||
},
|
||||
sequence::{SequenceView, VecBuffer},
|
||||
Observer,
|
||||
ObserverExt,
|
||||
context::{ReprTree, Object, MorphismType, MorphismMode, Context},
|
||||
port::{UpdateTask}},
|
||||
index::{IndexView},
|
||||
sequence::{SequenceView},
|
||||
vec::{VecBuffer},
|
||||
integer::{RadixProjection},
|
||||
terminal::{Terminal, TerminalAtom, TerminalStyle, TerminalCompositor, TerminalEvent},
|
||||
string_editor::StringEditor
|
||||
terminal::{
|
||||
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 fn main() {
|
||||
|
@ -58,25 +81,27 @@ write::
|
|||
*/
|
||||
|
||||
let mut args = std::env::args();
|
||||
|
||||
/*
|
||||
let arg0_port = ViewPort::new();
|
||||
let _arg0 = VecBuffer::<char>::with_data(
|
||||
args.next().expect("Arg $0 missing!")
|
||||
.chars().collect::<Vec<char>>(),
|
||||
arg0_port.inner()
|
||||
);
|
||||
/*
|
||||
*/
|
||||
let arg1_vec_port = ViewPort::new();
|
||||
let mut arg1 = VecBuffer::<char>::with_data(
|
||||
vec!['1'],
|
||||
/*
|
||||
args.next().expect("Arg $1 missing!")
|
||||
.chars().collect::<Vec<char>>(),
|
||||
*/
|
||||
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>>();
|
||||
|
||||
*/
|
||||
let term_port = ViewPort::new();
|
||||
let compositor = TerminalCompositor::new(term_port.inner());
|
||||
|
||||
|
@ -247,12 +272,43 @@ write::
|
|||
arg1_hex_unic_port.clone().into()
|
||||
);
|
||||
|
||||
compositor.write().unwrap().push(
|
||||
ed.insert_view()
|
||||
.map_key(
|
||||
|pt| Point2::new(40 as i16 - pt.x, 1 as i16),
|
||||
|pt| if pt.y == 1 { Some(Point2::new(40 as i16 - pt.x, 0)) } else { None }
|
||||
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)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
{
|
||||
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(
|
||||
|_pos, atom|
|
||||
TerminalAtom::new(
|
||||
|
@ -269,180 +325,189 @@ write::
|
|||
} else {
|
||||
(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()
|
||||
.map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((255, 255, 255)))),
|
||||
|
||||
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()
|
||||
.map(|c| TerminalAtom::from(c))
|
||||
.to_index()
|
||||
.map_key(
|
||||
|idx| Point2::new(40 - *idx as i16, 2 as i16),
|
||||
|pt| if pt.y == 2 { Some(40 - 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)),
|
||||
|idx| Point2::new(*idx as i16, 0 as i16),
|
||||
|pt| if pt.y == 0 { Some(pt.x as usize) } else { None }
|
||||
),
|
||||
],
|
||||
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 = VecBuffer::with_data(
|
||||
vec![
|
||||
liport.outer().flatten(),
|
||||
items_port.outer().to_sequence().sexpr_view(1),
|
||||
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()
|
||||
);
|
||||
|
||||
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(
|
||||
par_liport.outer()
|
||||
.flatten()
|
||||
.to_index()
|
||||
.map_key(
|
||||
|idx| Point2::new(*idx as i16, 3),
|
||||
|pt| if pt.y == 3 { Some(pt.x as usize) } else { None }
|
||||
)
|
||||
par_items_port.outer()
|
||||
.to_sequence()
|
||||
.sexpr_view(0)
|
||||
.offset(Vector2::new(45, 5))
|
||||
);
|
||||
}
|
||||
|
||||
let magic_vec_port = ViewPort::new();
|
||||
let _magic_vec = VecBuffer::with_data("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>".chars().collect::<Vec<char>>(), magic_vec_port.inner());
|
||||
for c in _arg1_vec {
|
||||
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(
|
||||
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, 4),
|
||||
|pt| if pt.y == 4 { Some(pt.x as usize) } else { None }
|
||||
)
|
||||
te.segment_seq.horizontal_sexpr_view(0).offset(cgmath::Vector2::new(40,y))
|
||||
);
|
||||
y += 1;
|
||||
|
||||
compositor.write().unwrap().push(
|
||||
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();
|
||||
let mut p = te.get_data_port().map(|string_editor| string_editor.read().unwrap().get_data_port());
|
||||
|
||||
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();
|
||||
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