From c68a9f785d3c42b3f86029f402e4163bd505c4ec Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Fri, 24 Sep 2021 23:31:09 +0200 Subject: [PATCH] shell: use a ListEditor of ProcessLaunchers in top level --- nested/src/list/editor.rs | 2 +- nested/src/terminal/ansi_parser.rs | 6 +- shell/src/ascii_box.rs | 132 ++++++++++++++++++++ shell/src/box.rs | 131 ++++++++++++++++++++ shell/src/main.rs | 189 +++++++---------------------- shell/src/process.rs | 89 ++++++++++---- shell/src/pty.rs | 7 +- 7 files changed, 378 insertions(+), 178 deletions(-) create mode 100644 shell/src/ascii_box.rs create mode 100644 shell/src/box.rs diff --git a/nested/src/list/editor.rs b/nested/src/list/editor.rs index 6113454..e3a48cd 100644 --- a/nested/src/list/editor.rs +++ b/nested/src/list/editor.rs @@ -699,7 +699,7 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, self.cursor_port.outer() } - fn get_item(&self) -> Option>> { + pub fn get_item(&self) -> Option>> { if let Some(idx) = self.cursor.get().idx { Some(self.data.get(idx)) } else { diff --git a/nested/src/terminal/ansi_parser.rs b/nested/src/terminal/ansi_parser.rs index aadfb44..4ae37ef 100644 --- a/nested/src/terminal/ansi_parser.rs +++ b/nested/src/terminal/ansi_parser.rs @@ -53,7 +53,7 @@ pub fn read_ansi_from(ansi_reader: &mut R, port: InnerViewPort< } }, Err(err) => { - println!("err: {}", err); + //println!("err: {}", err); break; }, } @@ -138,10 +138,12 @@ impl Perform for PerfAtom { } fn csi_dispatch(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) { + /* eprintln!( "[csi_dispatch] params={:#?}, intermediates={:?}, ignore={:?}, char={:?}", params, intermediates, ignore, c ); + */ let mut piter = params.into_iter(); @@ -213,7 +215,7 @@ impl Perform for PerfAtom { if let Some(y) = piter.next() { self.cursor.y = y[0] as i16 - 1 }; if let Some(x) = piter.next() { self.cursor.x = x[0] as i16 - 1 }; - eprintln!("cursor at {:?}", self.cursor); + //eprintln!("cursor at {:?}", self.cursor); }, 'A' => { self.cursor.y -= piter.next().unwrap()[0] as i16; } diff --git a/shell/src/ascii_box.rs b/shell/src/ascii_box.rs new file mode 100644 index 0000000..11b20c4 --- /dev/null +++ b/shell/src/ascii_box.rs @@ -0,0 +1,132 @@ + +use{ + std::sync::{Arc, RwLock}, + cgmath::{Point2, Vector2}, + nested::{ + core::{ + View, + ViewPort, + InnerViewPort, + OuterViewPort, + Observer, + ObserverExt, + ObserverBroadcast, + context::{ReprTree, Object, MorphismType, MorphismMode, Context}, + port::{UpdateTask}}, + index::{IndexView}, + grid::{GridWindowIterator}, + terminal::{ + Terminal, + TerminalStyle, + TerminalAtom, + TerminalCompositor, + TerminalEvent, + make_label, + TerminalView, + TerminalEditor}, + } +}; + +pub struct AsciiBox { + content: Option>, + extent: Vector2, + + cast: Arc>> +} + +impl AsciiBox { + pub fn new( + extent: Vector2, + content_port: OuterViewPort, + output_port: InnerViewPort + ) -> Arc> { + let ascii_box = Arc::new(RwLock::new(AsciiBox { + content: None, + extent, + cast: output_port.get_broadcast() + })); + + output_port.0.update_hooks.write().unwrap().push(Arc::new(content_port.0.clone())); + output_port.set_view(Some(ascii_box.clone())); + content_port.add_observer(ascii_box.clone()); + + ascii_box + } + + pub fn resize(&mut self, new_extent: Vector2) { + if self.extent != new_extent { + let old_extent = self.extent; + self.extent = new_extent; + self.notify_each(GridWindowIterator::from(Point2::new(0, 0) .. Point2::new(2+std::cmp::max(old_extent.x, new_extent.x), 2+std::cmp::max(old_extent.y, new_extent.y)))); + } + } + + pub fn fit_content(&mut self) { + if let Some(c) = self.content.as_ref() { + let p = c.range().end; + self.resize(Vector2::new(p.x, p.y)); + } else { + self.resize(Vector2::new(0, 0)); + } + } +} + +impl Observer for AsciiBox { + fn reset(&mut self, new_content: Option>) { + self.content = new_content; + self.notify_each(GridWindowIterator::from(Point2::new(0, 0) .. Point2::new(self.extent.x+2, self.extent.y+2))); + } + + fn notify(&mut self, pt: &Point2) { + self.cast.notify(&(pt + Vector2::new(1, 1))); + self.fit_content(); + } +} + +impl View for AsciiBox { + type Msg = Point2; +} + +impl IndexView> for AsciiBox { + type Item = TerminalAtom; + + fn get(&self, pt: &Point2) -> Option { + if pt.x == 0 || pt.x == self.extent.x+1 { + // vertical line + if pt.y == 0 && pt.x == 0 { + Some(TerminalAtom::from('╭')) + } else if pt.y == 0 && pt.x == self.extent.x+1 { + Some(TerminalAtom::from('╮')) + } else if pt.y > 0 && pt.y < self.extent.y+1 { + Some(TerminalAtom::from('│')) + } else if pt.y == self.extent.y+1 && pt.x == 0 { + Some(TerminalAtom::from('╰')) + } else if pt.y == self.extent.y+1 && pt.x == self.extent.x+1 { + Some(TerminalAtom::from('╯')) + } else { + None + } + } else if pt.y == 0 || pt.y == self.extent.y+1 { + // horizontal line + if pt.x > 0 && pt.x < self.extent.x+1 { + Some(TerminalAtom::from('─')) + } else { + None + } + } else if + pt.x < self.extent.x+1 && + pt.y < self.extent.y+1 + { + self.content.get(&(pt - Vector2::new(1, 1))) + } else { + None + } + } + + fn area(&self) -> Option>> { + Some(GridWindowIterator::from( + Point2::new(0, 0) .. Point2::new(self.extent.x+2, self.extent.y+2) + ).collect()) + } + +} diff --git a/shell/src/box.rs b/shell/src/box.rs new file mode 100644 index 0000000..5d895f4 --- /dev/null +++ b/shell/src/box.rs @@ -0,0 +1,131 @@ + +use{ + std::sync::{Arc, RwLock}, + cgmath::{Point2, Vector2}, + nested::{ + core::{ + View, + ViewPort, + InnerViewPort, + OuterViewPort, + Observer, + ObserverExt, + ObserverBroadcast, + context::{ReprTree, Object, MorphismType, MorphismMode, Context}, + port::{UpdateTask}}, + index::{IndexView}, + grid::{GridWindowIterator}, + terminal::{ + Terminal, + TerminalStyle, + TerminalAtom, + TerminalCompositor, + TerminalEvent, + make_label, + TerminalView, + TerminalEditor}, + } +}; + +pub struct AsciiBox { + content: Option>, + extent: Vector2, + + cast: Arc>> +} + +impl AsciiBox { + pub fn new( + extent: Vector2, + content_port: OuterViewPort, + output_port: InnerViewPort + ) -> Arc> { + let ascii_box = Arc::new(RwLock::new(AsciiBox { + content: None, + extent, + cast: output_port.get_broadcast() + })); + + output_port.0.update_hooks.write().unwrap().push(Arc::new(content_port.0.clone())); + output_port.set_view(Some(ascii_box.clone())); + content_port.add_observer(ascii_box.clone()); + + ascii_box + } + + pub fn resize(&mut self, new_extent: Vector2) { + if self.extent != new_extent { + let old_extent = self.extent; + self.extent = new_extent; + self.notify_each(GridWindowIterator::from(Point2::new(0, 0) .. Point2::new(2+std::cmp::max(old_extent.x, new_extent.x), 2+std::cmp::max(old_extent.y, new_extent.y)))); + } + } + + pub fn fit_content(&mut self) { + if let Some(c) = self.content.as_ref() { + let p = c.range().end; + self.resize(Vector2::new(p.x, p.y)); + } else { + self.resize(Vector2::new(0, 0)); + } + } +} + +impl Observer for AsciiBox { + fn reset(&mut self, new_content: Option>) { + self.content = new_content; + self.notify_each(GridWindowIterator::from(Point2::new(0, 0) .. Point2::new(self.extent.x+2, self.extent.y+2))); + } + + fn notify(&mut self, pt: &Point2) { + self.cast.notify(&(pt + Vector2::new(1, 1))); + } +} + +impl View for AsciiBox { + type Msg = Point2; +} + +impl IndexView> for AsciiBox { + type Item = TerminalAtom; + + fn get(&self, pt: &Point2) -> Option { + if pt.x == 0 || pt.x == self.extent.x+1 { + // vertical line + if pt.y == 0 && pt.x == 0 { + Some(TerminalAtom::from('╭')) + } else if pt.y == 0 && pt.x == self.extent.x+1 { + Some(TerminalAtom::from('╮')) + } else if pt.y > 0 && pt.y < self.extent.y+1 { + Some(TerminalAtom::from('│')) + } else if pt.y == self.extent.y+1 && pt.x == 0 { + Some(TerminalAtom::from('╰')) + } else if pt.y == self.extent.y+1 && pt.x == self.extent.x+1 { + Some(TerminalAtom::from('╯')) + } else { + None + } + } else if pt.y == 0 || pt.y == self.extent.y+1 { + // horizontal line + if pt.x > 0 && pt.x < self.extent.x+1 { + Some(TerminalAtom::from('─')) + } else { + None + } + } else if + pt.x < self.extent.x+1 && + pt.y < self.extent.y+1 + { + self.content.get(&(pt - Vector2::new(1, 1))) + } else { + None + } + } + + fn area(&self) -> Option>> { + Some(GridWindowIterator::from( + Point2::new(0, 0) .. Point2::new(self.extent.x+2, self.extent.y+2) + ).collect()) + } + +} diff --git a/shell/src/main.rs b/shell/src/main.rs index 7df39da..79bc16d 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -4,6 +4,7 @@ extern crate portable_pty; mod monstera; mod process; mod pty; +mod ascii_box; use{ std::sync::{Arc, RwLock}, @@ -43,109 +44,6 @@ use{ } }; - -struct AsciiBox { - content: Option>, - extent: Vector2, - - cast: Arc>> -} - -impl AsciiBox { - pub fn new( - extent: Vector2, - content_port: OuterViewPort, - output_port: InnerViewPort - ) -> Arc> { - let ascii_box = Arc::new(RwLock::new(AsciiBox { - content: None, - extent, - cast: output_port.get_broadcast() - })); - - output_port.0.update_hooks.write().unwrap().push(Arc::new(content_port.0.clone())); - output_port.set_view(Some(ascii_box.clone())); - content_port.add_observer(ascii_box.clone()); - - ascii_box - } - - pub fn resize(&mut self, new_extent: Vector2) { - if self.extent != new_extent { - let old_extent = self.extent; - self.extent = new_extent; - self.notify_each(GridWindowIterator::from(Point2::new(0, 0) .. Point2::new(2+std::cmp::max(old_extent.x, new_extent.x), 2+std::cmp::max(old_extent.y, new_extent.y)))); - } - } - - pub fn fit_content(&mut self) { - if let Some(c) = self.content.as_ref() { - let p = c.range().end; - self.resize(Vector2::new(p.x, p.y)); - } else { - self.resize(Vector2::new(0, 0)); - } - } -} - -impl Observer for AsciiBox { - fn reset(&mut self, new_content: Option>) { - self.content = new_content; - self.notify_each(GridWindowIterator::from(Point2::new(0, 0) .. Point2::new(self.extent.x+2, self.extent.y+2))); - } - - fn notify(&mut self, pt: &Point2) { - self.cast.notify(&(pt + Vector2::new(1, 1))); - } -} - -impl View for AsciiBox { - type Msg = Point2; -} - -impl IndexView> for AsciiBox { - type Item = TerminalAtom; - - fn get(&self, pt: &Point2) -> Option { - if pt.x == 0 || pt.x == self.extent.x+1 { - // vertical line - if pt.y == 0 && pt.x == 0 { - Some(TerminalAtom::from('╭')) - } else if pt.y == 0 && pt.x == self.extent.x+1 { - Some(TerminalAtom::from('╮')) - } else if pt.y > 0 && pt.y < self.extent.y+1 { - Some(TerminalAtom::from('│')) - } else if pt.y == self.extent.y+1 && pt.x == 0 { - Some(TerminalAtom::from('╰')) - } else if pt.y == self.extent.y+1 && pt.x == self.extent.x+1 { - Some(TerminalAtom::from('╯')) - } else { - None - } - } else if pt.y == 0 || pt.y == self.extent.y+1 { - // horizontal line - if pt.x > 0 && pt.x < self.extent.x+1 { - Some(TerminalAtom::from('─')) - } else { - None - } - } else if - pt.x < self.extent.x+1 && - pt.y < self.extent.y+1 - { - self.content.get(&(pt - Vector2::new(1, 1))) - } else { - None - } - } - - fn area(&self) -> Option>> { - Some(GridWindowIterator::from( - Point2::new(0, 0) .. Point2::new(self.extent.x+2, self.extent.y+2) - ).collect()) - } -} - #[async_std::main] async fn main() { let term_port = ViewPort::new(); @@ -177,55 +75,51 @@ async fn main() { let status_chars_port = ViewPort::new(); let mut status_chars = VecBuffer::new(status_chars_port.inner()); + let mut process_list_editor = ListEditor::new( + Box::new(|| { + Arc::new(RwLock::new( + ProcessLauncher::new() + )) + }), + ListEditorStyle::VerticalSexpr + ); + table_buf.insert_iter(vec![ (Point2::new(0, 0), magic.clone()), (Point2::new(0, 1), status_chars_port.outer().to_sequence().to_grid_horizontal()), (Point2::new(0, 2), magic.clone()), + (Point2::new(0, 3), process_list_editor.get_term_view()) ]); compositor.write().unwrap().push(monstera::make_monstera()); compositor.write().unwrap().push(table_port.outer().flatten().offset(Vector2::new(40, 2))); - let mut y = 4; - - let mut process_launcher = ProcessLauncher::new(); - table_buf.insert(Point2::new(0, y), process_launcher.get_term_view()); - - process_launcher.goto(TreeCursor { + process_list_editor.goto(TreeCursor { leaf_mode: ListCursorMode::Insert, tree_addr: vec![ 0 ] }); - let mut pty : Option = None; - let mut ptybox : Option>> = None; - loop { term_port.update(); + /* if let Some(p) = pty.as_mut() { if p.get_status() { if let Some(ptybox) = ptybox.take() { ptybox.write().unwrap().fit_content(); } pty = None; - - process_launcher = ProcessLauncher::new(); - process_launcher.goto(TreeCursor { - leaf_mode: ListCursorMode::Insert, - tree_addr: vec![ 0 ] - }); - - y += 1; - table_buf.insert(Point2::new(0, y), process_launcher.get_term_view()); + process_list_editor.up(); } } +*/ term_port.update(); let ev = term.next_event().await; - +/* if let Some(pty) = pty.as_mut() { pty.handle_terminal_event(&ev); } else { - +*/ match ev { TerminalEvent::Resize(new_size) => { cur_size.set(new_size); @@ -240,32 +134,32 @@ async fn main() { TerminalEvent::Input(Event::Key(Key::Ctrl('d'))) => break, TerminalEvent::Input(Event::Key(Key::Left)) => { - process_launcher.pxev(); + process_list_editor.pxev(); } TerminalEvent::Input(Event::Key(Key::Right)) => { - process_launcher.nexd(); + process_list_editor.nexd(); } TerminalEvent::Input(Event::Key(Key::Up)) => { - if process_launcher.up() == TreeNavResult::Exit { - //process_launcher.dn(); - //process_launcher.goto_home(); + if process_list_editor.up() == TreeNavResult::Exit { + process_list_editor.dn(); + process_list_editor.goto_home(); } } TerminalEvent::Input(Event::Key(Key::Down)) => { - if process_launcher.dn() == TreeNavResult::Continue { - process_launcher.goto_home(); + if process_list_editor.dn() == TreeNavResult::Continue { + process_list_editor.goto_home(); } } TerminalEvent::Input(Event::Key(Key::Home)) => { - process_launcher.goto_home(); + process_list_editor.goto_home(); } TerminalEvent::Input(Event::Key(Key::End)) => { - process_launcher.goto_end(); + process_list_editor.goto_end(); } TerminalEvent::Input(Event::Key(Key::Char('\n'))) => { - let mut output_port = ViewPort::new(); - pty = process_launcher.launch_pty(output_port.inner()); - + //let mut output_port = ViewPort::new(); + process_list_editor.get_item().unwrap().write().unwrap().launch_pty2(); +/* let box_port = ViewPort::new(); let test_box = AsciiBox::new( Vector2::new(80, 25), @@ -278,36 +172,35 @@ async fn main() { table_buf.remove(Point2::new(0, y-1)); - let mut p = box_port.outer().map_item(|_idx, x| x.add_style_back(TerminalStyle::fg_color((90, 120, 100)))) - .offset(Vector2::new(0, -1)); + let mut p = box_port.outer().map_item(|_idx, x| x.add_style_back(TerminalStyle::fg_color((90, 120, 100))) .offset(Vector2::new(0, -1)); table_port.update_hooks.write().unwrap().push(Arc::new(p.clone().0)); y += 1; table_buf.insert(Point2::new(0, y), p.clone()); +*/ } ev => { - if process_launcher.get_cursor().leaf_mode == ListCursorMode::Select { + if process_list_editor.get_cursor().leaf_mode == ListCursorMode::Select { match ev { - TerminalEvent::Input(Event::Key(Key::Char('l'))) => { process_launcher.up(); }, - TerminalEvent::Input(Event::Key(Key::Char('a'))) => { process_launcher.dn(); }, - TerminalEvent::Input(Event::Key(Key::Char('i'))) => { process_launcher.pxev(); }, - TerminalEvent::Input(Event::Key(Key::Char('e'))) => { process_launcher.nexd(); }, - TerminalEvent::Input(Event::Key(Key::Char('u'))) => { process_launcher.goto_home(); }, - TerminalEvent::Input(Event::Key(Key::Char('o'))) => { process_launcher.goto_end(); }, + TerminalEvent::Input(Event::Key(Key::Char('l'))) => { process_list_editor.up(); }, + TerminalEvent::Input(Event::Key(Key::Char('a'))) => { process_list_editor.dn(); }, + TerminalEvent::Input(Event::Key(Key::Char('i'))) => { process_list_editor.pxev(); }, + TerminalEvent::Input(Event::Key(Key::Char('e'))) => { process_list_editor.nexd(); }, + TerminalEvent::Input(Event::Key(Key::Char('u'))) => { process_list_editor.goto_home(); }, + TerminalEvent::Input(Event::Key(Key::Char('o'))) => { process_list_editor.goto_end(); }, _ => { - process_launcher.handle_terminal_event(&ev); + process_list_editor.handle_terminal_event(&ev); } } } else { - process_launcher.handle_terminal_event(&ev); + process_list_editor.handle_terminal_event(&ev); } } } - } status_chars.clear(); - let cur = process_launcher.get_cursor(); + let cur = process_list_editor.get_cursor(); if cur.tree_addr.len() > 0 { status_chars.push(TerminalAtom::new('@', TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true)))); diff --git a/shell/src/process.rs b/shell/src/process.rs index dd8148c..0bb63fc 100644 --- a/shell/src/process.rs +++ b/shell/src/process.rs @@ -8,7 +8,7 @@ use { termion::event::{Key, Event}, cgmath::Point2, nested::{ - core::{OuterViewPort, InnerViewPort, Observer}, + core::{ViewPort, OuterViewPort, InnerViewPort, Observer}, singleton::{SingletonView, SingletonBuffer}, sequence::{SequenceView, SequenceViewExt}, index::buffer::IndexBuffer, @@ -69,14 +69,26 @@ impl TreeNav for ProcessArg { } pub struct ProcessLauncher { - editor: ListEditor< ProcessArg, - Box Arc> + Send + Sync + 'static> > + cmd_editor: ListEditor< + ProcessArg, Box Arc> + Send + Sync + 'static> + >, + pty: Option, + ptybox: Arc>, + + pty_port: ViewPort, + + comp_port: ViewPort, + compositor: Arc> } impl ProcessLauncher { pub fn new() -> Self { - ProcessLauncher { - editor: ListEditor::new( + let pty_port = ViewPort::new(); + let comp_port = ViewPort::new(); + let box_port = ViewPort::::new(); + let compositor = nested::terminal::TerminalCompositor::new(comp_port.inner()); + + let cmd_editor = ListEditor::new( Box::new( || { Arc::new(RwLock::new(ProcessArg { @@ -89,19 +101,52 @@ impl ProcessLauncher { ListEditorStyle::Plain) })) } - ), + ) as Box:: Arc> + Send + Sync>, ListEditorStyle::Plain - ) + ); + + compositor.write().unwrap().push( + box_port.outer() + .map_item(|_idx, x| x.add_style_back(TerminalStyle::fg_color((90, 120, 100)))) + ); + compositor.write().unwrap().push( + cmd_editor + .get_seg_seq_view() + .decorate("$(", ")", " ", 0) + .to_grid_horizontal() + .flatten() + ); + + ProcessLauncher { + cmd_editor, + pty: None, + ptybox: crate::ascii_box::AsciiBox::new( + cgmath::Vector2::new(80, 25), + pty_port.outer() + .map_item(|_,a:&TerminalAtom| a.add_style_back(TerminalStyle::fg_color((230, 230, 230)))), + box_port.inner() + ), + pty_port, + comp_port, + compositor } } + pub fn launch_pty2(&mut self) { + self.launch_pty(self.pty_port.inner()); + //self.ptybox.write().unwrap().fit_content(); + + //let mut p = + //table_port.update_hooks.write().unwrap().push(Arc::new(p.clone().0)); + } + pub fn launch_pty(&mut self, port: InnerViewPort) -> Option { self.up(); self.up(); let mut strings = Vec::new(); - let v = self.editor.get_data_port().get_view().unwrap(); + let v = self.cmd_editor.get_data_port().get_view().unwrap(); for i in 0 .. v.len().unwrap_or(0) { let arg_view = v.get(&i).unwrap().read().unwrap().get_data_port().get_view().unwrap(); strings.push(arg_view.iter().collect::()); @@ -121,35 +166,31 @@ impl ProcessLauncher { impl TerminalEditor for ProcessLauncher { fn get_term_view(&self) -> OuterViewPort { - self.editor - .get_seg_seq_view() - .decorate("$(", ")", " ", 0) - .to_grid_horizontal() - .flatten() + self.comp_port.outer() } fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { match event { TerminalEvent::Input(Event::Key(Key::Char('\n'))) => { // launch command - self.editor.up(); - self.editor.up(); + self.cmd_editor.up(); + self.cmd_editor.up(); TerminalEditorResult::Exit } - event => self.editor.handle_terminal_event(event) + event => self.cmd_editor.handle_terminal_event(event) } } } impl TreeNav for ProcessLauncher { - fn get_cursor(&self) -> TreeCursor { self.editor.get_cursor() } - fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { self.editor.goto(cur) } - fn goto_home(&mut self) -> TreeNavResult { self.editor.goto_home() } - fn goto_end(&mut self) -> TreeNavResult { self.editor.goto_end() } - fn pxev(&mut self) -> TreeNavResult { self.editor.pxev() } - fn nexd(&mut self) -> TreeNavResult { self.editor.nexd() } - fn up(&mut self) -> TreeNavResult { self.editor.up() } - fn dn(&mut self) -> TreeNavResult { self.editor.dn() } + fn get_cursor(&self) -> TreeCursor { self.cmd_editor.get_cursor() } + fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { self.cmd_editor.goto(cur) } + fn goto_home(&mut self) -> TreeNavResult { self.cmd_editor.goto_home() } + fn goto_end(&mut self) -> TreeNavResult { self.cmd_editor.goto_end() } + fn pxev(&mut self) -> TreeNavResult { self.cmd_editor.pxev() } + fn nexd(&mut self) -> TreeNavResult { self.cmd_editor.nexd() } + fn up(&mut self) -> TreeNavResult { self.cmd_editor.up() } + fn dn(&mut self) -> TreeNavResult { self.cmd_editor.dn() } } diff --git a/shell/src/pty.rs b/shell/src/pty.rs index 74a5f67..4a11c7b 100644 --- a/shell/src/pty.rs +++ b/shell/src/pty.rs @@ -1,6 +1,7 @@ use { termion::event::{Key, Event}, + std::sync::Mutex, nested::{ core::{InnerViewPort}, terminal::{TerminalView, TerminalEvent} @@ -12,7 +13,7 @@ pub use portable_pty::CommandBuilder; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> pub struct PTY { - master: Box, + master: Mutex>, child: Box } @@ -45,7 +46,7 @@ impl PTY { }); Some(PTY { - master: pair.master, + master: Mutex::new(pair.master), child }) } else { @@ -64,7 +65,7 @@ impl PTY { pub fn handle_terminal_event(&mut self, event: &TerminalEvent) { match event { TerminalEvent::Input(Event::Key(Key::Char(c))) => { - write!(self.master, "{}", c); + write!(self.master.lock().unwrap(), "{}", c); } _ => { }