From 8b47a19f2a8f3952b50d2b5081aa2e61fce72f5f Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Mon, 21 Aug 2023 14:12:39 +0200
Subject: [PATCH] list editor: refactor event handling

---
 nested/src/editors/char/mod.rs        |   7 +-
 nested/src/editors/list/cmd.rs        |  52 ++++-
 nested/src/editors/list/editor.rs     |  56 ++---
 nested/src/editors/list/pty_editor.rs | 288 +++++++++-----------------
 4 files changed, 172 insertions(+), 231 deletions(-)

diff --git a/nested/src/editors/char/mod.rs b/nested/src/editors/char/mod.rs
index 6297b3c..708424e 100644
--- a/nested/src/editors/char/mod.rs
+++ b/nested/src/editors/char/mod.rs
@@ -26,10 +26,7 @@ impl ObjCommander for CharEditor {
         let cmd_obj = cmd_obj.read().unwrap();
         let cmd_type = cmd_obj.get_type().clone();
 
-        let char_type = (&self.ctx, "( Char )").into();
-        //let _term_event_type = (&ctx, "( TerminalEvent )").into();
-
-        if cmd_type == char_type {
+        if cmd_type == (&self.ctx, "( Char )").into() {
             if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
                 let value = cmd_view.get();
 
@@ -66,9 +63,7 @@ impl CharEditor {
 
     pub fn new_node(ctx0: Arc<RwLock<Context>>) -> NestedNode {
         let data = SingletonBuffer::new('\0');
-
         let ctx = ctx0.clone();
-
         let editor = Arc::new(RwLock::new(CharEditor{ ctx, data: data.clone() }));
 
         NestedNode::new(
diff --git a/nested/src/editors/list/cmd.rs b/nested/src/editors/list/cmd.rs
index 6ac44d5..83d10fd 100644
--- a/nested/src/editors/list/cmd.rs
+++ b/nested/src/editors/list/cmd.rs
@@ -4,7 +4,7 @@ use {
         buffer::{singleton::*}
     },
     crate::{
-        editors::list::{ListEditor, ListCursorMode},
+        editors::list::{ListEditor, ListCursor, ListCursorMode},
         type_system::{Context, ReprTree},
         tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
         commander::{ObjCommander}
@@ -36,8 +36,29 @@ impl ListCmd {
 impl ObjCommander for ListEditor {
     fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
         let cmd_repr = cmd_obj.read().unwrap();
+        
+        if let Some(view) = cmd_repr.get_view::<dyn SingletonView<Item = NestedNode>>() {
+            let node = view.get();
+            let cur = self.cursor.get();
 
-        if let Some(cmd) = cmd_repr.get_view::<dyn SingletonView<Item = ListCmd>>() {
+            if let Some(idx) = cur.idx {
+                match cur.mode {
+                    ListCursorMode::Select => {
+                        *self.data.get_mut(idx as usize) = Arc::new(RwLock::new(node));
+                        TreeNavResult::Exit
+                    }
+                    ListCursorMode::Insert => {
+                        self.insert(Arc::new(RwLock::new(node)));
+                        self.cursor.set(ListCursor{ idx: Some(idx+1),  mode: ListCursorMode::Insert });
+                        TreeNavResult::Continue
+                    }
+                }
+            } else {
+                TreeNavResult::Exit
+            }
+        }
+
+        else if let Some(cmd) = cmd_repr.get_view::<dyn SingletonView<Item = ListCmd>>() {
             let cur = self.cursor.get();
             drop(cmd_repr);
             
@@ -80,9 +101,30 @@ impl ObjCommander for ListEditor {
                                         }
                                     }
 
-                                    _ => {
+                                    ListCmd::Split => {
+                                        self.listlist_split();
                                         TreeNavResult::Continue
                                     }
+
+                                    _ => {
+                                        eprintln!("list edit: give cmd to child");
+
+                                        match item.send_cmd_obj(cmd_obj) {
+                                            TreeNavResult::Continue => TreeNavResult::Continue,
+                                            TreeNavResult::Exit => {
+                                                TreeNavResult::Continue
+                                                /*
+                                                match cmd.get() {
+                                                ListCmd::Split => {
+                                                    },
+                                                    _ => {
+                                                        TreeNavResult::Exit
+                                                    }
+                                            }
+                                                    */
+                                            }
+                                        }
+                                    }
                                 }
                             } else {
                                 TreeNavResult::Exit
@@ -103,7 +145,11 @@ impl ObjCommander for ListEditor {
                                 TreeNavResult::Continue
                             }
                             ListCmd::Split => {
+/*
+                                self.split(self.spill_node);
+                                */
                                 self.listlist_split();
+
                                 TreeNavResult::Continue
                             }
                             ListCmd::Clear => {
diff --git a/nested/src/editors/list/editor.rs b/nested/src/editors/list/editor.rs
index 70cda6c..1714415 100644
--- a/nested/src/editors/list/editor.rs
+++ b/nested/src/editors/list/editor.rs
@@ -354,9 +354,13 @@ impl ListEditor {
             
             if let Some(head_editor) = item.editor.get() {
 
+                eprintln!("listlistsplit:editor = {:?}", Arc::into_raw(head_editor.clone()));
+
                 let head = head_editor.downcast::<RwLock<ListEditor>>().unwrap();
                 let mut head = head.write().unwrap();
-                
+
+                let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), 0).unwrap();
+
                 if head.data.len() > 0 {
                     if cur.tree_addr.len() > 2 {
                         eprintln!("call child head listlist split");
@@ -364,35 +368,33 @@ impl ListEditor {
                         eprintln!("return");
                     }
 
-                    eprintln!("got head");
+                    /*
+                    TODO: replace this by: (does not require  ListEditor downcast)
+                    head.send_cmd_obj(ListCmd::Split.into_repr());
+                    tail_node = head.spill_buf.clone();
+                     */
 
-                    let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), 0).unwrap();
                     head.split( &mut tail_node );
-                    
-                    eprintln!("made split");
-
-                    head.goto(TreeCursor::none());
-                    drop(head);
-
-                    eprintln!("done goto");
-
-                    tail_node.goto(
-                        TreeCursor {
-                            tree_addr: vec![0],
-                            leaf_mode: if cur.tree_addr.len() > 2 {
-                                ListCursorMode::Select
-                            } else {
-                                ListCursorMode::Insert
-                            }
-                        }
-                    );
-
-                    self.insert(
-                        Arc::new(RwLock::new(tail_node))
-                    );
-
-                    eprintln!("made insert");
                 }
+
+                head.goto(TreeCursor::none());
+                drop(head);
+
+                tail_node.goto(
+                    TreeCursor {
+                        tree_addr: vec![0],
+                        leaf_mode: if cur.tree_addr.len() > 2 {
+                            ListCursorMode::Select
+                        } else {
+                            ListCursorMode::Insert
+                        }
+                    }
+                );
+                self.insert(
+                    Arc::new(RwLock::new(tail_node))
+                );
+
+                eprintln!("made insert");
             }
         }
     }
diff --git a/nested/src/editors/list/pty_editor.rs b/nested/src/editors/list/pty_editor.rs
index 9ed9719..1d40f37 100644
--- a/nested/src/editors/list/pty_editor.rs
+++ b/nested/src/editors/list/pty_editor.rs
@@ -137,224 +137,122 @@ impl PTYListController {
         self.depth = depth;
     }
 
-/*
-    pub fn handle_node_event(&mut self, c: &NestedNode) -> TreeNavResult {
-        
+    pub fn handle_term_event(&mut self, event: &TerminalEvent, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
+        let mut e = self.editor.write().unwrap();
+        match event {
+            TerminalEvent::Input(Event::Key(Key::Insert)) => {
+                e.toggle_leaf_mode();
+                TreeNavResult::Continue
+            }
+            _  => TreeNavResult::Continue
+        }        
     }
 
-    pub fn handle_char_event(&mut self, c: &char) -> TreeNavResult {
+    pub fn handle_meta_char(&mut self, c: char, child_close_char: Option<char>) -> TreeNavResult {
+        eprintln!("handle meta char");
+        let mut e = self.editor.write().unwrap();
+        let cur = e.cursor.get();
         
+        if Some(c) == self.split_char {
+            e.listlist_split();
+            TreeNavResult::Continue
+        } else if Some(c) == child_close_char {
+            e.goto(TreeCursor::none());
+            e.cursor.set(ListCursor {
+                mode: ListCursorMode::Select,
+                idx: Some(cur.idx.unwrap_or(0))
+            });
+            TreeNavResult::Continue
+        } else {
+            TreeNavResult::Exit
+        }
     }
 
-    pub fn handle_term_event(&mut self, e: &TerminalEvent) -> TreeNavResult {
-        
-}
-    */
+    pub fn handle_any_event(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
+        let mut e = self.editor.write().unwrap();
+        let cur = e.cursor.get();
+        let ctx = e.ctx.clone();
+        let ctx = ctx.read().unwrap();
+
+        match cur.mode {
+            ListCursorMode::Insert => {
+                let mut new_edit = Context::make_node(&e.ctx, e.typ.clone(), self.depth).unwrap();
+                new_edit.goto(TreeCursor::home());
+
+                match new_edit.send_cmd_obj(cmd_obj.clone()) {
+                    TreeNavResult::Continue => {
+                        e.insert(Arc::new(RwLock::new(new_edit)));
+                        TreeNavResult::Continue
+                    }
+                    TreeNavResult::Exit => TreeNavResult::Exit
+                }
+            },
+            ListCursorMode::Select => {
+                if let Some(mut item) = e.get_item_mut() {
+
+                    eprintln!("PTYList: forward any cmd to current child item");
+                    let res = item.write().unwrap().send_cmd_obj(cmd_obj.clone());
+                    let child_close_char = item.read().unwrap().close_char.get();
+                    eprintln!("PTYList: returned");
+
+                    match res {
+                        TreeNavResult::Continue => TreeNavResult::Continue,
+                        TreeNavResult::Exit => {
+                            eprintln!("...returned with exit");
+                            // child editor returned control, probably for meta-char handling..
+
+                            if cmd_obj.read().unwrap().get_type().clone() == ctx.type_term_from_str("( Char )").unwrap() {
+                                let co = cmd_obj.read().unwrap();
+                                if let Some(cmd_view) = co.get_view::<dyn SingletonView<Item = char>>() {
+                                    drop(co);
+                                    drop(e);
+                                    self.handle_meta_char(cmd_view.get(), child_close_char)
+                                } else {
+                                    TreeNavResult::Exit
+                                }
+                            } else {
+                                TreeNavResult::Exit
+                            }
+                        }
+                    }
+                } else {
+                    // cursor selects non existent item
+                    TreeNavResult::Exit
+                }
+            }
+        }
+    }
 }
 
+
 use r3vi::view::singleton::SingletonView;
 use crate::commander::ObjCommander;
 
 impl ObjCommander for PTYListController {
     fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
         let mut e = self.editor.write().unwrap();
-        let cur = e.cursor.get();
-        let cur_depth = e.get_cursor().tree_addr.len();
+        let cmd_type = cmd_obj.read().unwrap().get_type().clone();
 
-        let ctx0 = e.ctx.clone();
-        let ctx = e.ctx.clone();
-        let ctx = ctx.read().unwrap();
-
-        let co = cmd_obj.read().unwrap();
-        let cmd_type = co.get_type().clone();
-        let term_event_type = ctx.type_term_from_str("( TerminalEvent )").unwrap();
-        let list_cmd_type = ctx.type_term_from_str("( ListCmd )").unwrap();
-        let nested_node_type = ctx.type_term_from_str("( NestedNode )").unwrap();
-        let char_type = ctx.type_term_from_str("( Char )").unwrap();
-
-        if cmd_type == nested_node_type {
-            eprintln!("got nested node cmd");
-            if let Some(node_view) = co.get_view::<dyn SingletonView<Item = NestedNode>>() {
-                if let Some(idx) = cur.idx {
-                    match cur.mode {
-                        ListCursorMode::Select => {
-                            *e.data.get_mut(idx as usize) = Arc::new(RwLock::new(node_view.get()));
-                            TreeNavResult::Exit
-                        }
-                        ListCursorMode::Insert => {
-                            e.insert(Arc::new(RwLock::new(node_view.get())));
-                            e.cursor.set(ListCursor{ idx: Some(idx+1),  mode: ListCursorMode::Insert });
-                            TreeNavResult::Continue
-                        }
-                    }
-                } else {
-                    TreeNavResult::Exit
-                }
-            } else {
-                TreeNavResult::Continue
-            }
-        }
-
-        else if cmd_type == list_cmd_type {
-            drop(co);
+        if cmd_type == (&e.ctx, "( ListCmd )").into()
+        || cmd_type == (&e.ctx, "( NestedNode )").into()
+        {
             e.send_cmd_obj( cmd_obj )
         }
 
-        else if cmd_type == term_event_type {
-            if let Some(te_view) = co.get_view::<dyn SingletonView<Item = TerminalEvent>>() {
-                drop(co);
-                let event = te_view.get();
-
-                match event {
-                    TerminalEvent::Input(Event::Key(Key::Char('\t')))
-                        | TerminalEvent::Input(Event::Key(Key::Insert)) => {
-                            e.toggle_leaf_mode();
-                            e.set_leaf_mode(ListCursorMode::Select);
-
-                            TreeNavResult::Continue
-                        }
-                    _ => {
-                        if let Some(idx) = cur.idx {
-                            match cur.mode {
-                                ListCursorMode::Insert => {
-                                    match event {
-                                        TerminalEvent::Input(Event::Key(Key::Backspace)) => {
-                                            e.send_cmd_obj( ListCmd::DeletePxev.into_repr_tree(&ctx0) )
-                                        }
-                                        TerminalEvent::Input(Event::Key(Key::Delete)) => {
-                                            e.send_cmd_obj( ListCmd::DeletePxev.into_repr_tree(&ctx0) )
-                                        }
-                                        _ => {
-                                            let mut node = Context::make_node(&e.ctx, e.typ.clone(), self.depth).unwrap();
-                                            node.goto(TreeCursor::home());
-                                            node.send_cmd_obj(cmd_obj);
-/*
-                                            if e.is_listlist() {
-                                                if let Some(new_edit) = node.get_edit::<ListEditor>() {
-                                                    if new_edit.data.len() == 0 {
-                                                        remove = true;
-                                                    }
-                                                }
-                                            }
-
-                                            if ! remove {
-                                            */
-                                            e.insert(Arc::new(RwLock::new(node)));
-
-                                            TreeNavResult::Continue
-                                        }
-                                    }
-                                },
-                                ListCursorMode::Select => {
-                                    if let Some(mut item) = e.get_item().clone() {
-                                        if e.is_listlist() {
-                                            match event {
-                                                TerminalEvent::Input(Event::Key(Key::Backspace)) => {
-                                                    e.send_cmd_obj( ListCmd::DeletePxev.into_repr_tree(&ctx0) )
-                                                }
-                                                TerminalEvent::Input(Event::Key(Key::Delete)) => {
-                                                    e.send_cmd_obj( ListCmd::DeleteNexd.into_repr_tree(&ctx0) )
-                                                }
-
-                                                TerminalEvent::Input(Event::Key(Key::Char(c))) => {
-                                                    if Some(c) == self.split_char {
-                                                        e.listlist_split();
-                                                        TreeNavResult::Continue
-                                                    } else {
-                                                        item.send_cmd_obj(cmd_obj)
-                                                    }
-                                                }
-                                                _ => {
-                                                    item.send_cmd_obj(cmd_obj)
-                                                }
-                                            }
-                                        } else {
-                                            item.send_cmd_obj(cmd_obj)
-                                        }
-                                    } else {
-                                        TreeNavResult::Exit
-                                    }
-                                }
-                            }
-                        } else {
-                            TreeNavResult::Exit
-                        }
-                    }
-                }
+        else if cmd_type == (&e.ctx, "( TerminalEvent )").into() {
+            let co = cmd_obj.read().unwrap();
+            if let Some(view) = co.get_view::<dyn SingletonView<Item = TerminalEvent>>() {
+                drop( co );
+                drop( e );
+                self.handle_term_event( &view.get(), cmd_obj )
             } else {
                 TreeNavResult::Exit
             }
         }
 
         else {
-            drop(co);
-            match cur.mode {
-                ListCursorMode::Insert => {
-                    let mut new_edit = Context::make_node(&e.ctx, e.typ.clone(), self.depth).unwrap();
-                    new_edit.goto(TreeCursor::home());
-
-                    match new_edit.send_cmd_obj(cmd_obj.clone()) {
-                        TreeNavResult::Continue => {
-                            e.insert(Arc::new(RwLock::new(new_edit)));
-                            TreeNavResult::Continue
-                        }
-
-                        TreeNavResult::Exit => {
-                            //eprintln!("listedit: exit from insert mode");
-                            TreeNavResult::Exit
-                        }
-                    }
-                },
-                ListCursorMode::Select => {
-                    if let Some(mut item) = e.get_item_mut() {
-
-                        let mut i = item.write().unwrap();
-                        let res = i.send_cmd_obj(cmd_obj.clone());
-
-                        let close_char = i.close_char.get();
-                        drop(i);
-                        drop(item);
-
-                        match res {
-                            TreeNavResult::Continue => {
-                                TreeNavResult::Continue
-                            }
-
-                            TreeNavResult::Exit => {
-                                if cmd_type == char_type {
-                                    let co = cmd_obj.read().unwrap();
-                                    if let Some(cmd_view) = co.get_view::<dyn SingletonView<Item = char>>() {
-                                        drop(co);
-                                        let c = cmd_view.get();
-
-                                        if Some(c) == self.split_char {
-                                            e.listlist_split();
-                                            TreeNavResult::Continue
-                                        } else if Some(c) == close_char {
-                                            //eprintln!("listedit: exit from select (close)");
-                                            //item.goto(TreeCursor::none());
-                                            e.cursor.set(ListCursor {
-                                                mode: ListCursorMode::Insert,
-                                                idx: Some(cur.idx.unwrap_or(0)+1)
-                                            });
-                                            TreeNavResult::Continue
-                                        } else {
-                                            //eprintln!("listedit: exit from select mode");
-                                            TreeNavResult::Exit
-                                        }
-                                    } else {
-                                        TreeNavResult::Exit
-                                    }
-                                } else {
-                                    TreeNavResult::Exit
-                                }
-                            }
-                        }
-                    } else {
-                        TreeNavResult::Exit
-                    }
-                }
-            }
+            drop( e );
+            self.handle_any_event( cmd_obj )
         }
     }
 }