context: add meta_chars collection

This commit is contained in:
Michael Sippel 2023-05-19 11:26:05 +02:00
parent 52efcfc6c6
commit 66c6478124
Signed by: senvas
GPG key ID: 060F22F65102F95C
9 changed files with 198 additions and 71 deletions

View file

@ -32,11 +32,19 @@ impl ObjCommander for CharEditor {
if cmd_type == char_type {
if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
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
}
}
}

View file

@ -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 '")),

View file

@ -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 {

View file

@ -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<char>,
close_char: Option<char>
) {
{
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::<ListEditor>().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<dyn SequenceView<Item = NestedNode>> {
@ -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::<dyn SingletonView<Item = char>>() {
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::<dyn SingletonView<Item = char>>() {
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
}

View file

@ -36,6 +36,7 @@ pub struct NestedNode {
pub diag: Option<OuterViewPort<dyn SequenceView<Item = Message>>>,
/// commander
pub close_char: Option<char>,
pub cmd: Option<Arc<RwLock<dyn ObjCommander + Send + Sync>>>,
/// tree navigation
@ -155,6 +156,7 @@ impl NestedNode {
view: None,
diag: None,
cmd: None,
close_char: None,
tree_nav: None
}
}

View file

@ -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<TypeID>,
pub dst_tyid: TypeID
@ -62,6 +62,7 @@ impl From<MorphismType> for MorphismTypePattern {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
#[derive(Clone)]
pub struct Context {
/// assigns a name to every type
pub type_dict: Arc<RwLock<TypeDict>>,
@ -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 {

View file

@ -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::<ListEditor>().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::<dyn SingletonView<Item = NestedNode>>().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<RwLock<Context>>, 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::<dyn SingletonView<Item = char>>() {
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 {

View file

@ -89,12 +89,7 @@ pub fn init_editor_ctx(parent: Arc<RwLock<Context>>) -> Arc<RwLock<Context>> {
|ctx: Arc<RwLock<Context>>, 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();

View file

@ -18,6 +18,18 @@ pub struct ReprTree {
branches: HashMap<TypeTerm, Arc<RwLock<ReprTree>>>,
}
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<TypeTerm>) -> Self {
ReprTree {