TreeNav trait

adapt ListEditor and StringEditor
This commit is contained in:
Michael Sippel 2021-08-15 04:27:09 +02:00
parent 127c43bca0
commit 603034a065
Signed by: senvas
GPG key ID: F96CF119C34B64A6
5 changed files with 393 additions and 208 deletions

View file

@ -12,6 +12,8 @@ pub mod terminal;
pub mod integer;
pub mod list;
pub mod tree_nav;
pub mod string_editor;
pub mod leveled_term_view;

View file

@ -18,6 +18,7 @@ use {
Context
}
},
tree_nav::{TreeNav, TreeNavResult, TerminalTreeEditor},
projection::ProjectionHelper,
singleton::{SingletonView, SingletonBuffer},
sequence::{SequenceView},
@ -62,8 +63,221 @@ where SubEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
segment_seq: OuterViewPort<dyn SequenceView<Item = ListEditorViewSegment>>,
}
impl<SubEditor, FnMakeItemEditor> TreeNav for ListEditor<SubEditor, FnMakeItemEditor>
where SubEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<SubEditor>>
{
fn up(&mut self) -> TreeNavResult {
match self.cursor.get() {
ListEditorCursor::Edit(idx) => {
let ce = self.data.get_mut(idx);
let mut cur_edit = ce.write().unwrap();
match cur_edit.up() {
TreeNavResult::Exit => {
self.cursor.set(ListEditorCursor::Select(idx));
}
TreeNavResult::Continue => {}
}
TreeNavResult::Continue
}
_ => {
self.cursor.set(ListEditorCursor::None);
TreeNavResult::Exit
}
}
}
fn goto(&mut self, tree_addr: Vec<usize>) -> TreeNavResult {
if tree_addr.len() == 1 {
if tree_addr[0] < self.data.len() {
match self.cursor.get() {
ListEditorCursor::None |
ListEditorCursor::Select(_) => {
self.cursor.set(ListEditorCursor::Select(tree_addr[0]));
}
ListEditorCursor::Insert(_) => {
self.cursor.set(ListEditorCursor::Insert(tree_addr[0]));
}
ListEditorCursor::Edit(_) => {
self.cursor.set(ListEditorCursor::Edit(tree_addr[0]));
}
}
TreeNavResult::Continue
} else {
TreeNavResult::Exit
}
} else if tree_addr.len() > 0 {
if tree_addr[0] < self.data.len() {
self.cursor.set(ListEditorCursor::Edit(tree_addr[0]));
let ce = self.data.get_mut(tree_addr[0]);
let mut cur_edit = ce.write().unwrap();
cur_edit.goto(tree_addr[1..].iter().cloned().collect());
TreeNavResult::Continue
} else {
TreeNavResult::Exit
}
} else {
self.cursor.set(ListEditorCursor::None);
TreeNavResult::Exit
}
}
fn goto_end(&mut self) -> TreeNavResult {
match self.cursor.get() {
ListEditorCursor::None |
ListEditorCursor::Insert(_) |
ListEditorCursor::Select(_) =>
self.goto(vec![ self.data.len()-1 ]),
ListEditorCursor::Edit(idx) => {
let ce = self.data.get_mut(idx);
let mut cur_edit = ce.write().unwrap();
match cur_edit.goto_end() {
TreeNavResult::Continue => TreeNavResult::Continue,
TreeNavResult::Exit => {
if idx+1 < self.data.len() {
self.cursor.set(ListEditorCursor::Edit(idx+1));
self.data.get_mut(idx+1).write().unwrap().goto_end();
TreeNavResult::Continue
} else {
self.cursor.set(ListEditorCursor::None);
TreeNavResult::Exit
}
}
}
}
}
}
fn goto_home(&mut self) -> TreeNavResult {
match self.cursor.get() {
ListEditorCursor::None |
ListEditorCursor::Insert(_) |
ListEditorCursor::Select(_) => self.goto(vec![ 0 ]),
ListEditorCursor::Edit(idx) => {
let ce = self.data.get_mut(idx);
let mut cur_edit = ce.write().unwrap();
match cur_edit.goto_home() {
TreeNavResult::Continue => TreeNavResult::Continue,
TreeNavResult::Exit => {
if idx > 0 {
self.cursor.set(ListEditorCursor::Edit(idx-1));
self.data.get_mut(idx-1).write().unwrap().goto_home();
TreeNavResult::Continue
} else {
self.cursor.set(ListEditorCursor::None);
TreeNavResult::Exit
}
}
}
}
_ => {
self.up();
TreeNavResult::Exit
}
}
}
fn dn(&mut self) -> TreeNavResult {
match self.cursor.get() {
ListEditorCursor::Select(idx) => {
self.data.get_mut(idx).write().unwrap().goto_home();
self.cursor.set(ListEditorCursor::Edit(idx));
}
_ => {}
}
TreeNavResult::Continue
}
fn pxev(&mut self) -> TreeNavResult {
match self.cursor.get() {
ListEditorCursor::None => TreeNavResult::Exit,
ListEditorCursor::Insert(idx) => {
if idx > 0 {
self.cursor.set(ListEditorCursor::Insert(idx-1));
TreeNavResult::Continue
} else {
self.cursor.set(ListEditorCursor::None);
TreeNavResult::Exit
}
}
ListEditorCursor::Select(idx) => {
if idx > 0 {
self.cursor.set(ListEditorCursor::Select(idx-1));
TreeNavResult::Continue
} else {
self.cursor.set(ListEditorCursor::None);
TreeNavResult::Exit
}
}
ListEditorCursor::Edit(idx) => {
let ce = self.data.get_mut(idx);
let mut cur_edit = ce.write().unwrap();
match cur_edit.pxev() {
TreeNavResult::Exit => {
if idx > 0 {
self.cursor.set(ListEditorCursor::Edit(idx-1));
self.data.get_mut(idx-1).write().unwrap().goto_end();
TreeNavResult::Continue
} else {
TreeNavResult::Exit
}
}
TreeNavResult::Continue => TreeNavResult::Continue
}
}
}
}
fn nexd(&mut self) -> TreeNavResult {
match self.cursor.get() {
ListEditorCursor::None => TreeNavResult::Exit,
ListEditorCursor::Insert(idx) => {
if idx < self.data.len() {
self.cursor.set(ListEditorCursor::Insert(idx+1));
TreeNavResult::Continue
} else {
TreeNavResult::Exit
}
}
ListEditorCursor::Select(idx) => {
if idx+1 < self.data.len() {
self.cursor.set(ListEditorCursor::Select(idx + 1));
TreeNavResult::Continue
} else {
TreeNavResult::Exit
}
}
ListEditorCursor::Edit(idx) => {
let ce = self.data.get_mut(idx);
let mut cur_edit = ce.write().unwrap();
match cur_edit.nexd() {
TreeNavResult::Exit => {
if idx+1 < self.data.len() {
self.cursor.set(ListEditorCursor::Edit(idx+1));
self.data.get_mut(idx+1).write().unwrap().goto_home();
TreeNavResult::Continue
} else {//if idx+1 == self.data.len() {
TreeNavResult::Exit
}
}
TreeNavResult::Continue => TreeNavResult::Continue
}
}
}
}
}
impl<SubEditor, FnMakeItemEditor> TerminalEditor for ListEditor<SubEditor, FnMakeItemEditor>
where SubEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
where SubEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<SubEditor>>
{
fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> {
@ -72,144 +286,51 @@ where SubEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
match self.cursor.get() {
ListEditorCursor::None => {
}
ListEditorCursor::Insert(idx) => {
self.data.insert(idx, (self.make_item_editor)());
let mut ce = self.data.get_mut(idx);
let mut cur_edit = ce.write().unwrap();
cur_edit.goto_home();
self.cursor.set(ListEditorCursor::Edit(idx));
cur_edit.handle_terminal_event(event);
}
ListEditorCursor::Edit(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));
}
TerminalEvent::Input(Event::Key(Key::Char(' '))) => {
// split..
self.data.insert(idx+1, (self.make_item_editor)());
self.data.get_mut(idx).write().unwrap().goto_end();
self.data.get_mut(idx+1).write().unwrap().goto_home();
self.cursor.set(ListEditorCursor::Edit(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);
let mut ce = self.data.get_mut(idx);
let mut cur_edit = ce.write().unwrap();
cur_edit.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 => {}
} else if idx == self.data.len() {
self.cursor.set(ListEditorCursor::Select(idx-1));
}
}
_=>{}
}
}
_ => {}
}
TerminalEditorResult::Continue
@ -404,10 +525,15 @@ where SubEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
pub fn vertical_sexpr_view(&self) -> OuterViewPort<dyn TerminalView> {
self.get_seg_seq_view().vertical_sexpr_view(0)
}
pub fn path_view(&self) -> OuterViewPort<dyn TerminalView> {
self.get_seg_seq_view()
.decorate("<", ">", "/", 1)
.decorate("<", ">", "/", 0)
.to_grid_horizontal()
.flatten()
}
pub fn string_view(&self) -> OuterViewPort<dyn TerminalView> {
self.get_seg_seq_view()
.decorate("\"", "\"", "", 1)
.to_grid_horizontal()
.flatten()
}

