diff --git a/Cargo.toml b/Cargo.toml
index c3f2dbd..fe2b93b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,4 +12,5 @@ members = [
     "examples/tty-04-posint",
     "examples/tty-05-dictionary",
     "examples/tty-06-lines",
+    "examples/tty-07-color",
 ]
diff --git a/examples/tty-04-posint/src/main.rs b/examples/tty-04-posint/src/main.rs
index 5f9e032..1a125b9 100644
--- a/examples/tty-04-posint/src/main.rs
+++ b/examples/tty-04-posint/src/main.rs
@@ -39,8 +39,8 @@ async fn main() {
      */
     let ctx = Arc::new(RwLock::new(Context::new()));
     nested::editors::char::init_ctx( ctx.clone() );
-    nested::editors::digit::init_ctx( ctx.clone() );
-    nested::editors::integer::init_ctx( ctx.clone() );
+    //nested::editors::digit::init_ctx( ctx.clone() );
+    //nested::editors::integer::init_ctx( ctx.clone() );
     nested::editors::list::init_ctx( ctx.clone() );
     nested_tty::setup_edittree_hook(&ctx);
 
@@ -49,23 +49,28 @@ async fn main() {
      */
     let int_builder = ReprTreeBuilder::new( ctx.clone() )
             .require(Context::parse(&ctx,
-                "ℕ ~ <PosInt 16 BigEndian> ~ EditTree"))
+                //"ℕ ~ <PosInt 16 BigEndian> ~ <Seq <Digit 16>> ~ <List <Digit 16>> ~
+                "<List  <Digit 16>> ~ <List Char> ~ EditTree"))
+            /*
             .require(Context::parse(&ctx,
                 "ℕ ~ <PosInt 10 BigEndian> ~ EditTree"))
             .require(Context::parse(&ctx,
                 "ℕ ~ <PosInt 8 BigEndian> ~ EditTree"))
             .require(Context::parse(&ctx,
                 "ℕ ~ <PosInt 2 BigEndian> ~ EditTree"))
+                */
                 ;
 
     let mut rt_int = nested::repr_tree::ReprTree::from_str("3");
     rt_int.write().unwrap().set_halo(
         /* HALO TYPE (append to top of type ladder) */
-        Context::parse(&ctx, "
+        Context::parse(&ctx, /*"
               ℕ
             ~ <PosInt 16 BigEndian>
             ~ <Seq <Digit 16>>
             ~ <List <Digit 16>>
+            */
+            " <List <Digit 16>>
             ~ <List Char>
         ")
     );
@@ -102,7 +107,7 @@ async fn main() {
     let first_idx : usize = 0;
     int_builder.update( &rt_int, int_builder.required_leaves[first_idx].clone() );
 
-    edittree.goto(TreeCursor{
+    edittree.goto(TreeCursor {
         leaf_mode: nested::editors::list::ListCursorMode::Insert,
         tree_addr: vec![first_idx as isize, 0]
     });
@@ -155,7 +160,6 @@ async fn main() {
             let halo_type = rt_edittree.read().unwrap().get_halo_type().clone();
             let edittree = rt_edittree.edittree( &ctx );
 
-
             let box_port = ViewPort::new();
             let ascii_box = nested_tty::widgets::ascii_box::AsciiBox::new(
                 Vector2::new(30, 1),
diff --git a/examples/tty-06-lines/src/line.rs b/examples/tty-06-lines/src/line.rs
new file mode 100644
index 0000000..0fe9a70
--- /dev/null
+++ b/examples/tty-06-lines/src/line.rs
@@ -0,0 +1,257 @@
+use {
+    cgmath::{Point2},
+    nested::{
+        editors::{
+            char::CharEditor,
+            list::{ListEditor, ListSegment, ListSegments},
+        },
+        repr_tree::{
+            Context,
+            ReprTreeExt,
+        },
+    },
+    nested_tty::{TerminalAtom, TerminalStyle, TerminalView},
+    r3vi::{
+        buffer::{singleton::*, vec::*},
+        projection::projection_helper::ProjectionHelper,
+        view::{
+            grid::*, index::*, list::*, sequence::*, singleton::*, Observer,
+            ObserverBroadcast, OuterViewPort, View, ViewPort,
+        },
+    },
+    std::sync::{Arc, RwLock},
+};
+
+#[derive(Clone)]
+pub struct LineDiagnostic {
+    pub range: (u32, u32),
+    pub msg: String,
+}
+
+pub struct LineEditor {
+    pub num_buf: SingletonBuffer<u64>,
+    pub diag_buf: VecBuffer<LineDiagnostic>,
+    chars_edit: Arc<RwLock<ListEditor>>,
+    out_port: ViewPort<dyn TerminalView>,
+    seg_count: usize,
+    view: Arc<RwLock<LineView>>,
+    cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
+}
+
+pub struct LineView {
+    line_num: Arc<dyn SingletonView<Item = u64>>,
+    segments: Arc<dyn ListView<ListSegment>>,
+    diagnostics: Arc<dyn SequenceView<Item = LineDiagnostic>>,
+    proj_helper: ProjectionHelper<usize, LineEditor>,
+}
+
+impl View for LineView {
+    type Msg = IndexArea<Point2<i16>>;
+}
+
+impl IndexView<Point2<i16>> for LineView {
+    type Item = TerminalAtom;
+
+    fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
+        let xoff = 6;
+
+        let mut pos = pos.clone();
+        pos.x -= xoff;
+        if pos.y == 0 {
+            // main line
+            if pos.x >= 0 {
+                match self.segments.get(&(pos.x as usize)) {
+                    Some(ListSegment::InsertCursor) => Some(TerminalAtom::new(
+                        '|',
+                        TerminalStyle::fg_color((220, 80, 40)),
+                    )),
+                    Some(ListSegment::Item { editor, cur_dist }) => {
+                        if let Some(e) = editor.get_edit::<CharEditor>() {
+                            let c = e.read().unwrap().get();
+                            let mut style = TerminalStyle::default();
+                            let i = if cur_dist >= 0 {
+                                pos.x as u32
+                            } else {
+                                pos.x as u32 - 1
+                            };
+                            for d in self.diagnostics.iter() {
+                                if d.range.0 <= i && d.range.1 > i {
+                                    style = TerminalStyle::bg_color((110, 80, 30))
+                                }
+                            }
+                            Some(TerminalAtom::new(c, style))
+                        } else {
+                            Some(TerminalAtom::from('?'))
+                        }
+                    }
+                    None => None,
+                }
+            } else if pos.x <= -2 {
+                // line number
+                let mut n = self.line_num.get();
+                let digit_idx = -(pos.x + 2);
+                for _ in 0..digit_idx {
+                    n /= 10;
+                }
+                Some(TerminalAtom::new(
+                    char::from_digit((n % 10) as u32, 10).unwrap_or('?'),
+                    TerminalStyle::fg_color((120, 120, 120)),
+                ))
+            } else {
+                None
+            }
+        } else if pos.y > 0 {
+            // optional diagnostic message
+            let diag_idx = pos.y as usize - 1;
+            if let Some(diag) = self.diagnostics.get(&diag_idx) {
+                if let Some(c) = diag.msg.chars().nth(pos.x as usize) {
+                    Some(TerminalAtom::new(
+                        c,
+                        TerminalStyle::bg_color((20, 20, 0))
+                            .add(TerminalStyle::fg_color((220, 40, 40))),
+                    ))
+                } else {
+                    None
+                }
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    }
+
+    fn area(&self) -> IndexArea<Point2<i16>> {
+        let xoff = 6;
+        let mut n = self.line_num.get();
+        let mut n_digits = 0 as i16;
+        while n > 0 {
+            n_digits += 1;
+            n /= 10;
+        }
+        let diag_len = self
+            .diagnostics
+            .iter()
+            .map(|d| d.msg.chars().count() as i16)
+            .max()
+            .unwrap_or(0);
+        IndexArea::Range(
+            Point2::new(xoff - n_digits - 1, 0)
+                ..=Point2::new(
+                    xoff + i16::max(
+                        self.segments.len().unwrap_or(i16::MAX as usize) as i16,
+                        diag_len,
+                    ),
+                    self.diagnostics.len().unwrap_or(i16::MAX as usize) as i16,
+                ),
+        )
+    }
+}
+
+impl LineEditor {
+    pub fn new(
+        ctx: &Arc<RwLock<Context>>,
+        n: u64,
+        chars_edit: Arc<RwLock<ListEditor>>,
+    ) -> Arc<RwLock<Self>> {
+        let num_buf = SingletonBuffer::new(n);
+        let diag_buf = VecBuffer::new();
+        let chars_segs = ListSegments::new(
+            chars_edit.read().unwrap().get_cursor_port(),
+            chars_edit.read().unwrap().get_edittree_list(),
+        );
+        let chars_segs_view = chars_segs.read().unwrap().get_view();
+
+        let out_port = ViewPort::new();
+
+        let mut proj_helper = ProjectionHelper::new(out_port.update_hooks.clone());
+        let line_view = Arc::new(RwLock::new(LineView {
+            line_num: proj_helper.new_singleton_arg(
+                0,
+                num_buf.get_port(),
+                |e: &mut LineEditor, _msg| {
+                    e.cast.write().unwrap().notify(&IndexArea::Range(
+                        (Point2::new(-100, 0)..=Point2::new(6, 0)),
+                    ));
+                },
+            ),
+            segments: proj_helper.new_list_arg(1, chars_segs_view, |e: &mut LineEditor, diff| {
+                let xoff = 6;
+                let mut l = &mut e.seg_count;
+                /*
+                    eprintln!("line: (l={}) (diff={})", l, match diff {
+                    ListDiff::Clear => format!("clear"),
+                    ListDiff::Remove(idx) => format!("remove {}", idx),
+                    ListDiff::Insert{idx,val} =>format!("insert {}", idx),
+                    ListDiff::Update{idx, val}=>format!("update {}", idx)
+                });
+                */
+                match diff {
+                    ListDiff::Clear => {
+                        e.cast.write().unwrap().notify(&IndexArea::Range(
+                            (Point2::new(xoff + 0 as i16, 0)..=Point2::new(xoff + *l as i16, 0)),
+                        ));
+                        *l = 0;
+                    }
+                    ListDiff::Remove(idx) => {
+                        *l -= 1;
+                        e.cast.write().unwrap().notify(&IndexArea::Range(
+                            (Point2::new(xoff + *idx as i16, 0)
+                                ..=Point2::new(xoff + *l as i16 + 1, 0)),
+                        ));
+                    }
+                    ListDiff::Insert { idx, val } => {
+                        *l += 1;
+                        e.cast.write().unwrap().notify(&IndexArea::Range(
+                            (Point2::new(xoff + *idx as i16, 0)..=Point2::new(xoff + *l as i16, 0)),
+                        ));
+                    }
+                    ListDiff::Update { idx, val } => {
+                        e.cast.write().unwrap().notify(&IndexArea::Range(
+                            (Point2::new(xoff + *idx as i16, 0)
+                                ..=Point2::new(xoff + *idx as i16, 0)),
+                        ));
+                    }
+                }
+            }),
+            diagnostics: proj_helper.new_sequence_arg(
+                2,
+                diag_buf.get_port().to_sequence(),
+                |e: &mut LineEditor, idx| {
+                    e.cast.write().unwrap().notify(&IndexArea::Range(
+                        (Point2::new(-100, 1 + *idx as i16)..=Point2::new(100, 1 + *idx as i16)),
+                    ));
+                },
+            ),
+
+            proj_helper,
+        }));
+
+        out_port.set_view(Some(line_view.clone() as Arc<dyn TerminalView>));
+
+        let line_edit = Arc::new(RwLock::new(LineEditor {
+            num_buf,
+            diag_buf,
+            chars_edit,
+            cast: out_port.inner().get_broadcast(),
+            view: line_view.clone(),
+            seg_count: 0,
+            out_port,
+        }));
+
+        line_view.write().unwrap().proj_helper.set_proj(&line_edit);
+        line_edit
+    }
+
+    pub fn set_linum(&mut self, n: u64) {
+        self.num_buf.set(n);
+    }
+
+    pub fn add_diag(&mut self, diag: LineDiagnostic) {
+        self.diag_buf.push(diag);
+    }
+
+    pub fn get_port(&self) -> OuterViewPort<dyn TerminalView> {
+        self.out_port.outer()
+    }
+}
diff --git a/examples/tty-06-lines/src/lines.rs b/examples/tty-06-lines/src/lines.rs
new file mode 100644
index 0000000..7419c4e
--- /dev/null
+++ b/examples/tty-06-lines/src/lines.rs
@@ -0,0 +1,225 @@
+use {
+    crate::line::{LineDiagnostic, LineEditor},
+    nested::{
+        edit_tree::{EditTree},
+        editors::list::{ListEditor},
+        repr_tree::{
+            Context, GenericReprTreeMorphism, ReprLeaf, ReprTree, ReprTreeArc, ReprTreeBuilder,
+            ReprTreeExt
+        },
+    },
+    nested_tty::{
+        DisplaySegment, TerminalProjections, TerminalStyle,
+    },
+    r3vi::{
+        buffer::{singleton::*},
+    },
+    std::sync::{Arc, RwLock},
+};
+
+pub struct LinesEditor {
+    ctx: Arc<RwLock<Context>>,
+    pub edit: EditTree,
+}
+
+impl LinesEditor {
+    pub fn new(ctx: Arc<RwLock<Context>>) -> Self {
+        let typ = Context::parse(&ctx, "Line");
+        let depth_port = SingletonBuffer::<usize>::new(0).get_port();
+
+        let list_edit = ListEditor::new(ctx.clone(), typ, ReprTreeBuilder::new(ctx.clone()));
+
+        let morph_new_line = GenericReprTreeMorphism::new(
+            Context::parse(&ctx, "Line ~ Void"),
+            Context::parse(&ctx, "Line ~ <List Char> ~ <Vec Char>"),
+            {
+                let ctx = ctx.clone();
+                move |line_rt, σ| {
+                    let mut l = ReprTree::from_str("");
+                    l.write()
+                        .unwrap()
+                        .set_halo(Context::parse(&ctx, "<List Char>"));
+                    l = ReprTree::rise(l);
+                    line_rt.insert_branch(l);
+                    line_rt
+                        .write()
+                        .unwrap()
+                        .branches
+                        .remove(&Context::parse(&ctx, "Void"));
+                    eprintln!("make line: {}", line_rt.read().unwrap().fmt(&ctx, 0));
+                }
+            },
+        );
+        ctx.write().unwrap().morphisms.add_morphism(morph_new_line);
+
+        let line_to_edittree = GenericReprTreeMorphism::new(
+            Context::parse(&ctx, "Line ~ <List Char> ~ EditTree"),
+            Context::parse(&ctx, "Line ~ EditTree"),
+            {
+                let ctx = ctx.clone();
+                move |line_rt, σ| {
+                    let chars_edittree = line_rt
+                        .descend(Context::parse(&ctx, "<List Char>"))
+                        .expect("cant descend")
+                        .edittree(&ctx)
+                        .get();
+
+                    let line =
+                        LineEditor::new(&ctx, 0, chars_edittree.get_edit::<ListEditor>().unwrap());
+                    let line_port = line.read().unwrap().get_port();
+
+                    let depth = SingletonBuffer::new(0).get_port();
+                    let mut line_edittree = EditTree::new(ctx.clone(), depth)
+                        .set_nav(chars_edittree.ctrl.tree_nav.get().unwrap())
+                        .set_cmd(chars_edittree.ctrl.cmd.get().unwrap())
+                        .set_editor(line.clone());
+
+                    line_edittree.disp.view.insert_leaf(
+                        Context::parse(&ctx, "TerminalView"),
+                        ReprLeaf::from_view(line_port),
+                    );
+                    line_rt.insert_leaf(
+                        Context::parse(&ctx, "EditTree"),
+                        ReprLeaf::from_singleton_buffer(SingletonBuffer::new(line_edittree)),
+                    );
+                }
+            },
+        );
+
+        ctx.write()
+            .unwrap()
+            .morphisms
+            .add_morphism(line_to_edittree);
+
+        let lines_segments = nested::editors::list::ListSegments::new(
+            list_edit.get_cursor_port(),
+            list_edit.get_edittree_list(),
+        )
+        .read()
+        .unwrap()
+        .get_view();
+        let lines_view = lines_segments
+            .map({
+                let ctx = ctx.clone();
+                move |segment| match segment {
+                    nested::editors::list::ListSegment::InsertCursor => {
+                        nested_tty::make_label("..... |").with_fg_color((220, 80, 40))
+                    }
+                    nested::editors::list::ListSegment::Item { editor, cur_dist } => {
+                        if *cur_dist == 0 {
+                            editor.display_view().map_item(|x, a| {
+                                a.add_style_back(TerminalStyle::bg_color((50, 50, 50)))
+                            })
+                        } else {
+                            editor.display_view()
+                        }
+                    }
+                }
+            })
+            .to_sequence()
+            .to_grid_vertical()
+            .flatten();
+
+        let mut list_edit = list_edit.into_node(depth_port);
+        {
+            nested_tty::editors::list::PTYListController::for_node(&mut list_edit, Some('\n'), None);
+        }
+        list_edit
+            .disp
+            .view
+            .write()
+            .unwrap()
+            .insert_branch(ReprTree::from_view(
+                Context::parse(&ctx, "TerminalView"),
+                lines_view,
+            ));
+
+        LinesEditor {
+            // lines,
+            edit: list_edit,
+            ctx,
+        }
+    }
+
+    pub fn add_line(&mut self, line_value: &str) -> ReprTreeArc {
+        let n = self
+            .edit
+            .get_edit::<ListEditor>()
+            .unwrap()
+            .read()
+            .unwrap()
+            .data
+            .len() as u64;
+
+        let line_rt = self.make_line(line_value);
+        self.edit
+            .get_edit::<ListEditor>()
+            .unwrap()
+            .write()
+            .unwrap()
+            .insert(line_rt.clone());
+
+        line_rt
+    }
+
+    pub fn make_line(&self, line_value: &str) -> ReprTreeArc {
+        let ctx = &self.ctx;
+        let rt_line = ReprTree::from_str(line_value);
+        rt_line
+            .write()
+            .unwrap()
+            .set_halo(Context::parse(&ctx, "Line ~ <List Char>"));
+
+        let line_builder = ReprTreeBuilder::new(ctx.clone())
+            .require(Context::parse(&ctx, "Line ~ <List Char> ~ <Vec Char>"))
+            .require(Context::parse(&ctx, "Line ~ EditTree"));
+
+        line_builder
+            .build_from(rt_line)
+            .expect("cant build line reprtree")
+    }
+
+    pub fn add_diagnostic(&mut self, line_num: usize, diag: LineDiagnostic) {
+        let line = self
+            .edit
+            .get_edit::<ListEditor>()
+            .expect("cant get list edit")
+            .read()
+            .unwrap()
+            .data
+            .get(line_num)
+            .edittree(&self.ctx)
+            .get()
+            .get_edit::<LineEditor>()
+            .expect("cant get line edit");
+
+        line.write().unwrap().diag_buf.push(diag);
+    }
+    /*
+        pub fn get_lines(&self) -> Vec<String> {
+            /*  1. get [[Char]]  Repr
+                2. call flatten
+                3. read out as <Vec Char> repr
+             */
+
+            // TODO
+            let lines = self.edit.read().unwrap().get_edit::< ListEditor >().expect("cant get list edit")
+                .read().unwrap().data
+                .clone().into_inner()
+                .read().unwrap()
+                .iter()
+                .map(|line_edittree_arc| {
+                    let line_edittree = line_edittree_arc.read().unwrap();
+                    line_edittree.
+                })
+        }
+
+        pub fn get(&self) -> String {
+            self.get_lines().iter()
+                .map(|l|
+                    l.chars().chain(std::iter::once('\n'))
+                ).flatten()
+                .collect()
+        }
+    */
+}
diff --git a/examples/tty-06-lines/src/main.rs b/examples/tty-06-lines/src/main.rs
index 74683d7..e9da856 100644
--- a/examples/tty-06-lines/src/main.rs
+++ b/examples/tty-06-lines/src/main.rs
@@ -4,462 +4,82 @@ extern crate nested_tty;
 extern crate r3vi;
 extern crate termion;
 
+mod line;
+mod lines;
+
 use {
-    cgmath::{Vector2, Point2},
+    cgmath::{Vector2},
     nested::{
-        editors::{ObjCommander, char::CharEditor, list::{ListEditor, ListSegment, ListSegments}},
-        repr_tree::{Context, ReprLeaf, ReprTreeBuilder, ReprTree, ReprTreeExt, ReprTreeArc, GenericReprTreeMorphism},
-        edit_tree::{EditTree, TreeNav, TreeCursor}
+        edit_tree::{TreeCursor, TreeNav},
+        editors::ObjCommander,
+        repr_tree::{Context, ReprTreeExt},
     },
     nested_tty::{
-        DisplaySegment, TTYApplication,
-        TerminalCompositor, TerminalStyle, TerminalView,
-        TerminalAtom, TerminalEvent,
-        edit_tree::cursor_widget::TreeNavExt,
-        TerminalProjections
-    },
-    r3vi::{
-        buffer::{singleton::*, vec::*},
-        view::{
-            ObserverBroadcast, Observer, ObserverExt, View, ViewPort, OuterViewPort,
-            port::UpdateTask, list::*, sequence::*, singleton::*, index::*, grid::*
-        },
-        projection::projection_helper::ProjectionHelper
+        edit_tree::cursor_widget::TreeNavExt, DisplaySegment, TTYApplication,
+        TerminalCompositor,
     },
     std::sync::{Arc, RwLock},
 };
 
-#[derive(Clone)]
-struct LineDiagnostic {
-    range: (u32, u32),
-    msg: String
-}
-
-struct LineEditor {
-    num_buf: SingletonBuffer< u64 >,
-    diag_buf: VecBuffer< LineDiagnostic >,
-    chars_edit: Arc<RwLock<ListEditor>>,
-    out_port: ViewPort< dyn TerminalView >,
-    seg_count: usize,
-    view: Arc<RwLock< LineView >>,
-    cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
-}
-
-struct LineView {
-    line_num: Arc< dyn SingletonView<Item = u64> >,
-    segments: Arc< dyn ListView<ListSegment> >,
-    diagnostics: Arc< dyn SequenceView<Item = LineDiagnostic> >,
-    proj_helper: ProjectionHelper<usize, LineEditor>
-}
-
-impl View for LineView {
-    type Msg = IndexArea<Point2<i16>>;
-}
-
-impl IndexView<Point2<i16>> for LineView {
-    type Item = TerminalAtom;
-
-    fn get(&self, pos: &Point2<i16>) -> Option< TerminalAtom > {
-        let xoff = 6;
-
-        let mut pos = pos.clone();
-        pos.x -= xoff;
-        if pos.y == 0 {
-            // main line
-            if pos.x >= 0 {
-                match self.segments.get(&(pos.x as usize)) {
-                    Some(ListSegment::InsertCursor) => {
-                        Some(TerminalAtom::new('|', TerminalStyle::fg_color((220, 80, 40))))
-                    }
-                    Some(ListSegment::Item { editor, cur_dist }) => {
-                        if let Some(e) = editor.get_edit::<CharEditor>() {
-                            let c = e.read().unwrap().get();
-                            let mut style = TerminalStyle::default();
-                            let i = if cur_dist >= 0 { pos.x as u32 } else { pos.x as u32 - 1 };
-                            for d in self.diagnostics.iter() {
-                                if d.range.0 <= i && d.range.1 > i {
-                                    style = TerminalStyle::bg_color((110, 80, 30))
-                                }
-                            }
-                            Some(TerminalAtom::new(c, style))
-                        } else {
-                            Some(TerminalAtom::from('?'))
-                        }
-                    }
-                    None => None
-                }
-            } else if pos.x <= -2 {
-                // line number
-                let mut n = self.line_num.get();
-                let digit_idx = -(pos.x+2);
-                for _ in 0..digit_idx { n /= 10; }
-                Some(
-                    TerminalAtom::new(
-                        char::from_digit((n % 10) as u32, 10).unwrap_or('?'),
-                        TerminalStyle::fg_color((120,120,120))
-                    )
-                )
-            } else {
-                None
-            }
-        } else if pos.y > 0 {
-            // optional diagnostic message
-            let diag_idx = pos.y as usize - 1;
-            if let Some(diag) = self.diagnostics.get(&diag_idx) {
-                if let Some(c) = diag.msg.chars().nth( pos.x as usize ) {
-                    Some(TerminalAtom::new(c,
-                        TerminalStyle::bg_color((20,20,0))
-                            .add(TerminalStyle::fg_color((220, 40, 40)))
-                    ))
-                } else {
-                    None
-                }
-            } else {
-                None
-            }
-        } else {
-            None
-        }
-    }
-
-    fn area(&self) -> IndexArea<Point2<i16>> {
-        let xoff = 6;
-        let mut n = self.line_num.get();
-        let mut n_digits = 0 as i16;
-        while n > 0 { n_digits += 1; n /= 10; }
-        let diag_len = self.diagnostics.iter().map(|d| d.msg.chars().count() as i16).max().unwrap_or(0);
-        IndexArea::Range(
-            Point2::new( xoff - n_digits - 1 , 0) ..=
-            Point2::new(
-                xoff + i16::max(
-                    self.segments.len().unwrap_or(i16::MAX as usize) as i16,
-                    diag_len
-                ),
-                self.diagnostics.len().unwrap_or(i16::MAX as usize) as i16,
-            )
-        )
-    }
-}
-
-impl LineEditor {
-    pub fn new(
-        ctx: &Arc<RwLock<Context>>,
-        n: u64,
-        chars_edit: Arc<RwLock<ListEditor>>
-    ) -> Arc<RwLock<Self>> {
-        let num_buf = SingletonBuffer::new(n);
-        let diag_buf = VecBuffer::new();
-        let chars_segs = ListSegments::new(
-            chars_edit.read().unwrap().get_cursor_port(),
-            chars_edit.read().unwrap().get_edittree_list()
-        );
-        let chars_segs_view = chars_segs.read().unwrap().get_view();
-
-        let out_port = ViewPort::new();
-
-        let mut proj_helper = ProjectionHelper::new(out_port.update_hooks.clone());
-        let line_view = Arc::new(RwLock::new(LineView {
-            line_num: proj_helper.new_singleton_arg(0, num_buf.get_port(),
-                |e: &mut LineEditor, _msg|{
-                    e.cast.write().unwrap()
-                        .notify(&IndexArea::Range(
-                            (Point2::new(-100, 0) ..= Point2::new(6, 0))
-                        ));
-                }),
-            segments: proj_helper.new_list_arg(1, chars_segs_view,
-                |e: &mut LineEditor, diff| {
-                    let xoff = 6;
-                    let mut l = &mut e.seg_count;
-                    /*
-                        eprintln!("line: (l={}) (diff={})", l, match diff {
-                        ListDiff::Clear => format!("clear"),
-                        ListDiff::Remove(idx) => format!("remove {}", idx),
-                        ListDiff::Insert{idx,val} =>format!("insert {}", idx),
-                        ListDiff::Update{idx, val}=>format!("update {}", idx)
-                    });
-                    */
-                    match diff {
-                        ListDiff::Clear => {
-                            e.cast.write().unwrap()
-                                .notify(&IndexArea::Range(
-                                    (Point2::new(xoff+0 as i16, 0) ..= Point2::new(xoff+*l as i16, 0))
-                                ));
-                            *l = 0;
-                        }
-                        ListDiff::Remove(idx) => {
-                            *l -= 1;
-                            e.cast.write().unwrap()
-                                .notify(&IndexArea::Range(
-                                    (Point2::new(xoff+*idx as i16, 0) ..= Point2::new(xoff+*l as i16+1, 0))
-                                ));
-                        }
-                        ListDiff::Insert{ idx, val } => {
-                            *l += 1;
-                            e.cast.write().unwrap()
-                                .notify(&IndexArea::Range(
-                                    (Point2::new(xoff+*idx as i16, 0) ..= Point2::new(xoff+*l as i16, 0))
-                                ));
-                        }
-                        ListDiff::Update{ idx, val } => {
-                            e.cast.write().unwrap()
-                                .notify(&IndexArea::Range(
-                                    (Point2::new(xoff+*idx as i16, 0) ..= Point2::new(xoff+*idx as i16, 0))
-                                ));
-                        }
-                    }
-                }),
-            diagnostics: proj_helper.new_sequence_arg(2, diag_buf.get_port().to_sequence(),
-                |e: &mut LineEditor, idx| {
-                    e.cast.write().unwrap()
-                        .notify(&IndexArea::Range(
-                            (Point2::new(-100, 1+*idx as i16) ..= Point2::new(100, 1+*idx as i16))
-                        ));
-                }),
-
-            proj_helper,
-        }));
-
-        out_port.set_view(Some(line_view.clone() as Arc<dyn TerminalView>));
-
-        let line_edit = Arc::new(RwLock::new(LineEditor {
-            num_buf,
-            diag_buf,
-            chars_edit,
-            cast: out_port.inner().get_broadcast(),
-            view: line_view.clone(),
-            seg_count: 0,
-            out_port,
-        }));
-
-        line_view.write().unwrap().proj_helper.set_proj(&line_edit);
-        line_edit
-    }
-
-    pub fn set_linum(&mut self, n: u64) {
-        self.num_buf.set(n);
-    }
-
-    pub fn add_diag(&mut self, diag: LineDiagnostic) {
-        self.diag_buf.push(diag);
-    }
-
-    pub fn get_port(&self) -> OuterViewPort<dyn TerminalView> {
-        self.out_port.outer()
-    }
-}
-
-struct LinesEditor {
-    ctx: Arc<RwLock<Context>>,
-    edit: EditTree
-}
-
-impl LinesEditor {
-    pub fn new(ctx: Arc<RwLock<Context>>) -> Self {
-        let typ = Context::parse(&ctx, "Line");
-        let depth_port = SingletonBuffer::<usize>::new(0).get_port();
-
-        let list_edit = ListEditor::new(ctx.clone(), typ, ReprTreeBuilder::new(ctx.clone()));
-
-        let morph_new_line = GenericReprTreeMorphism::new(
-            Context::parse(&ctx, "Line ~ Void"),
-            Context::parse(&ctx, "Line ~ <List Char> ~ <Vec Char>"),
-            {
-                let ctx = ctx.clone();
-                move |line_rt, σ| {
-                    let mut l = ReprTree::from_str("");
-                    l.write().unwrap().set_halo(Context::parse(&ctx, "<List Char>"));
-                    l = ReprTree::rise(l);
-                    line_rt.insert_branch(l);
-                    line_rt.write().unwrap().branches.remove(&Context::parse(&ctx, "Void"));
-                    eprintln!("make line: {}", line_rt.read().unwrap().fmt(&ctx, 0));
-                }
-            });
-        ctx.write().unwrap().morphisms.add_morphism( morph_new_line );
-
-        let line_to_edittree = GenericReprTreeMorphism::new(
-            Context::parse(&ctx, "Line ~ <List Char> ~ EditTree"),
-            Context::parse(&ctx, "Line ~ EditTree"),
-            {
-                let ctx = ctx.clone();
-                move |line_rt, σ| {
-                    let chars_edittree = line_rt
-                        .descend(Context::parse(&ctx, "<List Char>")).expect("cant descend")
-                        .edittree(&ctx).get();
-
-                    let line = LineEditor::new(&ctx, 0,
-                        chars_edittree.get_edit::<ListEditor>().unwrap());
-                    let line_port = line.read().unwrap().get_port();
-
-                    let depth = SingletonBuffer::new(0).get_port();
-                    let mut line_edittree = EditTree::new(ctx.clone(), depth)
-                        .set_nav( chars_edittree.ctrl.tree_nav.get().unwrap() )
-                        .set_cmd( chars_edittree.ctrl.cmd.get().unwrap() )
-                        .set_editor( line.clone() );
-
-                    line_edittree.disp.view
-                        .insert_leaf(
-                            Context::parse(&ctx, "TerminalView"),
-                            ReprLeaf::from_view( line_port )
-                        );
-                    line_rt.insert_leaf(
-                        Context::parse(&ctx, "EditTree"),
-                        ReprLeaf::from_singleton_buffer(SingletonBuffer::new( line_edittree ))
-                    );
-                }
-            }
-        );
-        ctx.write().unwrap().morphisms.add_morphism( line_to_edittree );
-
-        let lines_segments = nested::editors::list::ListSegments::new(
-            list_edit.get_cursor_port(),
-            list_edit.get_edittree_list()
-        ).read().unwrap().get_view();
-        let lines_view = lines_segments
-            .map({
-                let ctx = ctx.clone();
-                move |segment| match segment {
-                    nested::editors::list::ListSegment::InsertCursor => {
-                        nested_tty::make_label("..... |")
-                            .with_fg_color((220, 80, 40))
-                    },
-                    nested::editors::list::ListSegment::Item { editor, cur_dist } => {
-                        if *cur_dist == 0 {
-                            editor.display_view()
-                                .map_item(|x,a| a
-                                    .add_style_back(TerminalStyle::bg_color((50, 50, 50)))
-                                )
-                        } else {
-                            editor.display_view()
-                        }
-                    }
-                }
-            })
-            .to_sequence()
-            .to_grid_vertical()
-            .flatten();
-
-        let mut list_edit = list_edit.into_node( depth_port );
-        nested_tty::editors::list::PTYListController::for_node( &mut list_edit, Some('\n'), None );
-        list_edit.disp.view.write().unwrap()
-            .insert_branch(ReprTree::from_view(
-                Context::parse(&ctx, "TerminalView"),
-                lines_view
-            ));
-
-        LinesEditor {
-           // lines,
-            edit: list_edit,
-            ctx
-        }
-    }
-
-    pub fn add_line(&mut self, line_value: &str) -> ReprTreeArc {
-        let n = self.edit.get_edit::< ListEditor >().unwrap()
-            .read().unwrap()
-            .data.len() as u64;
-
-        let mut line_rt = self.make_line(line_value);
-        self.edit.get_edit::< ListEditor >().unwrap()
-            .write().unwrap()
-            .insert( line_rt.clone() );
-
-        line_rt
-    }
-
-    pub fn make_line(&self, line_value: &str) -> ReprTreeArc {
-        let ctx = &self.ctx;
-        let mut rt_line = ReprTree::from_str(line_value);
-        rt_line.write().unwrap().set_halo(Context::parse(&ctx, "Line ~ <List Char>"));
-
-        let line_builder = ReprTreeBuilder::new(ctx.clone())
-            .require(Context::parse(&ctx, "Line ~ <List Char> ~ <Vec Char>"))
-            .require(Context::parse(&ctx, "Line ~ EditTree"));
-
-        line_builder.build_from(rt_line).expect("cant build line reprtree")
-    }
-
-    pub fn add_diagnostic(&mut self, line_num: usize, diag: LineDiagnostic) {
-        let mut line = self.edit
-            .get_edit::< ListEditor >().expect("cant get list edit")
-            .read().unwrap()
-            .data
-            .get(line_num)
-            .edittree(&self.ctx)
-            .get()
-            .get_edit::< LineEditor >().expect("cant get line edit");
-
-        line.write().unwrap().diag_buf.push(diag);
-    }
-/*
-    pub fn get_lines(&self) -> Vec<String> {
-        /*  1. get [[Char]]  Repr
-            2. call flatten
-            3. read out as <Vec Char> repr
-         */
-
-        // TODO
-        let lines = self.edit.read().unwrap().get_edit::< ListEditor >().expect("cant get list edit")
-            .read().unwrap().data
-            .clone().into_inner()
-            .read().unwrap()
-            .iter()
-            .map(|line_edittree_arc| {
-                let line_edittree = line_edittree_arc.read().unwrap();
-                line_edittree.
-            })
-    }
-
-    pub fn get(&self) -> String {
-        self.get_lines().iter()
-            .map(|l|
-                l.chars().chain(std::iter::once('\n'))
-            ).flatten()
-            .collect()
-    }
-*/
-}
-
 #[async_std::main]
 async fn main() {
     /* setup context
      */
     let ctx = Arc::new(RwLock::new(Context::new()));
-    nested::editors::char::init_ctx( ctx.clone() );
-    nested::editors::digit::init_ctx( ctx.clone() );
-    nested::editors::integer::init_ctx( ctx.clone() );
-    nested::editors::list::init_ctx( ctx.clone() );
+    nested::editors::char::init_ctx(ctx.clone());
+    nested::editors::digit::init_ctx(ctx.clone());
+    nested::editors::integer::init_ctx(ctx.clone());
+    nested::editors::list::init_ctx(ctx.clone());
     nested_tty::setup_edittree_hook(&ctx);
 
     let args: Vec<String> = std::env::args().collect();
     let path = String::from(args.get(1).expect("no filename given"));
 
-    let mut lines_edit = LinesEditor::new(ctx.clone());
+    let mut lines_edit = lines::LinesEditor::new(ctx.clone());
 
     let iter_lines = iterate_text::file::lines::IterateFileLines::new(path.clone());
-    for (i,line) in iter_lines.enumerate() {
+    for (i, line) in iter_lines.enumerate() {
         let mut sanitized_line = String::new();
         for c in line.chars() {
             if c == '\t' {
-                for _ in 0..4 { sanitized_line.push(' '); }
+                for _ in 0..4 {
+                    sanitized_line.push(' ');
+                }
             } else if c != '\n' {
                 sanitized_line.push(c);
             }
         }
         let line = lines_edit.add_line(&sanitized_line);
 
-        line.edittree(&ctx).get()
-            .get_edit::<LineEditor>().unwrap()
-            .write().unwrap()
-            .num_buf.set(i as u64);
+        line.edittree(&ctx)
+            .get()
+            .get_edit::<line::LineEditor>()
+            .unwrap()
+            .write()
+            .unwrap()
+            .num_buf
+            .set(i as u64);
     }
 
     lines_edit.edit.goto(TreeCursor::home());
-    lines_edit.add_diagnostic( 5, LineDiagnostic{ range: (5, 10), msg: "test diagnostic".into() } );
-    lines_edit.add_diagnostic( 8, LineDiagnostic{ range: (6, 14), msg: "another test diagnostic".into() } );
+    lines_edit.add_diagnostic(
+        5,
+        line::LineDiagnostic {
+            range: (5, 10),
+            msg: "test diagnostic".into(),
+        },
+    );
+    lines_edit.add_diagnostic(
+        8,
+        line::LineDiagnostic {
+            range: (6, 14),
+            msg: "another test diagnostic".into(),
+        },
+    );
 
     lines_edit.edit.goto(TreeCursor::home());
 
-    let mut edit = lines_edit.edit.clone();
+    let edit = lines_edit.edit.clone();
 
     /* setup terminal
      */
diff --git a/examples/tty-07-color/Cargo.toml b/examples/tty-07-color/Cargo.toml
index 53db651..d5299b8 100644
--- a/examples/tty-07-color/Cargo.toml
+++ b/examples/tty-07-color/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "tty-06-color"
+name = "tty-07-color"
 version = "0.1.0"
 edition = "2021"
 
@@ -16,4 +16,3 @@ cgmath = "*"
 [dependencies.async-std]
 version = "1.9.0"
 features = ["unstable", "attributes"]
-
diff --git a/examples/tty-07-color/src/main.rs b/examples/tty-07-color/src/main.rs
index e02ae87..afe5403 100644
--- a/examples/tty-07-color/src/main.rs
+++ b/examples/tty-07-color/src/main.rs
@@ -10,7 +10,7 @@ use {
         editors::{
             ObjCommander
         },
-        repr_tree::{Context, ReprTree, ReprTreeExt, ReprLeaf},
+        repr_tree::{Context, ReprTree, ReprTreeBuilder, ReprTreeExt, ReprTreeArc, ReprLeaf},
         edit_tree::{EditTree, TreeNav, TreeCursor}
     },
     nested_tty::{
@@ -46,139 +46,57 @@ async fn main() {
         Context::parse(&ctx, "<Vec EditTree>")
     );
 
-    let mut red = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, "
-            ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ <Vec Char>
-        "),
-        "221"
-    );
-    ctx.read().unwrap().apply_morphism( &red,
-        &laddertypes::MorphismType {
-            src_type: Context::parse(&ctx, "ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10> ~ Char > ~ <Vec Char>"),
-            dst_type: Context::parse(&ctx, "ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > ~ EditTree")
-        });
-    let red_edit = ctx.read().unwrap().setup_edittree(
-        red.descend(Context::parse(&ctx, "
-                ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16>~Char>
-            ")).unwrap(),
-        SingletonBuffer::new(0).get_port()
-    ).unwrap();
+    let channel_builder = ReprTreeBuilder::new(ctx.clone())
+        .require(Context::parse(&ctx, "
+            ℕ ~ <PosInt 10 BigEndian> ~ EditTree
+        "))
+        .require(Context::parse(&ctx, "
+            ℕ ~ <PosInt 16 BigEndian> ~ EditTree
+        "));
 
-    let mut green = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, "
-            ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ <Vec Char>
-        "),
-        "220"
-    );
-    ctx.read().unwrap().apply_morphism( &green,
-        &laddertypes::MorphismType {
-            src_type: Context::parse(&ctx, "ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10> ~ Char > ~ <Vec Char>"),
-            dst_type: Context::parse(&ctx, "ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > ~ EditTree")
-        });
-     let green_edit = ctx.read().unwrap().setup_edittree(green.descend(Context::parse(&ctx, "
-                ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16>~Char>
-            ")).unwrap(),
-        SingletonBuffer::new(0).get_port()
-    ).unwrap();
+    let mut red = nested::repr_tree::ReprTree::from_str("221");
+    red.write().unwrap().set_halo(Context::parse(&ctx, "
+        ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char>
+    "));
+    red = channel_builder.build_from(red).expect("");
 
-    
-    let mut blue = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, "
-            ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10>> ~ <List <Digit 10> ~ Char> ~ <Vec Char>
-        "),
-        "5"
-    );
-    ctx.read().unwrap().apply_morphism( &blue,
-        &laddertypes::MorphismType {
-            src_type: Context::parse(&ctx, "ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10> ~ Char > ~ <Vec Char>"),
-            dst_type: Context::parse(&ctx, "ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > ~ EditTree")
-        });
-    let blue_edit = ctx.read().unwrap().setup_edittree(
-        blue.descend(Context::parse(&ctx, "
-                ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16>~Char>
-            ")).unwrap(),
-        SingletonBuffer::new(0).get_port()
-    ).unwrap();
+    let mut green = nested::repr_tree::ReprTree::from_str("220");
+    green.write().unwrap().set_halo(Context::parse(&ctx, "
+        ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char>
+    "));
+    green = channel_builder.build_from(green).expect("");
 
+    let mut blue = nested::repr_tree::ReprTree::from_str("150");
+    blue.write().unwrap().set_halo(Context::parse(&ctx, "
+        ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char>
+    "));
+    blue = channel_builder.build_from(blue).expect("");
+
+    let mut color_builder = ReprTreeBuilder::new(ctx.clone())
+        .require(Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian>> ~ EditTree"))
+        .require(Context::parse(&ctx, "<List ℕ ~ <PosInt 10 BigEndian>> ~ EditTree"))
+        ;
 
-    eprintln!("======\n   M A K E    L I S T    E D I T O R\n======\n");
-    
     let mut color = nested::repr_tree::ReprTree::new_arc(
         Context::parse(&ctx, "<List ℕ>")
     );
-
     color.insert_leaf(
         Context::parse(&ctx, "
-                <List   ℕ
-                      ~ <PosInt 16 BigEndian>
-                      ~ <Seq <Digit 16>>
-                      ~ <List  <Digit 16>
-                              ~ Char >
-                >
-                ~ <List EditTree>
-                ~ <Vec EditTree>
+                < List   ℕ ~ ReprTree >
+                ~ < Vec ReprTree >
             "),
-
-        ReprLeaf::from_vec_buffer(VecBuffer::<
-            Arc<RwLock< EditTree >>
-        >::with_data(vec![
-            red_edit.get(),
-            green_edit.get(),
-            blue_edit.get()
-        ]))
+        ReprLeaf::from_vec_buffer(VecBuffer::<ReprTreeArc>::with_data(
+            vec![ red, green, blue ])
+        )
+    );
+/*
+    color.attach_leaf_to(
+        Context::parse(&ctx, "< List ℕ ~ <PosInt 10 BigEndian> ~ EditTre >"),
+        color.descend(Context::parse(&ctx, "<List ℕ ~ ReprTree> ~ <Vec ReprTree>"))
+            .expect("descend")
+            .
     );
-    ctx.read().unwrap().apply_morphism(
-        &color,
-        &laddertypes::MorphismType {
-            src_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > ~ EditTree > ~ <Vec EditTree>"),
-            dst_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > > ~ EditTree")
-        });
-    let edit = ctx.read().unwrap().setup_edittree(
-        color.descend(Context::parse(&ctx, "
-                <List   ℕ
-                      ~ < PosInt 16 BigEndian >
-                      ~ < Seq~List   <Digit 16>
-                                   ~ Char >
-                >
-            ")).unwrap(),
-        SingletonBuffer::new(0).get_port()
-    ).unwrap();
-
-
-
-eprintln!(" edittree => list list char ");
-     ctx.read().unwrap().apply_morphism(
-        &color,
-        &laddertypes::MorphismType {
-            src_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > > ~ EditTree"),
-            dst_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char > >")
-        });
-
-eprintln!("list char ==> list u64");
-    ctx.read().unwrap().apply_morphism(
-        &color,
-        &laddertypes::MorphismType {
-            src_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ Char>>"),
-            dst_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ ℤ_2^64 ~ machine.UInt64>>")
-        });
-return;
-
-    ctx.read().unwrap().apply_morphism(
-        &color,
-        &laddertypes::MorphismType {
-            src_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16> ~ ℤ_2^64 ~ machine.UInt64 > >"),
-            dst_type: Context::parse(&ctx, "<List ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10> ~ Char > >")
-        });
-    /*
-    let edit2 = ctx.read().unwrap().setup_edittree(
-        color.descend(Context::parse(&ctx, "
-                <List   ℕ
-                      ~ < PosInt 10 BigEndian >
-                      ~ < Seq~List   <Digit 10>
-                                   ~ Char >
-                >
-            ")).unwrap(),
-        SingletonBuffer::new(0).get_port()
-    ).unwrap();
 */
-
     return;
 
     /* setup terminal
@@ -187,12 +105,12 @@ return;
         /* event handler
          */
         let ctx = ctx.clone();
-        let edit = edit.get().clone();
+        //let edit = edit.get().clone();
+
+       // edit.write().unwrap().goto(TreeCursor::home());
 
-        edit.write().unwrap().goto(TreeCursor::home());
-        
         move |ev| {
-            edit.write().unwrap().send_cmd_obj( ev.to_repr_tree(&ctx) );
+      //      edit.write().unwrap().send_cmd_obj( ev.to_repr_tree(&ctx) );
         }
     });
 
@@ -213,7 +131,7 @@ return;
             let halo_type = rt_edittree.read().unwrap().get_halo_type().clone();
             let edittree = rt_edittree.read().unwrap().get_view::<dyn r3vi::view::singleton::SingletonView<Item = Arc<RwLock<EditTree>>>>().unwrap().get().read().unwrap().clone();
 
-            comp.push(  nested_tty::make_label( &ctx.read().unwrap().type_term_to_str(&halo_type) ) 
+            comp.push(  nested_tty::make_label( &ctx.read().unwrap().type_term_to_str(&halo_type) )
                 .map_item(|_pt, atom| atom.add_style_front(TerminalStyle::fg_color((90,90,90))))
                 .offset(Vector2::new(1,y)));
 
@@ -221,12 +139,11 @@ return;
                 .offset(Vector2::new(1,y+1)));
         }
 
-        show_edit_tree( &ctx, &mut comp, &color.descend(Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16>~Char>>")).unwrap(), 1 );        
-        show_edit_tree( &ctx, &mut comp, &color.descend(Context::parse(&ctx, "<List ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char>>")).unwrap(), 3 );
+    //    show_edit_tree( &ctx, &mut comp, &color.descend(Context::parse(&ctx, "<List ℕ ~ <PosInt 16 BigEndian> ~ <Seq~List <Digit 16>~Char>>")).unwrap(), 1 );
+    //    show_edit_tree( &ctx, &mut comp, &color.descend(Context::parse(&ctx, "<List ℕ ~ <PosInt 10 BigEndian> ~ <Seq~List <Digit 10>~Char>>")).unwrap(), 3 );
     }
 
     /* write the changes in the view of `term_port` to the terminal
      */
     app.show().await.expect("output error!");
 }
-
diff --git a/lib-nested-core/src/editors/list/ctx.rs b/lib-nested-core/src/editors/list/ctx.rs
index 1d00b34..58ee1d5 100644
--- a/lib-nested-core/src/editors/list/ctx.rs
+++ b/lib-nested-core/src/editors/list/ctx.rs
@@ -261,7 +261,7 @@ pub fn init_ctx(ctx: Arc<RwLock<Context>>) {
     ctx.write().unwrap().add_varname("Item");
 
     let list_morph_editsetup1 = GenericReprTreeMorphism::new(
-        Context::parse(&ctx, "<List Item>~<List ReprTree>~<Vec ReprTree>"),
+        Context::parse(&ctx, "<List~Vec Item~ReprTree>"),
         Context::parse(&ctx, "<List Item>~EditTree"),
         {
             let ctx = ctx.clone();
diff --git a/lib-nested-core/src/repr_tree/builder.rs b/lib-nested-core/src/repr_tree/builder.rs
index 47002f6..ea8c541 100644
--- a/lib-nested-core/src/repr_tree/builder.rs
+++ b/lib-nested-core/src/repr_tree/builder.rs
@@ -1,23 +1,11 @@
 use {
-    r3vi::{
-        view::{
-            ViewPort, OuterViewPort,
-            AnyViewPort, AnyInnerViewPort, AnyOuterViewPort,
-            port::UpdateTask,
-            View, Observer,
-            singleton::*,
-            sequence::*,
-            list::*
-        },
-        buffer::{singleton::*, vec::*}
-    },
-    laddertypes::{TypeTerm, TypeID, sugar::*},
-    std::{
-        collections::HashMap,
-        sync::{Arc, RwLock},
-        any::Any
-    },
-    super::{Context, ReprLeaf, ReprTree, ReprTreeExt, context::{TYPEID_list, TYPEID_vec, TYPEID_char, TYPEID_u64, TYPEID_edittree}}
+    super::{context::{TYPEID_char, TYPEID_edittree, TYPEID_list, TYPEID_u64, TYPEID_vec}, Context, ReprLeaf, ReprTree, ReprTreeExt}, laddertypes::{steiner_tree, sugar::*, unparser::UnparseLadderType as _, TypeID, TypeTerm}, r3vi::{
+        buffer::{singleton::*, vec::*}, view::{
+            list::*, port::UpdateTask, sequence::*, singleton::*, AnyInnerViewPort, AnyOuterViewPort, AnyViewPort, Observer, OuterViewPort, View, ViewPort
+        }
+    }, std::{
+        any::Any, collections::HashMap, sync::{Arc, RwLock}
+    }
 };
 
 //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@@ -65,8 +53,8 @@ impl ReprTreeBuilder {
 
         let morphism_base = &self.ctx.read().unwrap().morphisms;
 
-        let mt = master_leaf_type.into();
-        //eprintln!("REBUILD repr tree from {}", self.ctx.read().unwrap().type_term_to_str(&mt));
+        let mt = master_leaf_type.into().normalize().param_normalize();
+        eprintln!("REBUILD repr tree from {}", self.ctx.read().unwrap().type_term_to_str(&mt));
         let mut leaves = self.required_leaves.clone();
         leaves.retain(|t| t != &mt);
 
@@ -77,18 +65,32 @@ impl ReprTreeBuilder {
 
         if let Some( steiner_tree ) = st_problem.solve( &morphism_base ) {
             eprintln!("--> from {}", self.ctx.read().unwrap().type_term_to_str(&mt));
-            for morphism_type in steiner_tree.into_edges() {
+
+            let edges = steiner_tree.into_edges();
+            eprintln!("steiner tree has {} edges", edges.len());
+            for morphism_type in edges {
                 eprintln!("--> morph to {}",
                     self.ctx.read().unwrap().type_term_to_str(&morphism_type.dst_type));
 
-                if let Some(( morphism, mut τ, σ )) =
-                    morphism_base.find_morphism_with_subtyping( &morphism_type )
+                let mut dict = self.ctx.read().unwrap().type_dict.clone();
+
+                if let Some(morph_inst) =
+                    morphism_base.find_morphism( &morphism_type, &mut dict )
                 {
-                    let mut rt = rt.descend_create( τ ).expect("descend src repr");
-                    (morphism.setup_projection)( &mut rt, &σ );
+                    eprintln!("setup morph");
+
+                    let halo = laddertypes::common_halo(
+                        &morphism_type.src_type,
+                        &morphism_type.dst_type
+                    ).unwrap_or(TypeTerm::unit());
+                    eprintln!("halo = {}", dict.read().unwrap().unparse(&halo));
+
+                    let mut rt = rt.descend_create( halo ).expect("descend src repr");
+                    eprintln!("{}", rt.read().unwrap().fmt(&self.ctx, 0));
+                    (morph_inst.m.setup_projection)( &mut rt, &morph_inst.σ );
                 } else {
                     eprintln!("failed to get morphism");
-                    //return Err(ReprTreeError::MissingMorphism);
+                    return Err(ReprTreeError::MissingMorphism);
                 }
             }
 
diff --git a/lib-nested-core/src/repr_tree/context.rs b/lib-nested-core/src/repr_tree/context.rs
index 8254090..8fdea0a 100644
--- a/lib-nested-core/src/repr_tree/context.rs
+++ b/lib-nested-core/src/repr_tree/context.rs
@@ -53,22 +53,28 @@ pub struct Context {
 
 impl Context {
     pub fn with_parent(parent: Option<Arc<RwLock<Context>>>) -> Self {
-        Context {
-            type_dict: match parent.as_ref() {
-                Some(p) => p.read().unwrap().type_dict.clone(),
-                None => {
-                    let mut dict = BimapTypeDict::new();
-                    assert_eq!(TYPEID_reprtree, dict.add_typename("ReprTree".into()));
-                    assert_eq!(TYPEID_edittree, dict.add_typename("EditTree".into()));
-                    assert_eq!(TYPEID_char, dict.add_typename("Char".into()));
-                    assert_eq!(TYPEID_u64, dict.add_typename("machine.UInt64".into()));
-                    assert_eq!(TYPEID_list, dict.add_typename("List".into()));
-                    assert_eq!(TYPEID_vec, dict.add_typename("Vec".into()));
 
-                    Arc::new(RwLock::new(dict))
-                }
-            },
-            morphisms: MorphismBase::new(TYPEID_list),
+        let mut dict = match parent.as_ref() {
+            Some(p) => p.read().unwrap().type_dict.clone(),
+            None => {
+                let mut dict = BimapTypeDict::new();
+                assert_eq!(TYPEID_reprtree, dict.add_typename("ReprTree".into()));
+                assert_eq!(TYPEID_edittree, dict.add_typename("EditTree".into()));
+                assert_eq!(TYPEID_char, dict.add_typename("Char".into()));
+                assert_eq!(TYPEID_u64, dict.add_typename("machine.UInt64".into()));
+                assert_eq!(TYPEID_list, dict.add_typename("List".into()));
+                assert_eq!(TYPEID_vec, dict.add_typename("Vec".into()));
+
+                Arc::new(RwLock::new(dict))
+            }
+        };
+
+        Context {
+            type_dict: dict.clone(),
+            morphisms: MorphismBase::new(vec![
+                dict.parse("List").expect(""),
+                //dict.parse("Vec").expect("")
+            ]),
             nodes: HashMap::new(),
             list_types: match parent.as_ref() {
                 Some(p) => p.read().unwrap().list_types.clone(),
@@ -104,22 +110,9 @@ impl Context {
 
     pub fn apply_morphism(&self, rt: &Arc<RwLock<ReprTree>>, ty: &MorphismType) {
         if let Some(path) = self.morphisms.find_morphism_path(ty.clone().normalize()) {
-            let mut path = path.into_iter();
-            if let Some(mut src_type) = path.next() {
-                for dst_type in path {
-                    if let Some((m, mut τ, σ)) =
-                        self.morphisms
-                            .find_morphism_with_subtyping(&laddertypes::MorphismType {
-                                src_type: src_type.clone(),
-                                dst_type: dst_type.clone(),
-                            })
-                    {
-                        let mut rt = rt.descend(τ).expect("descend src repr");
-                        (m.setup_projection)(&mut rt, &σ);
-                    }
-
-                    src_type = dst_type;
-                }
+            for morph_inst in path {
+                let mut rt = rt.descend(morph_inst.halo).expect("descend src repr");
+                (morph_inst.m.setup_projection)(&mut rt, &morph_inst.σ);
             }
         } else {
             eprintln!("no path found");
diff --git a/lib-nested-core/src/repr_tree/morphism.rs b/lib-nested-core/src/repr_tree/morphism.rs
index c5e5e8a..d841d94 100644
--- a/lib-nested-core/src/repr_tree/morphism.rs
+++ b/lib-nested-core/src/repr_tree/morphism.rs
@@ -27,13 +27,19 @@ pub struct GenericReprTreeMorphism {
     >
 }
 
+impl PartialEq  for GenericReprTreeMorphism {
+    fn eq(&self, other: &Self) -> bool {
+        self.morph_type == other.morph_type
+    }
+}
+
 impl Morphism for GenericReprTreeMorphism {
     fn get_type(&self) -> MorphismType {
         self.morph_type.clone()
     }
 
-    fn list_map_morphism(&self, list_typeid: TypeID) -> Option< GenericReprTreeMorphism > {
-        self.into_list_map_dyn(list_typeid)
+    fn map_morphism(&self, seq_type: TypeTerm) -> Option< GenericReprTreeMorphism > {
+        self.into_list_map_dyn(seq_type)
     }
 }
 
@@ -54,7 +60,7 @@ impl GenericReprTreeMorphism {
         }
     }
 
-    pub fn into_list_map< SrcItem, DstItem >(&self, list_typeid: TypeID)
+    pub fn into_list_map< SrcItem, DstItem >(&self, seq_type: TypeTerm)
     -> GenericReprTreeMorphism
     where
         SrcItem: Clone + Send + Sync + 'static,
@@ -62,11 +68,11 @@ impl GenericReprTreeMorphism {
     {
         let mut lst_map_type = MorphismType {
             src_type: TypeTerm::App(vec![
-                TypeTerm::TypeID(list_typeid),
+                seq_type.clone(),
                 self.morph_type.src_type.clone()
             ]),
             dst_type: TypeTerm::App(vec![
-                TypeTerm::TypeID(list_typeid),
+                seq_type.clone(),
                 self.morph_type.dst_type.clone()
             ])
         }.normalize();
@@ -86,14 +92,13 @@ impl GenericReprTreeMorphism {
                     "lst map type ::\n {:?}\n===>  {:?}\n\n", lst_map_type.src_type, lst_map_type.dst_type
                 );
 
-                
                 let mut item_ladder = item_morph.morph_type.src_type.clone().get_lnf_vec();
                 let top_type = item_ladder.remove( item_ladder.len() - 1 );
 
                 if let Ok(item_sigma) = laddertypes::unify(
                     &top_type,
                     &TypeTerm::App(vec![
-                        TypeTerm::TypeID( list_typeid ),
+                        seq_type.clone(),
                         TypeTerm::TypeID( TypeID::Var( 200 ) )
                     ])
                 ) {
@@ -113,7 +118,7 @@ impl GenericReprTreeMorphism {
                                     top_type.clone(),
                                     r3vi::buffer::singleton::SingletonBuffer::new(x.clone())
                             );
-                            
+
 
                             // TODO: required?
                             for t in item_ladder.iter().rev() {
@@ -139,43 +144,43 @@ impl GenericReprTreeMorphism {
         }
     }
 
-    pub fn into_list_map_dyn(&self, typeid_list: TypeID)
+    pub fn into_list_map_dyn(&self, seq_type: TypeTerm)
     -> Option< GenericReprTreeMorphism >
-    {        
+    {
         let src_item_type_lnf = self.morph_type.src_type.clone().get_lnf_vec();
         let dst_item_type_lnf = self.morph_type.dst_type.clone().get_lnf_vec();
 
-        eprintln!("into list map dyn");
+        eprintln!("into list map dyn:\n src {:?}\n dst {:?}", src_item_type_lnf, dst_item_type_lnf);
 
         if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) &&
            dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char))
         {
-            Some( self.into_list_map::< char, char >(TYPEID_list) )
+            Some( self.into_list_map::< char, char >( seq_type ) )
         }
         else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_u64)) &&
            dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_u64))
         {
-            Some( self.into_list_map::< u64, u64 >(TYPEID_list) )
+            Some( self.into_list_map::< u64, u64 >( seq_type ) )
         }
         else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) &&
            dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_u64))
         {
-            Some( self.into_list_map::< char, u64 >(TYPEID_list) )
+            Some( self.into_list_map::< char, u64 >( seq_type ) )
         }
         else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_u64)) &&
                 dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char))
         {
-            Some( self.into_list_map::< u64, char >(TYPEID_list) )
+            Some( self.into_list_map::< u64, char >( seq_type ) )
         }
         else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char)) &&
                 dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_edittree))
         {
-            Some( self.into_list_map::< char, Arc<RwLock<crate::edit_tree::EditTree>> >(TYPEID_list) )
+            Some( self.into_list_map::< char, Arc<RwLock<crate::edit_tree::EditTree>> >(seq_type) )
         }
         else if src_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_edittree)) &&
                 dst_item_type_lnf.last() == Some(&TypeTerm::TypeID(TYPEID_char))
         {
-            Some( self.into_list_map::< Arc<RwLock<crate::edit_tree::EditTree>>, char >(TYPEID_list) )
+            Some( self.into_list_map::< Arc<RwLock<crate::edit_tree::EditTree>>, char >(seq_type) )
         }
 /*
         else if src_item_type_lnf.last() == Some(&TypeTerm::App(vec![ TypeTerm::TypeID(typeid_list), TypeTerm::TypeID(typeid_char) ])) &&
@@ -208,4 +213,3 @@ impl GenericReprTreeMorphism {
 }
 
 //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
-
diff --git a/todo.md b/todo.md
new file mode 100644
index 0000000..8bfb27f
--- /dev/null
+++ b/todo.md
@@ -0,0 +1,27 @@
+# Workbench
+* TreeType trait
+* TypedCursor widget
+
+# Layouting
+* Columns, word-oriented line breaks
+
+# Navigation
+* save Cursor Gravity mode in editor
+* find intuitive scheme to switch gravity mode
+
+# Editing
+* Char Editor: escape chars \n \t etc.
+* Range Seletcion
+* Drag/Move
+
+# Refactor
+* Proper Variable Scoping in Type Terms
+* cleaner type substitutions
+* TreeNavCmd via ObjCommander → remove tree_nav in NestedNode
+* lib crates: add prelude
+* rename
+  OuterViewPort -> OutPort
+  InnerViewPort -> InPort
+  AnyOuterViewPort -> AnyOutPort
+  AnyInnerViewPort -> AnyInPort
+