From 66c647812474828bebaba7eabb8f4e4609aea258 Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Fri, 19 May 2023 11:26:05 +0200 Subject: [PATCH] context: add meta_chars collection --- nested/src/editors/char/mod.rs | 16 +++- nested/src/editors/integer/editor.rs | 6 +- nested/src/editors/list/editor.rs | 18 ++++- nested/src/editors/list/pty_editor.rs | 102 ++++++++++++++++---------- nested/src/tree/node.rs | 2 + nested/src/type_system/context.rs | 20 +++-- nested/src/type_system/editor.rs | 86 ++++++++++++++++++---- nested/src/type_system/make_editor.rs | 7 +- nested/src/type_system/repr_tree.rs | 12 +++ 9 files changed, 198 insertions(+), 71 deletions(-) diff --git a/nested/src/editors/char/mod.rs b/nested/src/editors/char/mod.rs index 23794c3..9f5a54a 100644 --- a/nested/src/editors/char/mod.rs +++ b/nested/src/editors/char/mod.rs @@ -32,11 +32,19 @@ impl ObjCommander for CharEditor { if cmd_type == char_type { if let Some(cmd_view) = cmd_obj.get_view::>() { let value = cmd_view.get(); - self.data.set(Some(value)); - } - } - TreeNavResult::Continue + if self.ctx.read().unwrap().meta_chars.contains(&value) { + TreeNavResult::Exit + } else { + self.data.set(Some(value)); + TreeNavResult::Continue + } + } else { + TreeNavResult::Exit + } + } else { + TreeNavResult::Exit + } } } diff --git a/nested/src/editors/integer/editor.rs b/nested/src/editors/integer/editor.rs index b0cdc11..93f7636 100644 --- a/nested/src/editors/integer/editor.rs +++ b/nested/src/editors/integer/editor.rs @@ -49,7 +49,11 @@ impl ObjCommander for DigitEditor { self.data.set(Some(c)); self.msg.clear(); - if c.to_digit(self.radix).is_none() { + + if self.ctx.read().unwrap().meta_chars.contains(&c) { + return TreeNavResult::Exit; + } + else if c.to_digit(self.radix).is_none() { let mut mb = IndexBuffer::new(); mb.insert_iter(vec![ (Point2::new(1, 0), make_label("invalid digit '")), diff --git a/nested/src/editors/list/editor.rs b/nested/src/editors/list/editor.rs index f944579..d98d9f2 100644 --- a/nested/src/editors/list/editor.rs +++ b/nested/src/editors/list/editor.rs @@ -5,7 +5,7 @@ use { }, crate::{ type_system::{Context, TypeTerm, ReprTree}, - editors::list::{ListCursor, ListCursorMode}, + editors::list::{ListCursor, ListCursorMode, PTYListController, PTYListStyle}, tree::{NestedNode, TreeNav, TreeCursor}, diagnostics::Diagnostics }, @@ -41,7 +41,13 @@ impl ListEditor { } => { if args.len() > 0 { let typ = (args[0].clone().0)[0].clone(); - Some(ListEditor::new(ctx, typ).into_node(depth)) + + let mut node = ListEditor::new(ctx.clone(), typ).into_node(depth); + + PTYListController::for_node( &mut node, Some(','), Some('}') ); + PTYListStyle::for_node( &mut node, ("{",", ","}") ); + + Some(node) } else { None } @@ -250,7 +256,7 @@ impl ListEditor { if self.is_listlist() { cur.mode = ListCursorMode::Select; } else { - cur.idx = Some(idx + 1); + cur.idx = Some(idx + 1); } } @@ -263,12 +269,16 @@ impl ListEditor { } self.cursor.set(cur); + } else { + //eprintln!("insert: no cursor"); } } /// split the list off at the current cursor position and return the second half pub fn split(&mut self) -> ListEditor { - let mut le = ListEditor::new(self.ctx.clone(), self.typ.clone()); + let mut le = ListEditor::new( + Arc::new(RwLock::new(self.ctx.read().unwrap().clone())), + self.typ.clone()); let cur = self.cursor.get(); if let Some(idx) = cur.idx { diff --git a/nested/src/editors/list/pty_editor.rs b/nested/src/editors/list/pty_editor.rs index 9976851..c6fb3ea 100644 --- a/nested/src/editors/list/pty_editor.rs +++ b/nested/src/editors/list/pty_editor.rs @@ -13,6 +13,7 @@ use { PtySegment }, std::sync::{Arc, RwLock}, + std::any::{Any}, termion::event::{Event, Key} }; @@ -101,10 +102,23 @@ impl PTYListController { split_char: Option, close_char: Option ) { + { + let mut ctx = node.ctx.as_ref().unwrap(); + let mut ctx = ctx.write().unwrap(); + + if let Some(c) = split_char.as_ref() { + ctx.meta_chars.push(*c); + } + if let Some(c) = close_char.as_ref() { + ctx.meta_chars.push(*c); + } + } + let editor = node.get_edit::().unwrap(); let controller = Arc::new(RwLock::new(PTYListController::from_editor( editor, split_char, close_char, node.depth ))); node.cmd = Some(controller.clone()); + node.close_char = close_char; } pub fn get_data_port(&self) -> OuterViewPort> { @@ -285,55 +299,67 @@ impl ObjCommander for PTYListController { } else { TreeNavResult::Exit } - } else if cmd_type == char_type && cur.mode == ListCursorMode::Select { - if let Some(cmd_view) = co.get_view::>() { - drop(co); - let c = cmd_view.get(); + } - if Some(c) == self.split_char && cur_depth == 2 { - e.listlist_split(); - TreeNavResult::Continue - } else { - if let Some(mut item) = e.get_item_mut() { - match item.send_cmd_obj(cmd_obj) { - TreeNavResult::Continue => TreeNavResult::Continue, - TreeNavResult::Exit => { - if Some(c) == self.split_char { - e.listlist_split(); - } - - item.goto(TreeCursor::none()); - e.cursor.set(ListCursor { - mode: ListCursorMode::Insert, - idx: Some(cur.idx.unwrap_or(0)+1) - }); - - TreeNavResult::Continue - } - } - } else { - TreeNavResult::Exit - } - } - } else { - TreeNavResult::Exit - } - } else { + else { drop(co); - match cur.mode { ListCursorMode::Insert => { let mut new_edit = Context::make_node(&e.ctx, e.typ.clone(), self.depth).unwrap(); new_edit.goto(TreeCursor::home()); - new_edit.send_cmd_obj(cmd_obj); - e.insert(new_edit); + match new_edit.send_cmd_obj(cmd_obj.clone()) { + TreeNavResult::Continue => { + e.insert(new_edit); + TreeNavResult::Continue + } - TreeNavResult::Continue + TreeNavResult::Exit => { + //eprintln!("listedit: exit from insert mode"); + TreeNavResult::Exit + } + } }, ListCursorMode::Select => { if let Some(mut item) = e.get_item_mut() { - item.send_cmd_obj(cmd_obj) + match item.send_cmd_obj(cmd_obj.clone()) { + TreeNavResult::Continue => { + TreeNavResult::Continue + } + + TreeNavResult::Exit => { + if cmd_type == char_type { + let co = cmd_obj.read().unwrap(); + if let Some(cmd_view) = co.get_view::>() { + drop(co); + let c = cmd_view.get(); + + //eprintln!("close char = {:?}", item.close_char); + + if Some(c) == self.split_char { + //eprintln!("listlist_split"); + e.listlist_split(); + TreeNavResult::Continue + } else if Some(c) == item.close_char { + //eprintln!("listedit: exit from select (close)"); + //item.goto(TreeCursor::none()); + e.cursor.set(ListCursor { + mode: ListCursorMode::Insert, + idx: Some(cur.idx.unwrap_or(0)+1) + }); + TreeNavResult::Continue + } else { + //eprintln!("listedit: exit from select mode"); + TreeNavResult::Exit + } + } else { + TreeNavResult::Exit + } + } else { + TreeNavResult::Exit + } + } + } } else { TreeNavResult::Exit } diff --git a/nested/src/tree/node.rs b/nested/src/tree/node.rs index d530104..360cd2d 100644 --- a/nested/src/tree/node.rs +++ b/nested/src/tree/node.rs @@ -36,6 +36,7 @@ pub struct NestedNode { pub diag: Option>>, /// commander + pub close_char: Option, pub cmd: Option>>, /// tree navigation @@ -155,6 +156,7 @@ impl NestedNode { view: None, diag: None, cmd: None, + close_char: None, tree_nav: None } } diff --git a/nested/src/type_system/context.rs b/nested/src/type_system/context.rs index cf9fd85..0edf8ae 100644 --- a/nested/src/type_system/context.rs +++ b/nested/src/type_system/context.rs @@ -38,7 +38,7 @@ pub struct MorphismType { pub dst_type: TypeTerm, } -#[derive(Hash, Eq, PartialEq, Debug)] +#[derive(Clone, Hash, Eq, PartialEq, Debug)] pub struct MorphismTypePattern { pub src_tyid: Option, pub dst_tyid: TypeID @@ -62,6 +62,7 @@ impl From for MorphismTypePattern { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> +#[derive(Clone)] pub struct Context { /// assigns a name to every type pub type_dict: Arc>, @@ -71,7 +72,8 @@ pub struct Context { /// todo: beautify /// types that can be edited as lists - list_types: Vec< TypeID >, + pub list_types: Vec< TypeID >, + pub meta_chars: Vec< char >, /// graph constructors morphisms: HashMap< @@ -105,6 +107,10 @@ impl Context { Some(p) => p.read().unwrap().list_types.clone(), None => Vec::new() }, + meta_chars: match parent.as_ref() { + Some(p) => p.read().unwrap().meta_chars.clone(), + None => Vec::new() + }, parent, } } @@ -215,7 +221,10 @@ impl Context { dst_type: type_term.clone() })?; - mk_node(NestedNode::new(depth).set_ctx(ctx.clone()), type_term) + mk_node(NestedNode::new(depth).set_ctx( + Arc::new(RwLock::new( + Context::with_parent(Some(ctx.clone())))) + ), type_term) } pub fn morph_node(mut node: NestedNode, dst_type: TypeTerm) -> NestedNode { @@ -233,8 +242,9 @@ impl Context { } let pattern = MorphismType { src_type, dst_type: dst_type.clone() }.into(); - let ctx = ctx.read().unwrap(); - if let Some(transform) = ctx.get_morphism(pattern) { + + let m = ctx.read().unwrap().get_morphism(pattern); + if let Some(transform) = m { if let Some(new_node) = transform(node.clone(), dst_type) { new_node } else { diff --git a/nested/src/type_system/editor.rs b/nested/src/type_system/editor.rs index d93a9c8..d19312a 100644 --- a/nested/src/type_system/editor.rs +++ b/nested/src/type_system/editor.rs @@ -18,6 +18,7 @@ use { cgmath::{Vector2, Point2} }; +#[derive(PartialEq, Eq, Clone, Copy)] enum State { Any, Char, @@ -62,13 +63,39 @@ impl TypeTermEditor { ctx.add_morphism(pattern, Arc::new( |mut node, _dst_type:_| { - Some(TypeTermEditor::with_node( node.ctx.clone().unwrap(), node.depth, node, State::Any )) + //eprintln!("morphism to typeterm"); + + PTYListController::for_node( &mut node, Some(' '), None ); + PTYListStyle::for_node( &mut node, ("","","") ); + + let mut new_node = TypeTermEditor::with_node( node.ctx.clone().unwrap(), node.depth, node.clone(), State::Any ); + + let item_nodes = node.get_edit::().clone().unwrap(); + let item_nodes = item_nodes.read().unwrap(); + + for i in 0..item_nodes.data.len() { + if let Some(x) = item_nodes.data.get(i).data { + //eprintln!("item with {:?}", x); + //let c = x.read().unwrap().get_view::>().unwrap().get(); + new_node.send_cmd_obj( + ReprTree::from_char(&new_node.ctx.as_ref().unwrap(), 'x') + ); + //new_node.send_cmd_obj(c); + } + } + + if item_nodes.data.len() > 0 { + new_node.goto(TreeCursor::home()); + } + + Some(new_node) } ) ); } fn set_state(&mut self, new_state: State) { + let old_node = self.cur_node.get(); let mut node = match new_state { State::Char => { let mut node = Context::make_node( &self.ctx, (&self.ctx, "( Char )").into(), 0 ).unwrap(); @@ -83,6 +110,7 @@ impl TypeTermEditor { ] ); + node.close_char = Some('\''); node.view = Some( grid.get_port() .flatten() @@ -92,8 +120,9 @@ impl TypeTermEditor { State::List => { let mut node = Context::make_node( &self.ctx, (&self.ctx, "( List TypeTerm )").into(), 0 ).unwrap(); - PTYListController::for_node( &mut node, Some(' '), Some(')') ); - PTYListStyle::for_node( &mut node, ("("," ",")") ); + PTYListController::for_node( &mut node, Some(' '), Some('>') ); + PTYListStyle::for_node( &mut node, ("<"," ",">") ); + node } State::Symbol => { @@ -103,11 +132,12 @@ impl TypeTermEditor { Context::make_node( &self.ctx, (&self.ctx, "( PosInt 10 BigEndian )").into(), 0 ).unwrap() } _ => { - self.cur_node.get() + old_node } }; node.goto(TreeCursor::home()); + self.cur_node.set(node); self.state = new_state; } @@ -117,7 +147,7 @@ impl TypeTermEditor { } fn with_node(ctx: Arc>, depth: usize, node: NestedNode, state: State) -> NestedNode { - let editor = TypeTermEditor { + let mut editor = TypeTermEditor { ctx: ctx.clone(), state, cur_node: SingletonBuffer::new(node) @@ -155,6 +185,7 @@ impl TypeTermEditor { .to_grid() .flatten(); + let cc = editor.cur_node.get().close_char; let editor = Arc::new(RwLock::new(editor)); let mut node = NestedNode::new(depth) @@ -214,10 +245,10 @@ impl ObjCommander for TypeTermEditor { if let Some(cmd_view) = cmd_obj.get_view::>() { let c = cmd_view.get(); - match self.state { + match &self.state { State::Any => { match c { - '(' => { + '<' => { self.set_state( State::List ); TreeNavResult::Continue } @@ -233,8 +264,7 @@ impl ObjCommander for TypeTermEditor { _ => { self.set_state( State::Symbol ); self.cur_node.get_mut().goto(TreeCursor::home()); - self.cur_node.get_mut().send_cmd_obj( co ); - TreeNavResult::Continue + self.cur_node.get_mut().send_cmd_obj( co ) } } } @@ -246,15 +276,45 @@ impl ObjCommander for TypeTermEditor { TreeNavResult::Exit } _ => { - self.cur_node.get_mut().send_cmd_obj( co ); - TreeNavResult::Continue + self.cur_node.get_mut().send_cmd_obj( co ) + } + } + } + + State::List => { + match self.cur_node.get_mut().send_cmd_obj( co ) { + TreeNavResult::Continue => { + TreeNavResult::Continue + } + + TreeNavResult::Exit => { + match c { + '>' => { + let cur = self.get_cursor(); + + if cur.tree_addr.len() > 2 { + self.goto( + TreeCursor { + leaf_mode: ListCursorMode::Insert, + tree_addr: vec![ cur.tree_addr.get(0).unwrap_or(&0)+1 ] + } + ); + TreeNavResult::Continue + } else { + TreeNavResult::Exit + } + } + _ => { + TreeNavResult::Exit + } + } + } } } _ => { - self.cur_node.get_mut().send_cmd_obj( co ); - TreeNavResult::Continue + self.cur_node.get_mut().send_cmd_obj( co ) } } } else { diff --git a/nested/src/type_system/make_editor.rs b/nested/src/type_system/make_editor.rs index dd51ae2..748ea29 100644 --- a/nested/src/type_system/make_editor.rs +++ b/nested/src/type_system/make_editor.rs @@ -89,12 +89,7 @@ pub fn init_editor_ctx(parent: Arc>) -> Arc> { |ctx: Arc>, dst_typ: TypeTerm, depth: usize| { let mut node = Context::make_node( &ctx, - TypeTerm::Type { - id: ctx.read().unwrap().get_fun_typeid("List").unwrap(), - args: vec![ - TypeTerm::new(ctx.read().unwrap().get_typeid("Char").unwrap()).into() - ] - }, + (&ctx, "( List Char )").into(), depth+1 ).unwrap(); diff --git a/nested/src/type_system/repr_tree.rs b/nested/src/type_system/repr_tree.rs index 42eac89..52e8d32 100644 --- a/nested/src/type_system/repr_tree.rs +++ b/nested/src/type_system/repr_tree.rs @@ -18,6 +18,18 @@ pub struct ReprTree { branches: HashMap>>, } +impl std::fmt::Debug for ReprTree { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "type: {:?}", self.type_tag)?; + + for (k,x) in self.branches.iter() { + write!(f, "child: {:?}", x)?; + } + + Ok(()) + } +} + impl ReprTree { pub fn new(type_tag: impl Into) -> Self { ReprTree {