View file

@ -5,7 +5,8 @@ use {
core::{ViewPort, OuterViewPort},
singleton::{SingletonView, SingletonBuffer},
vec::VecBuffer,
terminal::{TerminalView, TerminalEvent, TerminalEditor, TerminalEditorResult}
terminal::{TerminalView, TerminalEvent, TerminalEditor, TerminalEditorResult},
tree_nav::{TreeNav, TreeNavResult}
}
};
@ -53,56 +54,89 @@ impl StringEditor {
self.cursor_port.outer()
}
pub fn goto(&mut self, new_pos: usize) -> TerminalEditorResult {
if new_pos <= self.data.len() {
self.cursor.set(Some(new_pos));
TerminalEditorResult::Continue
} else {
self.cursor.set(None);
TerminalEditorResult::Exit
}
}
pub fn goto_end(&mut self) -> TerminalEditorResult {
self.goto(self.data.len())
}
pub fn prev(&mut self) -> TerminalEditorResult {
let cur = self.cursor.get().unwrap_or(usize::MAX);
if cur > 0 {
self.cursor.set(Some(cur - 1));
TerminalEditorResult::Continue
} else {
self.cursor.set(None);
TerminalEditorResult::Exit
}
}
pub fn next(&mut self) -> TerminalEditorResult {
self.goto(self.cursor.get().unwrap_or(0) + 1)
}
pub fn insert(&mut self, c: char) -> TerminalEditorResult {
pub fn insert(&mut self, c: char) -> TreeNavResult {
self.data.insert(self.cursor.get().unwrap_or(0), c);
self.next()
self.nexd()
}
pub fn delete_prev(&mut self) -> TerminalEditorResult {
pub fn delete_prev(&mut self) -> TreeNavResult {
let cur = self.cursor.get().unwrap_or(0);
if cur <= self.data.len() && cur > 0 {
self.data.remove(cur-1);
}
self.prev()
self.pxev()
}
pub fn delete(&mut self) -> TerminalEditorResult {
pub fn delete(&mut self) -> TreeNavResult {
let cur = self.cursor.get().unwrap_or(0);
if cur < self.data.len() {
self.data.remove(cur);
TerminalEditorResult::Continue
TreeNavResult::Continue
} else {
self.cursor.set(None);
TerminalEditorResult::Exit
TreeNavResult::Exit
}
}
}
impl TreeNav for StringEditor {
fn goto(&mut self, tree_pos: Vec<usize>) -> TreeNavResult {
if tree_pos.len() == 1 {
let new_pos = tree_pos[0];
if new_pos <= self.data.len() {
self.cursor.set(Some(new_pos));
TreeNavResult::Continue
} else {
self.cursor.set(None);
TreeNavResult::Exit
}
} else {
self.cursor.set(None);
TreeNavResult::Exit
}
}
fn pxev(&mut self) -> TreeNavResult {
let cur = self.cursor.get().unwrap_or(usize::MAX);
if cur > 0 {
self.cursor.set(Some(cur - 1));
TreeNavResult::Continue
} else {
self.cursor.set(None);
TreeNavResult::Exit
}
}
fn nexd(&mut self) -> TreeNavResult {
self.goto(vec![ self.cursor.get().unwrap_or(0) + 1 ])
}
fn goto_end(&mut self) -> TreeNavResult {
if self.cursor.get() == Some(self.data.len()) {
self.up()
} else {
self.goto(vec![ self.data.len() ])
}
}
fn goto_home(&mut self) -> TreeNavResult {
if self.cursor.get() == Some(0) {
self.up()
} else {
self.goto(vec![ 0 ])
}
}
fn up(&mut self) -> TreeNavResult {
self.cursor.set(None);
TreeNavResult::Exit
}
fn dn(&mut self) -> TreeNavResult {
if self.cursor.get() == Some(0) {
self.up()
} else {
self.goto(vec![0])
}
}
}
@ -114,33 +148,19 @@ impl TerminalEditor for StringEditor {
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
match event {
TerminalEvent::Input(Event::Key(Key::Left)) => self.prev(),
TerminalEvent::Input(Event::Key(Key::Right)) => self.next(),
TerminalEvent::Input(Event::Key(Key::Up)) => {
self.cursor.set(None);
TerminalEditorResult::Exit
}
TerminalEvent::Input(Event::Key(Key::Down)) |
TerminalEvent::Input(Event::Key(Key::Home)) =>
if self.cursor.get() == Some(0) {
self.cursor.set(None);
TerminalEditorResult::Exit
} else {
self.goto(0)
},
TerminalEvent::Input(Event::Key(Key::End)) =>
if self.cursor.get() == Some(self.data.len()) {
self.cursor.set(None);
TerminalEditorResult::Exit
} else {
self.goto_end()
},
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => TerminalEditorResult::Continue,
TerminalEvent::Input(Event::Key(Key::Char(c))) => self.insert(*c),
TerminalEvent::Input(Event::Key(Key::Delete)) => self.delete(),
TerminalEvent::Input(Event::Key(Key::Backspace)) => self.delete_prev(),
TerminalEvent::Input(Event::Key(Key::Char(c))) => match self.insert(*c) {
TreeNavResult::Exit => TerminalEditorResult::Exit,
TreeNavResult::Continue => TerminalEditorResult::Continue
}
TerminalEvent::Input(Event::Key(Key::Delete)) => match self.delete() {
TreeNavResult::Exit => TerminalEditorResult::Exit,
TreeNavResult::Continue => TerminalEditorResult::Continue
}
TerminalEvent::Input(Event::Key(Key::Backspace)) => match self.delete_prev() {
TreeNavResult::Exit => TerminalEditorResult::Exit,
TreeNavResult::Continue => TerminalEditorResult::Continue
}
_ => TerminalEditorResult::Continue
}
}

41
nested/src/tree_nav.rs Normal file
View file

@ -0,0 +1,41 @@
#[derive(Eq, PartialEq)]
pub enum TreeNavResult {
Continue,
Exit
}
pub trait TreeNav {
fn up(&mut self) -> TreeNavResult {
TreeNavResult::Exit
}
fn dn(&mut self) -> TreeNavResult {
TreeNavResult::Exit
}
fn pxev(&mut self) -> TreeNavResult {
TreeNavResult::Exit
}
fn nexd(&mut self) -> TreeNavResult {
TreeNavResult::Exit
}
fn goto_home(&mut self) -> TreeNavResult {
TreeNavResult::Exit
}
fn goto_end(&mut self) -> TreeNavResult {
TreeNavResult::Exit
}
fn goto(&mut self, tree_addr: Vec<usize>) -> TreeNavResult {
TreeNavResult::Exit
}
}
use crate::terminal::{TerminalView, TerminalEditor};
pub trait TerminalTreeEditor = TerminalEditor + TreeNav;

View file

@ -28,6 +28,7 @@ use{
TerminalView,
TerminalEditor},
string_editor::StringEditor,
tree_nav::{TreeNav, TreeNavResult, TerminalTreeEditor},
list::{SExprView, ListEditor}
}
};
@ -297,25 +298,8 @@ write::
let cur_size_port = ViewPort::new();
let mut cur_size = nested::singleton::SingletonBuffer::new(Vector2::new(10, 10), cur_size_port.inner());
{
// 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 = || {
@ -346,6 +330,22 @@ write::
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::Left)) => {
if te.pxev() == TreeNavResult::Exit {
te.goto_home();
}
}
TerminalEvent::Input(Event::Key(Key::Right)) => {
if te.nexd() == TreeNavResult::Exit {
te.goto_end();
}
}
TerminalEvent::Input(Event::Key(Key::Up)) => { te.up(); }
TerminalEvent::Input(Event::Key(Key::Down)) => { te.dn(); }
TerminalEvent::Input(Event::Key(Key::Home)) => { te.goto_home(); }
TerminalEvent::Input(Event::Key(Key::End)) => { te.goto_end(); }
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
let mut strings = Vec::new();
@ -398,12 +398,8 @@ write::
y+=1;
}
te.handle_terminal_event(
&TerminalEvent::Input(Event::Key(Key::Up))
);
te.handle_terminal_event(
&TerminalEvent::Input(Event::Key(Key::Home))
);
te.up();
te.goto_home();
te = ListEditor::new(make_sub_editor.clone());
compositor.write().unwrap().push(magic.offset(Vector2::new(40, y)));