diff --git a/Cargo.toml b/Cargo.toml index 00261ad..c3f151d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "nested", "terminal/display_server", "terminal/ansi_parser", + "shell", "math/str2int", "math/int2str", "math/radix_transform", diff --git a/shell/Cargo.toml b/shell/Cargo.toml new file mode 100644 index 0000000..b3b735f --- /dev/null +++ b/shell/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "shell" +version = "0.1.0" +edition = "2018" + +[dependencies] +nested = { path = "../nested" } +cgmath = "*" +termion = "*" + +[dependencies.async-std] +version = "1.9.0" +features = ["unstable", "attributes"] diff --git a/shell/src/main.rs b/shell/src/main.rs new file mode 100644 index 0000000..96f8f50 --- /dev/null +++ b/shell/src/main.rs @@ -0,0 +1,411 @@ +use { + std::sync::RwLock, + cgmath::Point2, + termion::event::{Event, Key}, + nested::{ + core::{ + ViewPort, + OuterViewPort, + context::{ + ReprTree, + Object, + MorphismType, + MorphismMode, + Context + }, + port::{ + UpdateTask + } + }, + sequence::{SequenceView, VecBuffer}, + integer::{RadixProjection}, + terminal::{Terminal, TerminalAtom, TerminalStyle, TerminalCompositor, TerminalEvent}, + string_editor::StringEditor + } +}; + +#[async_std::main] +async fn main() { + /* todo: + +open:: +>0: +( Path ) +( Sequence ( Sequence UnicodeChar ) ) +( Sequence UnicodeChar ) +<1: +( FileDescriptor ) +( MachineInt ) + +read:: +>0: +( FileDescriptor ) +( MachineInt ) +<1: +( Sequence MachineSyllab ) +( Vec MachineSyllab ) + +write:: +>0 +( FileDescriptor ) +( MachineInt ) +>1: +( Sequence MachineSyllab ) +( Vec MachineSyllab ) + + */ + + let mut args = std::env::args(); + + let arg0_port = ViewPort::new(); + let _arg0 = VecBuffer::::with_data( + args.next().expect("Arg $0 missing!") + .chars().collect::>(), + arg0_port.inner() + ); +/* + let arg1_vec_port = ViewPort::new(); + let mut arg1 = VecBuffer::::with_data( + args.next().expect("Arg $1 missing!") + .chars().collect::>(), + arg1_vec_port.inner() + ); +*/ + + let arg1_vec = args.next().expect("Arg $1 missing!") + .chars().collect::>(); + + let term_port = ViewPort::new(); + let compositor = TerminalCompositor::new(term_port.inner()); + + let mut ed = StringEditor::new(); + + let mut term = Terminal::new(term_port.outer()); + let term_writer = term.get_writer(); + + async_std::task::spawn( + async move { + let mut ctx = Context::new(); + for tn in vec![ + "MachineWord", "MachineInt", "MachineSyllab", "Bits", + "Vec", "Stream", "Json", + "Sequence", "UTF-8-String", "UnicodeChar", + "PositionalInt", "Digit", "LittleEndian", "BigEndian", + "DiffStream", "ℕ" + ] { ctx.add_typename(tn.into()); } + + let src_type = + ctx.type_term_from_str("( Vec UnicodeChar )").unwrap(); + + let dst_type = + ctx.type_term_from_str("( Sequence UnicodeChar )").unwrap(); + + ctx.add_morphism( + MorphismType { + mode: MorphismMode::Epi, + src_type: src_type.clone(), + dst_type: dst_type.clone() + }, + Box::new(move |src| { + assert!(src.type_tag == src_type); + Object { + type_tag: dst_type.clone(), + repr: ReprTree::new_leaf( + src.get_port::>>().unwrap() + .to_sequence() + .into() + ) + } + }) + ); + + let src_type = ctx.type_term_from_str("( Sequence UnicodeChar )").unwrap(); + let dst_type = ctx.type_term_from_str("( Sequence ( Bits 32 ) )").unwrap(); + ctx.add_morphism( + MorphismType { + mode: MorphismMode::Mono, + src_type: src_type.clone(), + dst_type: dst_type.clone() + }, + Box::new({ + move |src| { + assert!(src.type_tag == src_type); + Object { + type_tag: dst_type.clone(), + repr: ReprTree::new_leaf( + src.get_port::>().unwrap() + .map( + |c| *c as u32 + ) + .into() + ) + } + } + }) + ); + +/* + let src_type = vec![ + ctx.type_term_from_str("( PositionalInteger )").unwrap(), + ]; + let dst_type = ctx.type_term_from_str("( Sequence MachineInt )").unwrap(); + ctx.add_morphism( + MorphismType { + mode: MorphismMode::Epi, + src_type: src_type.clone(), + dst_type: dst_type.clone() + }, + Box::new({ + move |src| { + assert!(src.type_tag == src_type); + Object { + type_tag: dst_type.clone(), + repr: ReprTree::new_leaf( + vec![ dst_type.clone() ].into_iter(), + src.get_port::>>().unwrap().to_sequence().into() + ) + } + } + }) + ); + */ + + let arg1_vec_port = ed.get_data_port(); + + ctx.add_obj("$1".into(), "( Vec UnicodeChar )"); + ctx.insert_repr( + "$1", + vec![].into_iter(), + arg1_vec_port.clone().into() + ); + + ctx.epi_cast("$1", "( Sequence UnicodeChar )"); + ctx.epi_cast("$1", "( Sequence ( Digit 10 ) )"); + ctx.epi_cast("$1", "( PositionalInt 10 LittleEndian )"); + ctx.epi_cast("$1", "( ℕ )"); + + let arg1_dec_unic_port: OuterViewPort> = + ctx.mono_view( + "$1", + vec![ + "( PositionalInt 10 LittleEndian )", + "( Sequence ( Digit 10 ) )", + "( Sequence UnicodeChar )" + ].into_iter() + ).unwrap(); + + let arg1_dec_mint_port: OuterViewPort> = + arg1_dec_unic_port + .map(|c| c.to_digit(10).map(|x| x as usize)) + .filter(|d| d.is_some()) + .map(|d| d.unwrap()); + + ctx.insert_repr( + "$1", + vec![ + "( PositionalInt 10 LittleEndian )", + "( Sequence ( Digit 10 ) )", + "( Sequence MachineInt )" + ].into_iter(), + arg1_dec_mint_port.clone().into() + ); + + let arg1_hex_mint_port: ViewPort>> + = ViewPort::new(); + let _radix_proj = RadixProjection::new( + 10, + 16, + arg1_dec_mint_port.clone(), + arg1_hex_mint_port.inner() + ); + + ctx.insert_repr( + "$1", + vec![ + "( PositionalInt 16 LittleEndian )", + "( Sequence ( Digit 16 ) )", + "( Sequence MachineInt )" + ].into_iter(), + arg1_hex_mint_port.outer().to_sequence().into() + ); + + let arg1_hex_unic_port: OuterViewPort> = + arg1_hex_mint_port.outer().to_sequence() + .map( + |d| char::from_digit(*d as u32, 16).unwrap() + ); + + ctx.insert_repr( + "$1", + vec![ + "( PositionalInt 16 LittleEndian )", + "( Sequence ( Digit 16 ) )", + "( Sequence UnicodeChar )" + ].into_iter(), + arg1_hex_unic_port.clone().into() + ); + + compositor.write().unwrap().push( + ed.insert_view() + .map_key( + |pt| Point2::new(40 as i16 - pt.x, 1 as i16), + |pt| if pt.y == 1 { Some(Point2::new(40 as i16 - pt.x, 0)) } else { None } + ) + .map_item( + |_pos, atom| + TerminalAtom::new( + atom.c.unwrap_or(' '), + TerminalStyle::fg_color( + if let Some(c) = atom.c { + if c == '|' { + (200, 200, 90) + } else if c.is_digit(10) { + (0, 200, 0) + } else { + (255, 0, 0) + } + } else { + (0, 0, 0) + } + ) + ) + ) + ); + + let opening_port = ViewPort::new(); + let opening = VecBuffer::::with_data("]".chars().collect(), opening_port.inner()); + + let dec_label_port = ViewPort::new(); + let dec_label = VecBuffer::::with_data("d0".chars().collect(), dec_label_port.inner()); + + let hex_label_port = ViewPort::new(); + let hex_label = VecBuffer::::with_data("x0".chars().collect(), hex_label_port.inner()); + + let delim_port = ViewPort::new(); + let delim = VecBuffer::::with_data(" ,".chars().collect(), delim_port.inner()); + + let closing_port = ViewPort::new(); + let closing = VecBuffer::::with_data("[".chars().collect(), closing_port.inner()); + for c in arg1_vec { + ed.insert(c); + ed.prev(); + } + + { + let tree_port = ViewPort::new(); + let mut tree = VecBuffer::with_data( + vec![ + opening_port.outer() + .to_sequence() + .map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((170, 170, 30)))), + + arg1_dec_mint_port + .map(|val| char::from_digit(*val as u32, 16).unwrap()) + .map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((255, 255, 255)))), + + dec_label_port.outer() + .to_sequence() + .map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((170, 170, 170)))), + + delim_port.outer() + .to_sequence() + .map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((170, 170, 30)))), + + arg1_hex_unic_port.clone() + .map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((255, 255, 255)))), + + hex_label_port.outer() + .to_sequence() + .map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((170, 170, 170)))), + + closing_port.outer() + .to_sequence() + .map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((170, 170, 30)))), + ], + tree_port.inner() + ); + + compositor.write().unwrap().push( + tree_port.outer() + .to_sequence() + .flatten() + .to_index() + .map_key( + |idx| Point2::new(40 - *idx as i16, 2 as i16), + |pt| if pt.y == 2 { Some(40 - pt.x as usize) } else { None } + ) + ); + } + + compositor.write().unwrap().push( + arg1_hex_unic_port + .to_index() + .map_key( + |idx| Point2::new(40 - *idx as i16, 3 as i16), + |pt| if pt.y == 3 { Some(40 - pt.x as usize) } else { None } + ) + .map_item( + |_idx, digit| TerminalAtom::from(digit) + ) + ); + + let magic_vec_port = ViewPort::new(); + let _magic_vec = VecBuffer::with_data("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>".chars().collect::>(), magic_vec_port.inner()); + + compositor.write().unwrap().push( + magic_vec_port.outer() + .to_sequence() + .to_index() + .map_item( + |idx, c| TerminalAtom::new( + *c, + TerminalStyle::fg_color((5, ((80+(idx*30)%100) as u8), (55+(idx*15)%180) as u8)) + ) + ) + .map_key( + |idx| Point2::new(*idx as i16, 4), + |pt| if pt.y == 4 { Some(pt.x as usize) } else { None } + ) + ); + + compositor.write().unwrap().push( + magic_vec_port.outer() + .to_sequence() + .to_index() + .map_item( + |idx, c| TerminalAtom::new( + *c, + TerminalStyle::fg_color((5, ((80+(idx*30)%100) as u8), (55+(idx*15)%180) as u8)) + ) + ) + .map_key( + |idx| Point2::new(*idx as i16, 0), + |pt| if pt.y == 0 { Some(pt.x as usize) } else { None } + ) + ); + + term_port.update(); + + loop { + match term.next_event().await { + TerminalEvent::Input(Event::Key(Key::Left)) => ed.next(), + TerminalEvent::Input(Event::Key(Key::Right)) => ed.prev(), + TerminalEvent::Input(Event::Key(Key::Home)) => ed.goto_end(), + TerminalEvent::Input(Event::Key(Key::End)) => ed.goto(0), + TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {}, + TerminalEvent::Input(Event::Key(Key::Char(c))) => { ed.insert(c); ed.prev() }, + TerminalEvent::Input(Event::Key(Key::Delete)) => ed.delete_prev(), + TerminalEvent::Input(Event::Key(Key::Backspace)) => ed.delete(), + TerminalEvent::Input(Event::Key(Key::Ctrl('c'))) => break, + _ => {} + } + term_port.update(); + } + + drop(term); + } + ); + + term_writer.show().await.expect("output error!"); +} +