From e111a360a974ea7d6b7a13bce7b9961e59a6398c Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Mon, 4 Sep 2023 01:24:53 +0200
Subject: [PATCH] fix list split/join & more edge cases in typetermeditor

---
 nested/src/editors/list/cmd.rs        | 175 ++++++------
 nested/src/editors/list/cursor.rs     |   6 +-
 nested/src/editors/list/editor.rs     | 245 ++++++++++-------
 nested/src/editors/list/pty_editor.rs |   2 +
 nested/src/editors/typeterm/ctx.rs    |  10 +-
 nested/src/editors/typeterm/mod.rs    | 382 ++++++++++++++++----------
 nested/src/tree/cursor.rs             |   2 +-
 7 files changed, 486 insertions(+), 336 deletions(-)

diff --git a/nested/src/editors/list/cmd.rs b/nested/src/editors/list/cmd.rs
index f74c753..a03efe9 100644
--- a/nested/src/editors/list/cmd.rs
+++ b/nested/src/editors/list/cmd.rs
@@ -60,110 +60,101 @@ impl ObjCommander for ListEditor {
         else if let Some(cmd) = cmd_repr.get_view::<dyn SingletonView<Item = ListCmd>>() {
             let cur = self.cursor.get();
             drop(cmd_repr);
-            
-            if let Some(idx) = cur.idx {
-                match cur.mode {
-                    ListCursorMode::Select => {
-                        if let Some(mut item) = self.get_item().clone() {
-                            if self.is_listlist() {
-                                let item_cur = item.get_cursor();
 
+            match cmd.get() {
+                ListCmd::Clear => {
+                    self.clear();
+                    TreeNavResult::Continue
+                }
+                _ => {
+                    if let Some(idx) = cur.idx {
+                        match cur.mode {
+                            ListCursorMode::Select => {                        
+                                if let Some(mut item) = self.get_item().clone() {
+                                    if self.is_listlist() {
+                                        let item_cur = item.get_cursor();
+
+                                        match cmd.get() {
+                                            ListCmd::DeletePxev => {
+                                                if idx > 0
+                                                    && item_cur.tree_addr.iter().fold(
+                                                        true,
+                                                        |is_zero, x| is_zero && (*x == 0)
+                                                    )
+                                                {
+                                                    self.listlist_join_pxev(idx);
+                                                    TreeNavResult::Continue
+                                                } else {
+                                                    item.send_cmd_obj(cmd_obj)
+                                                }
+                                            }
+
+                                            ListCmd::DeleteNexd => {
+                                                let item_cur = item.get_cursor_warp();
+                                                let next_idx = idx as usize + 1;
+
+                                                if next_idx < self.data.len()
+                                                    && item_cur.tree_addr.iter().fold(
+                                                        true,
+                                                        |is_end, x| is_end && (*x == -1)
+                                                    )
+                                                {
+                                                    self.listlist_join_nexd(idx as usize);
+                                                    TreeNavResult::Continue
+                                                } else {
+                                                    item.send_cmd_obj(cmd_obj)
+                                                }
+                                            }
+
+                                            ListCmd::Split => {
+                                                self.listlist_split();
+                                                TreeNavResult::Continue
+                                            }
+
+                                            _ => {
+                                                item.send_cmd_obj(cmd_obj);
+                                                TreeNavResult::Continue
+                                            }
+                                        }
+                                    } else {
+                                        TreeNavResult::Exit
+                                    }
+                                } else {
+                                    TreeNavResult::Exit
+                                }
+                            },
+
+                            ListCursorMode::Insert => {
                                 match cmd.get() {
                                     ListCmd::DeletePxev => {
-                                        if idx > 0
-                                            && item_cur.tree_addr.iter().fold(
-                                                true,
-                                                |is_zero, x| is_zero && (*x == 0)
-                                            )
-                                        {
-                                            self.listlist_join_pxev(idx, &item);
-                                            TreeNavResult::Continue
-                                        } else {
-                                            item.send_cmd_obj(cmd_obj)
-                                        }
-                                    }
-
-                                    ListCmd::DeleteNexd => {
-                                        let item_cur = item.get_cursor_warp();
-                                        let next_idx = idx as usize + 1;
-
-                                        if next_idx < self.data.len()
-                                            && item_cur.tree_addr.iter().fold(
-                                                true,
-                                                |is_end, x| is_end && (*x == -1)
-                                            )
-                                        {
-                                            self.listlist_join_nexd(next_idx, &item);
-                                            TreeNavResult::Continue
-                                        } else {
-                                            item.send_cmd_obj(cmd_obj)
-                                        }
-                                    }
-
-                                    ListCmd::Split => {
-                                        self.listlist_split();
+                                        self.delete_pxev();
                                         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
-                                                    }
-                                            }
-                                                    */
-                                            }
-                                        }
+                                    ListCmd::DeleteNexd => {
+                                        self.delete_nexd();
+                                        TreeNavResult::Continue
+                                    }
+                                    ListCmd::Split => {
+                                        self.split();
+                                        TreeNavResult::Exit
+                                    }
+                                    ListCmd::Close => {
+                                        self.goto(TreeCursor::none());
+                                        TreeNavResult::Exit
+                                    }
+                                    _ =>{
+                                        TreeNavResult::Continue
                                     }
                                 }
-                            } else {
-                                TreeNavResult::Exit
-                            }
-                        } else {
-                            TreeNavResult::Exit
-                        }
-                    },
-
-                    ListCursorMode::Insert => {
-                        match cmd.get() {
-                            ListCmd::DeletePxev => {
-                                self.delete_pxev();
-                                TreeNavResult::Continue
-                            }
-                            ListCmd::DeleteNexd => {
-                                self.delete_nexd();
-                                TreeNavResult::Continue
-                            }
-                            ListCmd::Split => {
-                                self.split();
-                                TreeNavResult::Exit
-                            }
-                            ListCmd::Clear => {
-                                self.clear();
-                                TreeNavResult::Continue
-                            }
-                            ListCmd::Close => {
-                                self.goto(TreeCursor::none());
-                                TreeNavResult::Exit
-                            }
-                            _ =>{
-                                TreeNavResult::Continue
                             }
                         }
+                    } else {
+                        TreeNavResult::Exit
                     }
+
                 }
-            } else {
-                TreeNavResult::Exit
             }
+            
 
         } else {
             if let Some(cur_item) = self.get_item_mut() {
diff --git a/nested/src/editors/list/cursor.rs b/nested/src/editors/list/cursor.rs
index de21c01..e995b10 100644
--- a/nested/src/editors/list/cursor.rs
+++ b/nested/src/editors/list/cursor.rs
@@ -1,4 +1,4 @@
-#[derive(Clone, Copy, Eq, PartialEq)]
+#[derive(Clone, Copy, Eq, PartialEq, Debug)]
 pub enum ListCursorMode {
     Insert,
     Select
@@ -10,7 +10,7 @@ impl Default for ListCursorMode {
     }
 }
 
-#[derive(Clone, Copy, Eq, PartialEq)]
+#[derive(Clone, Copy, Eq, PartialEq, Debug)]
 pub struct ListCursor {
     pub mode: ListCursorMode,
     pub idx: Option<isize>,
@@ -34,7 +34,7 @@ impl ListCursor {
 
 impl Default for ListCursor {
     fn default() -> Self {
-        ListCursor::none()
+        ListCursor::home()
     }
 }
 
diff --git a/nested/src/editors/list/editor.rs b/nested/src/editors/list/editor.rs
index 95c9287..1da2e58 100644
--- a/nested/src/editors/list/editor.rs
+++ b/nested/src/editors/list/editor.rs
@@ -52,7 +52,12 @@ impl ListEditor {
                             ListCursorMode::Insert => ip,
                             ListCursorMode::Select => {
                                 if let Some(idx) = c.idx {
-                                    data.get(idx as usize).read().unwrap().get_mode_view()
+                                    if idx > 0 && idx < data.len() as isize {
+                                        data.get(idx as usize).read().unwrap().get_mode_view()
+                                    } else {
+                                        eprintln!("ListEditor::mode_port invalid cursor idx");
+                                        ip
+                                    }
                                 } else {
                                     ip
                                 }
@@ -191,6 +196,12 @@ impl ListEditor {
 
     /// delete all items
     pub fn clear(&mut self) {
+        eprintln!("list editor: clear");
+        let mut b = self.spillbuf.write().unwrap();
+        for i in 0..self.data.len() {
+            b.push( self.data.get(i) );
+        }
+        
         self.data.clear();
         self.cursor.set(ListCursor::home());
     }
@@ -257,7 +268,8 @@ impl ListEditor {
             }
 
             /* TODO
-
+             */
+            /*
             if self.is_listlist() {
                 if idx > 0 && idx < self.data.len()+1 {
 
@@ -283,127 +295,165 @@ impl ListEditor {
         }
     }
 
-    /// append data of other editor at the end and set cursor accordingly
-    pub fn join(&mut self, other: &ListEditor) {
-        let selfcur = self.cursor.get();
-        let othercur = other.cursor.get();
-
-        let is_bottom = self.get_cursor().tree_addr.len() == 1 ||
-            other.get_cursor().tree_addr.len() == 1;
-
-        let is_insert =
-            selfcur.mode == ListCursorMode::Insert
-            || othercur.mode == ListCursorMode::Insert;
-
-        let is_primary = self.get_cursor().tree_addr.len() > 1;
-
-        self.cursor.set(ListCursor {
-            mode: if is_insert && is_bottom {
-                      ListCursorMode::Insert
-                  } else {
-                      ListCursorMode::Select
-                  },
-            idx: Some(self.data.len() as isize -
-                      if is_primary {
-                          1
-                      } else {
-                          0
-                      }
-            )
-        });
-
-        for i in 0 .. other.data.len() {
-            self.data.push(other.data.get(i));
-        }
-    }
-
     pub fn listlist_split(&mut self) {
         let cur = self.get_cursor();
-
+        eprintln!("listlist_split(): cur = {:?}", cur);
         if let Some(mut item) = self.get_item().clone() {
+            eprintln!("listlist_split(): split child item");
             item.send_cmd_obj(ListCmd::Split.into_repr_tree(&self.ctx));
+            eprintln!("listlist_split(): done child split");
 
-            let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), 0).unwrap();
-            tail_node.goto(TreeCursor::home());
+            if cur.tree_addr.len() < 3 {
+                item.goto(TreeCursor::none());
+                let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), 0).unwrap();
+                //tail_node = tail_node.morph(  );
+                tail_node.goto(TreeCursor::home());
 
-            let mut b = item.spillbuf.write().unwrap();
-            for node in b.iter() {
-                tail_node
-                    .send_cmd_obj(
-                        ReprTree::new_leaf(
-                            (&self.ctx, "( NestedNode )"),
-                            SingletonBuffer::<NestedNode>::new(
-                                node.read().unwrap().clone()
-                            ).get_port().into()
-                        )
-                    );
-            }
-            b.clear();
-            drop(b);
-
-            item.goto(TreeCursor::none());
-            drop(item);
-
-            tail_node.goto(
-                TreeCursor {
-                    tree_addr: vec![0],
-                    leaf_mode: if cur.tree_addr.len() > 2 {
-                        ListCursorMode::Select
-                    } else {
-                        ListCursorMode::Insert
-                    }
+                let mut b = item.spillbuf.write().unwrap();
+                for node in b.iter() {
+                    tail_node
+                        .send_cmd_obj(
+                            ReprTree::new_leaf(
+                                (&self.ctx, "( NestedNode )"),
+                                SingletonBuffer::<NestedNode>::new(
+                                    node.read().unwrap().clone()
+                                ).get_port().into()
+                            )
+                        );
                 }
-            );
+                b.clear();
+                drop(b);
+                drop(item);
 
-            self.insert(
-                Arc::new(RwLock::new(tail_node))
-            );
+                self.set_leaf_mode(ListCursorMode::Insert);
+                self.nexd();
+
+                tail_node.goto(TreeCursor::home());
+                if cur.tree_addr.len() > 2 {
+                    tail_node.dn();
+                }
+
+                eprintln!("insert tail node");
+                self.insert(
+                    Arc::new(RwLock::new(tail_node))
+                );
+            } else {
+                self.up();
+                self.listlist_split();
+                self.dn();
+                eprintln!("tree depth >= 3");
+            }
         }
     }
 
-    pub fn listlist_join_pxev(&mut self, idx: isize, item: &NestedNode) {
+    pub fn listlist_join_pxev(&mut self, idx: isize) {
         {
-            let prev_editor = self.data.get_mut(idx as usize-1);
-            let prev_editor = prev_editor.read().unwrap();
+            let cur_editor = self.data.get(idx as usize);
+            let pxv_editor = self.data.get(idx as usize-1);
+            let mut cur_editor = cur_editor.write().unwrap();
+            let mut pxv_editor = pxv_editor.write().unwrap();
 
-            if let Some(prev_editor) = prev_editor.editor.get() {
-                if let Ok(prev_editor) = prev_editor.downcast::<RwLock<ListEditor>>() {
-                    let mut prev_editor = prev_editor.write().unwrap();
+            let oc0 = cur_editor.get_cursor();
 
-                    let cur_editor = item.editor.get().unwrap();
-                    let cur_editor = cur_editor.downcast::<RwLock<ListEditor>>().unwrap();
-                    let cur_editor = cur_editor.write().unwrap();
+            // tell cur_editor move all its elements into its spill-buffer
+            cur_editor.goto(TreeCursor::none());
+            cur_editor.send_cmd_obj(
+                ListCmd::Clear.into_repr_tree( &self.ctx )
+            );
+            
+            pxv_editor.goto(TreeCursor {
+                tree_addr: vec![-1],
+                leaf_mode: ListCursorMode::Insert
+            });
 
-                    prev_editor.join(&cur_editor);
+            let old_cur = pxv_editor.get_cursor();
 
-                    self.cursor.set(
-                        ListCursor {
-                            idx: Some(idx - 1), mode: ListCursorMode::Select
-                        }
-                    );
-                }
+            let data = cur_editor.spillbuf.read().unwrap();
+            for x in data.iter() {
+                pxv_editor.send_cmd_obj(
+                    ReprTree::new_leaf(
+                        (&self.ctx, "( NestedNode )"),
+                        SingletonBuffer::<NestedNode>::new(
+                            x.read().unwrap().clone()
+                        ).get_port().into()
+                    )
+                );
+            }
+
+            if oc0.tree_addr.len() > 1 {
+                pxv_editor.goto(TreeCursor {
+                    tree_addr: vec![ old_cur.tree_addr[0], 0 ],
+                    leaf_mode: ListCursorMode::Insert                
+                });
+                pxv_editor.send_cmd_obj(ListCmd::DeletePxev.into_repr_tree( &self.ctx ));
+            } else {
+                pxv_editor.goto(TreeCursor {
+                    tree_addr: vec![ old_cur.tree_addr[0] ],
+                    leaf_mode: ListCursorMode::Insert                
+                });
             }
         }
 
+        self.cursor.set(ListCursor {
+            idx: Some(idx as isize - 1),
+            mode: ListCursorMode::Select
+        });
+
+        // remove cur_editor from top list, its elements are now in pxv_editor
         self.data.remove(idx as usize);
     }
 
-    pub fn listlist_join_nexd(&mut self, next_idx: usize, item: &NestedNode) {
+    pub fn listlist_join_nexd(&mut self, idx: usize) {
+        eprintln!("listilst_join_nexd");
         {
-            let next_editor = self.data.get(next_idx);
-            let next_editor = next_editor.read().unwrap();
-            if let Some(next_editor) = next_editor.editor.get() {
-                if let Ok(next_editor) = next_editor.downcast::<RwLock<ListEditor>>() {
-                    let next_editor = next_editor.write().unwrap();
-                    let cur_editor = item.editor.get().unwrap();
-                    let cur_editor = cur_editor.downcast::<RwLock<ListEditor>>().unwrap();
-                    let mut cur_editor = cur_editor.write().unwrap();
+            let cur_editor = self.data.get(idx);
+            let nxd_editor = self.data.get(idx + 1);
+            let mut cur_editor = cur_editor.write().unwrap();
+            let mut nxd_editor = nxd_editor.write().unwrap();
 
-                    cur_editor.join(&next_editor);
-                }
+            let oc0 = cur_editor.get_cursor();
+
+            // tell next_editor move all its elements into its spill-buffer
+            nxd_editor.goto(TreeCursor::none());
+            nxd_editor.send_cmd_obj(
+                ListCmd::Clear.into_repr_tree( &self.ctx )
+            );
+
+            let old_cur = cur_editor.get_cursor();
+            cur_editor.goto(TreeCursor {
+                tree_addr: vec![-1],
+                leaf_mode: ListCursorMode::Insert
+            });
+ 
+            let data = nxd_editor.spillbuf.read().unwrap();
+            eprintln!("spillbuf of next : {} elements", data.len());
+            for x in data.iter() {
+                cur_editor.send_cmd_obj(
+                    ReprTree::new_leaf(
+                        (&self.ctx, "( NestedNode )"),
+                        SingletonBuffer::<NestedNode>::new(
+                            x.read().unwrap().clone()
+                        ).get_port().into()
+                    )
+                );
+            }
+
+            if oc0.tree_addr.len() > 1 {
+                cur_editor.goto(TreeCursor {
+                    tree_addr: vec![ old_cur.tree_addr[0], -1 ],
+                    leaf_mode: ListCursorMode::Insert                
+                });
+                cur_editor.send_cmd_obj(ListCmd::DeleteNexd.into_repr_tree( &self.ctx ));
+            } else {
+                cur_editor.goto(TreeCursor {
+                    tree_addr: vec![ old_cur.tree_addr[0] ],
+                    leaf_mode: ListCursorMode::Insert                
+                });
             }
         }
-        self.data.remove(next_idx);
+
+        // remove next_editor from top list, its elements are now in cur_editor
+        self.data.remove(idx+1);
     }
 }
 
@@ -429,3 +479,4 @@ impl TreeType for ListEditor {
 }
  */
 
+
diff --git a/nested/src/editors/list/pty_editor.rs b/nested/src/editors/list/pty_editor.rs
index 3f3cbe7..b6f237e 100644
--- a/nested/src/editors/list/pty_editor.rs
+++ b/nested/src/editors/list/pty_editor.rs
@@ -152,7 +152,9 @@ impl PTYListController {
         let cur = e.cursor.get();
         
         if Some(c) == self.split_char {
+            eprintln!("handle meta char: --> e.listlist_split()");
             e.listlist_split();
+            eprintln!("e.listlist_split() DONE");
             TreeNavResult::Continue
         } else if Some(c) == child_close_char {
             e.goto(TreeCursor::none());
diff --git a/nested/src/editors/typeterm/ctx.rs b/nested/src/editors/typeterm/ctx.rs
index 2f842f5..d7236e0 100644
--- a/nested/src/editors/typeterm/ctx.rs
+++ b/nested/src/editors/typeterm/ctx.rs
@@ -4,7 +4,7 @@ use {
     },
     crate::{
         type_system::{Context, TypeTerm, MorphismTypePattern},
-        terminal::{TerminalStyle},
+        terminal::{TerminalStyle, TerminalProjections},
         editors::{list::{PTYListStyle, PTYListController}, typeterm::{State, TypeTermEditor}}
     },
     std::{sync::{Arc, RwLock}},
@@ -34,11 +34,11 @@ pub fn init_ctx(ctx: &mut Context) {
         Arc::new(|mut node, _dst_type: _| {
             PTYListController::for_node( &mut node, Some('~'), None );
 
-            let vertical_view = true;
+            let vertical_view = false;
             if vertical_view {
                 let editor = node.get_edit::<crate::editors::list::ListEditor>().unwrap();
                 let mut e = editor.write().unwrap();
-                let mut seg_view = PTYListStyle::new( ("","~",""), 0 ).get_seg_seq_view( &mut e );
+                let mut seg_view = PTYListStyle::new( ("","~",""), node.depth.get() ).get_seg_seq_view( &mut e );
 
                 node = node.set_view(
                     seg_view.to_grid_vertical().flatten()
@@ -95,14 +95,14 @@ pub fn init_ctx(ctx: &mut Context) {
         }));
 
     ctx.add_morphism(
-        MorphismTypePattern { src_tyid: ctx.get_typeid("List"), dst_tyid: ctx.get_typeid("Type::Lit::Char").unwrap() },
+        MorphismTypePattern { src_tyid: ctx.get_typeid("Char"), dst_tyid: ctx.get_typeid("Type::Lit::Char").unwrap() },
         Arc::new(|mut node, _dst_type:_| {
             let mut grid = r3vi::buffer::index_hashmap::IndexBuffer::new();
 
             grid.insert_iter(
                 vec![
                     (Point2::new(0,0), crate::terminal::make_label("'")),
-                    (Point2::new(1,0), node.view.clone().unwrap()),
+                    (Point2::new(1,0), node.view.clone().unwrap_or( crate::terminal::make_label(".").with_fg_color((220,200,20))) ),
                     (Point2::new(2,0), crate::terminal::make_label("'")),
                 ]
             );
diff --git a/nested/src/editors/typeterm/mod.rs b/nested/src/editors/typeterm/mod.rs
index 9a646f5..d213987 100644
--- a/nested/src/editors/typeterm/mod.rs
+++ b/nested/src/editors/typeterm/mod.rs
@@ -30,14 +30,17 @@ pub enum State {
 }
 
 pub struct TypeTermEditor {
+
+    // shared with NestedNode that contains self
     ctx: Arc<RwLock<Context>>,
     data: Arc<RwLock<ReprTree>>,
-
-    // references to Node pointing to TypeTermEditor
     close_char: SingletonBuffer<Option<char>>,
     spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
 
+    // editing/parsing state
     state: State,
+
+    // child node
     cur_node: SingletonBuffer< NestedNode >
 }
 
@@ -55,8 +58,7 @@ impl TypeTermEditor {
                 });
 
                 let typename = ctx.read().unwrap().get_typename(&tyid).unwrap_or("UNNAMED TYPE".into());
-                for x in typename.chars()
-                {
+                for x in typename.chars() {
                     node.send_cmd_obj(
                         ReprTree::from_char( &ctx, x )
                     );
@@ -101,20 +103,21 @@ impl TypeTermEditor {
 
             TypeTerm::Num( n ) => {
                 let editor = node.get_edit::<TypeTermEditor>().expect("typ term edit");
-
                 let parent_ctx = editor.read().unwrap().cur_node.get().ctx.clone();
 
-                let int_edit = crate::editors::integer::PosIntEditor::from_u64(parent_ctx, 10, *n as u64);
-                let node = int_edit.into_node();
-                editor.write().unwrap().cur_node.set(node);
-                editor.write().unwrap().state = State::Num;
+                let mut editor = editor.write().unwrap();
+                editor.cur_node.set(
+                    crate::editors::integer::PosIntEditor::from_u64(parent_ctx, 10, *n as u64)
+                        .into_node()
+                );
+                editor.state = State::Num;
             }
 
             TypeTerm::Char( c ) => {
                 let editor = node.get_edit::<TypeTermEditor>().expect("typ term edit");
-
-                editor.write().unwrap().set_state( State::Char );
-                editor.write().unwrap().send_cmd_obj(ReprTree::from_char(&ctx, *c));
+                let mut editor = editor.write().unwrap();
+                editor.set_state( State::Char );
+                editor.send_cmd_obj(ReprTree::from_char(&ctx, *c));
             }
             
             _ => {}
@@ -196,10 +199,9 @@ impl TypeTermEditor {
 
         let editor = TypeTermEditor {
             ctx: ctx.clone(),
-            state,
             data: data.clone(),
+            state,
             cur_node: SingletonBuffer::new(node),
-            //editor: SingletonBuffer::new(None),
             close_char: SingletonBuffer::new(None),
             spillbuf: Arc::new(RwLock::new(Vec::new()))
         };
@@ -227,7 +229,6 @@ impl TypeTermEditor {
     }
 
     fn forward_spill(&mut self) {
-        eprintln!("forward spill");
         let node = self.cur_node.get();
         let mut buf = node.spillbuf.write().unwrap();
         for n in buf.iter() {
@@ -237,12 +238,12 @@ impl TypeTermEditor {
     }
 
     fn send_child_cmd(&mut self, cmd: Arc<RwLock<ReprTree>>) -> TreeNavResult {
-        eprintln!("typterm forward cmd");
+        eprintln!("send child cmd");
         let res = self.cur_node.get_mut().send_cmd_obj( cmd );
         self.forward_spill();
         res
     }
-    
+
     fn get_typeterm(&self) -> Option<TypeTerm> {
         match self.state {
             State::Any => None,
@@ -267,6 +268,7 @@ impl TypeTermEditor {
                  */
                 Some(TypeTerm::new(TypeID::Fun(0)))
             },
+
             State::App => {
                 Some(TypeTerm::new(TypeID::Fun(0)))
             },
@@ -280,6 +282,189 @@ impl TypeTermEditor {
             _ => {None}
         }
     }
+
+    /* unwrap a ladder if it only contains one element
+     */
+    pub fn normalize_singleton(&mut self) {
+        eprintln!("normalize singleton ladder!");
+        let mut subladder_list_node = self.cur_node.get().clone();
+        let mut subladder_list_edit = subladder_list_node.get_edit::<ListEditor>().unwrap();
+
+        let subladder_list_edit = subladder_list_edit.read().unwrap();
+        if subladder_list_edit.data.len() == 1 {
+            eprintln!("-> is singleton ladder");
+            let it_node = subladder_list_edit.data.get(0);
+            let it_node = it_node.read().unwrap();
+            if it_node.get_type() == (&self.ctx, "( Type )").into() {
+                let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap();
+
+                let mut other_tt = other_tt.write().unwrap();
+
+                other_tt.normalize_singleton();
+
+                eprintln!(">>>==>>> reset curent editor!!");
+                self.close_char.set(other_tt.close_char.get());
+                self.cur_node.set(other_tt.cur_node.get());
+                self.state = other_tt.state;
+            }
+        } else {
+            eprintln!("-> is empty ladder");
+        }
+    }
+
+    /* flatten ladder of ladders into one ladder editor
+     */
+    pub fn normalize_nested_ladder(&mut self) {
+        let mut subladder_list_node = self.cur_node.get().clone(); 
+        let mut subladder_list_edit = subladder_list_node.get_edit::<ListEditor>().unwrap();
+
+        let item = subladder_list_edit.write().unwrap().get_item().clone();
+
+        if let Some(mut it_node) = item {
+            if it_node.get_type() == (&self.ctx, "( Type )").into() {
+                let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap();
+
+                if other_tt.write().unwrap().state == State::Ladder {
+                    let other = other_tt.read().unwrap().cur_node.get().get_edit::<ListEditor>().unwrap();
+                    let buf = other.read().unwrap().data.clone();
+
+                    subladder_list_edit.write().unwrap().up();
+                    subladder_list_edit.write().unwrap().up();
+                    subladder_list_node.send_cmd_obj(
+                        ListCmd::DeleteNexd.into_repr_tree( &self.ctx )
+                    );
+
+                    if subladder_list_edit.read().unwrap().get_cursor_warp().tree_addr.len() > 0 {
+                        if subladder_list_edit.read().unwrap().get_cursor_warp().tree_addr[0] == -1 {
+                            subladder_list_edit.write().unwrap().delete_nexd();
+                        }
+                    }
+
+                    let l = buf.len();
+                    for i in 0..l {
+                        subladder_list_edit.write().unwrap().insert( buf.get(i) );
+                    }
+                    subladder_list_node.dn();
+                }
+            }
+        }
+    }
+
+    /* in insert mode, morph the previous element into a ladder and continue there
+     */
+    pub fn previous_item_into_ladder(&mut self) {
+        eprintln!("previous_item_into_ladder()");
+        let app_edit = self.cur_node.get().get_edit::<ListEditor>().expect("editor");
+        let mut app_edit = app_edit.write().unwrap();
+
+        let cur = app_edit.get_cursor();
+
+        if cur.tree_addr.len() <= 2 && cur.tree_addr.len() > 0 {
+            if cur.tree_addr.len() == 2 {
+                app_edit.delete_nexd();
+            }
+
+            app_edit.goto(TreeCursor{
+                tree_addr: vec![ cur.tree_addr[0]-1 ],
+                leaf_mode: ListCursorMode::Select
+            });
+            
+           if let Some(item_node) = app_edit.get_item() {
+                let item_typterm = item_node.get_edit::<TypeTermEditor>().expect("typetermedit");
+                let mut item_typterm = item_typterm.write().unwrap();
+                match item_typterm.state {
+
+                    // if item at cursor is Ladder
+                    State::Ladder => {
+                        eprintln!("current item is already ladder");
+                        drop(item_typterm);
+
+                        app_edit.dn();
+                        app_edit.qnexd();
+                    }
+                    _ => {
+                        eprintln!("create new ladder");
+                        item_typterm.goto(TreeCursor::none());
+                        drop(item_typterm);
+                        
+                        // else create new ladder
+                        let mut list_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), 0 ).unwrap();
+                        list_node = list_node.morph( (&self.ctx, "( Type::Ladder )").into() );
+
+                        let mut new_node = TypeTermEditor::with_node(
+                            self.ctx.clone(),
+                            0,
+                            list_node,
+                            State::Ladder
+                        );
+
+                        // insert old node and split
+                        new_node.goto(TreeCursor::home());
+
+                        new_node.send_cmd_obj(
+                            ReprTree::new_leaf(
+                                (&self.ctx, "( NestedNode )"),
+                                SingletonBuffer::<NestedNode>::new( item_node ).get_port().into()
+                            )
+                        );
+
+                        
+
+                        *app_edit.get_item_mut().unwrap().write().unwrap() = new_node;
+                        /*
+                        let mut c = app_edit.cursor.get();
+                        c.mode = ListCursorMode::Select;
+                        app_edit.goto( c );
+                         */
+                        app_edit.dn();
+                    }
+                }
+            }
+        }
+    }
+
+    /* split up current 
+     */
+    pub fn morph_to_ladder(&mut self) {
+        let old_node = self.cur_node.get().clone();
+
+        /* create a new NestedNode with TerminaltypeEditor,
+         * that has same state & child-node as current node.
+         */
+        let mut old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), 0 );
+        let mut old_edit_clone = old_edit_node.get_edit::<TypeTermEditor>().unwrap();
+        old_edit_clone.write().unwrap().set_state( self.state );
+        old_edit_clone.write().unwrap().close_char.set( old_node.close_char.get() );
+        old_edit_clone.write().unwrap().cur_node.set( old_node );
+
+        /* create new list-edit node for the ladder
+         */
+        let mut new_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), 0 ).unwrap();
+        new_node = new_node.morph( (&self.ctx, "( Type::Ladder )").into() );
+
+        /* reconfigure current node to display new_node list-editor
+         */
+        self.close_char.set(new_node.close_char.get());
+        self.cur_node.set(new_node);
+        self.state = State::Ladder;
+
+        /* insert old node and split
+         */
+        self.goto(TreeCursor::home());
+        self.send_cmd_obj(
+            ReprTree::new_leaf(
+                (&self.ctx, "( NestedNode )"),
+                SingletonBuffer::new( old_edit_node ).get_port().into()
+            )
+        );
+
+        self.set_addr(0);
+        self.dn();
+
+        let res = self.send_cmd_obj(
+            ListCmd::Split.into_repr_tree( &self.ctx )
+        );
+    }
 }
 
 impl TreeNav for TypeTermEditor {
@@ -347,6 +532,7 @@ impl ObjCommander for TypeTermEditor {
                             }
                         }
                     }
+
                     State::Char => {
                         match c {
                             '\'' => {
@@ -360,7 +546,6 @@ impl ObjCommander for TypeTermEditor {
                     }
 
                     State::Ladder => {
-                        eprintln!("have LADDER, send cmd tochild");
                         let res = self.send_child_cmd( co );
                         let cur = self.get_cursor();
                         
@@ -369,96 +554,35 @@ impl ObjCommander for TypeTermEditor {
                                 if cur.tree_addr.len() == 3 {
                                     match c {
                                         '~' => {
-                                            let mut ladder_node = self.cur_node.get().clone();
-                                            let mut ladder_edit = ladder_node.get_edit::<ListEditor>().unwrap();
-
-                                            let item = ladder_edit.write().unwrap().get_item().clone();
-
-                                            if let Some(mut it_node) = item {
-                                                if it_node.get_type() == (&self.ctx, "( Type )").into() {
-                                                    let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap();
-                                                    let other = other_tt.read().unwrap().cur_node.get().get_edit::<ListEditor>().unwrap();
-                                                    let buf = other.read().unwrap().data.clone();
-
-                                                    ladder_edit.write().unwrap().up();
-                                                    ladder_edit.write().unwrap().up();
-
-                                                    ladder_node.send_cmd_obj(
-                                                        ListCmd::DeleteNexd.into_repr_tree( &self.ctx )
-                                                    );
-                                                    //ladder_edit.write().unwrap().delete_nexd();
-
-                                                    let l = buf.len();
-                                                    for i in 0..l {
-                                                        ladder_edit.write().unwrap().insert( buf.get(i) );
-                                                    }
-                                                    ladder_node.dn();
-
-                                                    TreeNavResult::Continue
-                                                } else {
-                                                    TreeNavResult::Continue
-                                                }
-                                            } else {
-                                                TreeNavResult::Continue
-                                            }
+                                            self.normalize_nested_ladder();
+                                            self.normalize_singleton();
                                         }
-                                        _=> res
+                                        _ => {}
                                     }
-                                } else {
-                                    TreeNavResult::Continue
+                                }
+                                TreeNavResult::Continue
+                            }
+                            TreeNavResult::Exit => {
+                                match c {
+                                    '~' => TreeNavResult::Continue,
+                                    _   => TreeNavResult::Exit
                                 }
                             }
-                            res => res,
                         }
                     }
 
                     State::App => {
-                        let res = self.send_child_cmd( co );
+                        let res = self.send_child_cmd( co.clone() );
+
+                        if let Some(cmd) = co.read().unwrap().get_view::<dyn SingletonView<Item = ListCmd>>() {
+                            
+                        }
 
                         match res {
                             TreeNavResult::Exit => {
                                 match c {
                                     '~' => {
-                                        // if item at cursor is Ladder
-                                        let app_edit = self.cur_node.get().get_edit::<ListEditor>().expect("editor");
-                                        let mut app_edit = app_edit.write().unwrap();
-                                        app_edit.delete_nexd();
-                                        app_edit.pxev();
-
-                                        if let Some(item_node) = app_edit.get_item() {
-
-                                            let item_typterm = item_node.get_edit::<TypeTermEditor>().expect("typetermedit");
-                                            let mut item_typterm = item_typterm.write().unwrap();
-                                            match item_typterm.state {
-                                                State::Ladder => {
-                                                    drop(item_typterm);
-
-                                                    app_edit.dn();
-                                                    app_edit.qnexd();
-                                                }
-                                                _ => {
-                                                    eprintln!("create new ladder");
-                                                    
-                                                    // else create enw ladder
-                                                    let mut new_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), 0 ).unwrap();
-                                                    new_node = new_node.morph( (&self.ctx, "( Type::Ladder )").into() );
-                                                    // insert old node and split
-                                                    new_node.goto(TreeCursor::home());
-
-                                                    new_node.send_cmd_obj(
-                                                        ReprTree::new_leaf(
-                                                            (&self.ctx, "( NestedNode )"),
-                                                            SingletonBuffer::<NestedNode>::new( item_node ).get_port().into()
-                                                        )
-                                                    );
-
-                                                    drop(item_typterm);
-                                                    *app_edit.get_item_mut().unwrap().write().unwrap() = new_node;
-                                                    app_edit.dn();
-                                                }
-                                            }
-                                        }
-
+                                        self.previous_item_into_ladder();
                                         TreeNavResult::Continue
                                     },
                                     _ => {TreeNavResult::Exit}
@@ -466,53 +590,17 @@ impl ObjCommander for TypeTermEditor {
                             },
                             res => res
                         }
-                }
+                    }
 
-                    State::AnySymbol | State::FunSymbol | State::VarSymbol | State::App => {
+                    State::AnySymbol |
+                    State::FunSymbol |
+                    State::VarSymbol => {
                         let res = self.send_child_cmd( co );
                         match res {
                             TreeNavResult::Exit => {
                                 match c {
                                     '~' => {
-                                        eprintln!("typeterm: ~ ");
-
-                                        let old_node = self.cur_node.get().clone();
-
-                                        // create a new NestedNode with TerminaltypeEditor,
-                                        // that has same data as current node.
-                                        let mut old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), 0 );
-                                        let mut old_edit_clone = old_edit_node.get_edit::<TypeTermEditor>().unwrap();
-                                        old_edit_clone.write().unwrap().set_state( self.state );
-                                        old_edit_clone.write().unwrap().close_char.set( old_node.close_char.get() );
-                                        old_edit_clone.write().unwrap().cur_node.set( old_node );
-
-                                        // create new list-edit node for the ladder
-                                        let mut new_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), 0 ).unwrap();
-                                        new_node = new_node.morph( (&self.ctx, "( Type::Ladder )").into() );
-
-                                        eprintln!("insert old node into new node");
-                                        
-                                        // insert old node and split
-                                        new_node.goto(TreeCursor::home());
-                                        new_node.send_cmd_obj(
-                                            ReprTree::new_leaf(
-                                                (&self.ctx, "( NestedNode )"),
-                                                SingletonBuffer::new( old_edit_node ).get_port().into()
-                                            )
-                                        );
-
-                                        new_node.set_addr(0);
-                                        new_node.dn();
-
-                                        let res = new_node.send_cmd_obj(
-                                            ListCmd::Split.into_repr_tree( &self.ctx )
-                                        );
-
-                                        // reconfigure current node to display new_node
-                                        self.close_char.set(new_node.close_char.get());
-                                        self.cur_node.set(new_node);
-                                        self.state = State::Ladder;
-
+                                        self.morph_to_ladder();
                                         TreeNavResult::Continue
                                     }
                                     _ => {
@@ -536,14 +624,32 @@ impl ObjCommander for TypeTermEditor {
         } else {
             match &self.state {
                 State::Any => {
-                    self.set_state( State::AnySymbol );
+                    let cmd_repr = co.read().unwrap();
+                    if cmd_repr.get_type().clone() == (&self.ctx, "( NestedNode )").into() {
+                        if let Some(view) = cmd_repr.get_view::<dyn SingletonView<Item = NestedNode>>() {
+                            let node = view.get();
+
+                            if node.data.read().unwrap().get_type().clone() == (&self.ctx, "( Char )").into() {
+                                self.set_state( State::AnySymbol );
+                            } else {
+                                self.set_state( State::Ladder );
+                            }
+                        } else {
+                            eprintln!("ERROR");
+                        }
+                    } else {
+                        self.set_state( State::AnySymbol );
+                    }
+
                     self.cur_node.get_mut().goto(TreeCursor::home());
                 }
                 _ => {
                 }
             }
 
-            self.send_child_cmd( co )
+            let res = self.send_child_cmd( co );
+
+            res
         }
     }
 }
diff --git a/nested/src/tree/cursor.rs b/nested/src/tree/cursor.rs
index bd0a4fb..98c0984 100644
--- a/nested/src/tree/cursor.rs
+++ b/nested/src/tree/cursor.rs
@@ -4,7 +4,7 @@ use {
 
 //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
 
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Clone, Eq, PartialEq, Debug)]
 pub struct TreeCursor {
     pub leaf_mode: ListCursorMode,
     pub tree_addr: Vec<isize>,