From f196726dab128a2034f1a3b29fbc7cb908dd1c75 Mon Sep 17 00:00:00 2001 From: Doron Tsur Date: Wed, 30 Dec 2020 10:54:31 +0200 Subject: [PATCH 1/2] fix(infra): make panes BTreeMap value Pane trait in preparation for the status bar (#124) --- src/boundaries.rs | 15 +- src/main.rs | 239 +++++++------ src/tab.rs | 354 ++++++++++-------- src/terminal_pane/terminal_pane.rs | 557 +++++++++++++++++++++++------ 4 files changed, 799 insertions(+), 366 deletions(-) diff --git a/src/boundaries.rs b/src/boundaries.rs index 875c6b295..6d5eb3bca 100644 --- a/src/boundaries.rs +++ b/src/boundaries.rs @@ -1,3 +1,4 @@ +use crate::tab::Pane; use std::collections::HashMap; pub mod boundary_type { @@ -371,7 +372,7 @@ impl Boundaries { boundary_characters: HashMap::new(), } } - pub fn add_rect(&mut self, rect: &R) { + pub fn add_rect(&mut self, rect: &Box) { if self.rect_right_boundary_is_before_screen_edge(rect) { // let boundary_x_coords = self.rect_right_boundary_x_coords(rect); let boundary_x_coords = rect.right_boundary_x_coords(); @@ -428,20 +429,20 @@ impl Boundaries { } vte_output } - fn rect_right_boundary_is_before_screen_edge(&self, rect: &R) -> bool { + fn rect_right_boundary_is_before_screen_edge(&self, rect: &Box) -> bool { rect.x() + rect.columns() < self.columns } - fn rect_bottom_boundary_is_before_screen_edge(&self, rect: &R) -> bool { + fn rect_bottom_boundary_is_before_screen_edge(&self, rect: &Box) -> bool { rect.y() + rect.rows() < self.rows } - fn rect_right_boundary_row_start(&self, rect: &R) -> usize { + fn rect_right_boundary_row_start(&self, rect: &Box) -> usize { if rect.y() == 0 { 0 } else { rect.y() - 1 } } - fn rect_right_boundary_row_end(&self, rect: &R) -> usize { + fn rect_right_boundary_row_end(&self, rect: &Box) -> usize { let rect_bottom_row = rect.y() + rect.rows(); // we do this because unless we're on the screen edge, we'd like to go one extra row to // connect to whatever boundary is beneath us @@ -451,14 +452,14 @@ impl Boundaries { rect_bottom_row + 1 } } - fn rect_bottom_boundary_col_start(&self, rect: &R) -> usize { + fn rect_bottom_boundary_col_start(&self, rect: &Box) -> usize { if rect.x() == 0 { 0 } else { rect.x() - 1 } } - fn rect_bottom_boundary_col_end(&self, rect: &R) -> usize { + fn rect_bottom_boundary_col_end(&self, rect: &Box) -> usize { let rect_right_col = rect.x() + rect.columns(); // we do this because unless we're on the screen edge, we'd like to go one extra column to // connect to whatever boundary is right of us diff --git a/src/main.rs b/src/main.rs index 82ce1a758..c59fe1c4f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -163,14 +163,7 @@ pub fn start(mut os_input: Box, opts: Opt) { ) = sync_channel(0); let send_app_instructions = SenderWithContext::new(err_ctx, SenderType::SyncSender(send_app_instructions)); - let mut screen = Screen::new( - receive_screen_instructions, - send_pty_instructions.clone(), - send_app_instructions.clone(), - &full_screen_ws, - os_input.clone(), - opts.max_panes, - ); + let mut pty_bus = PtyBus::new( receive_pty_instructions, send_screen_instructions.clone(), @@ -193,6 +186,7 @@ pub fn start(mut os_input: Box, opts: Opt) { .name("pty".to_string()) .spawn({ let mut command_is_executing = command_is_executing.clone(); + move || { if let Some(layout) = maybe_layout { pty_bus.spawn_terminals_for_layout(layout); @@ -263,113 +257,128 @@ pub fn start(mut os_input: Box, opts: Opt) { .name("screen".to_string()) .spawn({ let mut command_is_executing = command_is_executing.clone(); - move || loop { - let (event, mut err_ctx) = screen - .receiver - .recv() - .expect("failed to receive event on channel"); - err_ctx.add_call(ContextType::Screen(ScreenContext::from(&event))); - screen.send_app_instructions.update(err_ctx); - screen.send_pty_instructions.update(err_ctx); - match event { - ScreenInstruction::Pty(pid, vte_event) => { - screen - .get_active_tab_mut() - .unwrap() - .handle_pty_event(pid, vte_event); - } - ScreenInstruction::Render => { - screen.render(); - } - ScreenInstruction::NewPane(pid) => { - screen.get_active_tab_mut().unwrap().new_pane(pid); - command_is_executing.done_opening_new_pane(); - } - ScreenInstruction::HorizontalSplit(pid) => { - screen.get_active_tab_mut().unwrap().horizontal_split(pid); - command_is_executing.done_opening_new_pane(); - } - ScreenInstruction::VerticalSplit(pid) => { - screen.get_active_tab_mut().unwrap().vertical_split(pid); - command_is_executing.done_opening_new_pane(); - } - ScreenInstruction::WriteCharacter(bytes) => { - screen - .get_active_tab_mut() - .unwrap() - .write_to_active_terminal(bytes); - } - ScreenInstruction::ResizeLeft => { - screen.get_active_tab_mut().unwrap().resize_left(); - } - ScreenInstruction::ResizeRight => { - screen.get_active_tab_mut().unwrap().resize_right(); - } - ScreenInstruction::ResizeDown => { - screen.get_active_tab_mut().unwrap().resize_down(); - } - ScreenInstruction::ResizeUp => { - screen.get_active_tab_mut().unwrap().resize_up(); - } - ScreenInstruction::MoveFocus => { - screen.get_active_tab_mut().unwrap().move_focus(); - } - ScreenInstruction::MoveFocusLeft => { - screen.get_active_tab_mut().unwrap().move_focus_left(); - } - ScreenInstruction::MoveFocusDown => { - screen.get_active_tab_mut().unwrap().move_focus_down(); - } - ScreenInstruction::MoveFocusRight => { - screen.get_active_tab_mut().unwrap().move_focus_right(); - } - ScreenInstruction::MoveFocusUp => { - screen.get_active_tab_mut().unwrap().move_focus_up(); - } - ScreenInstruction::ScrollUp => { - screen - .get_active_tab_mut() - .unwrap() - .scroll_active_terminal_up(); - } - ScreenInstruction::ScrollDown => { - screen - .get_active_tab_mut() - .unwrap() - .scroll_active_terminal_down(); - } - ScreenInstruction::ClearScroll => { - screen - .get_active_tab_mut() - .unwrap() - .clear_active_terminal_scroll(); - } - ScreenInstruction::CloseFocusedPane => { - screen.get_active_tab_mut().unwrap().close_focused_pane(); - screen.render(); - } - ScreenInstruction::ClosePane(id) => { - screen.get_active_tab_mut().unwrap().close_pane(id); - screen.render(); - } - ScreenInstruction::ToggleActiveTerminalFullscreen => { - screen - .get_active_tab_mut() - .unwrap() - .toggle_active_terminal_fullscreen(); - } - ScreenInstruction::NewTab(pane_id) => { - screen.new_tab(pane_id); - command_is_executing.done_opening_new_pane(); - } - ScreenInstruction::SwitchTabNext => screen.switch_tab_next(), - ScreenInstruction::SwitchTabPrev => screen.switch_tab_prev(), - ScreenInstruction::CloseTab => screen.close_tab(), - ScreenInstruction::ApplyLayout((layout, new_pane_pids)) => { - screen.apply_layout(layout, new_pane_pids) - } - ScreenInstruction::Quit => { - break; + let os_input = os_input.clone(); + let send_pty_instructions = send_pty_instructions.clone(); + let send_app_instructions = send_app_instructions.clone(); + let max_panes = opts.max_panes; + + move || { + let mut screen = Screen::new( + receive_screen_instructions, + send_pty_instructions, + send_app_instructions, + &full_screen_ws, + os_input, + max_panes, + ); + loop { + let (event, mut err_ctx) = screen + .receiver + .recv() + .expect("failed to receive event on channel"); + err_ctx.add_call(ContextType::Screen(ScreenContext::from(&event))); + screen.send_app_instructions.update(err_ctx); + screen.send_pty_instructions.update(err_ctx); + match event { + ScreenInstruction::Pty(pid, vte_event) => { + screen + .get_active_tab_mut() + .unwrap() + .handle_pty_event(pid, vte_event); + } + ScreenInstruction::Render => { + screen.render(); + } + ScreenInstruction::NewPane(pid) => { + screen.get_active_tab_mut().unwrap().new_pane(pid); + command_is_executing.done_opening_new_pane(); + } + ScreenInstruction::HorizontalSplit(pid) => { + screen.get_active_tab_mut().unwrap().horizontal_split(pid); + command_is_executing.done_opening_new_pane(); + } + ScreenInstruction::VerticalSplit(pid) => { + screen.get_active_tab_mut().unwrap().vertical_split(pid); + command_is_executing.done_opening_new_pane(); + } + ScreenInstruction::WriteCharacter(bytes) => { + screen + .get_active_tab_mut() + .unwrap() + .write_to_active_terminal(bytes); + } + ScreenInstruction::ResizeLeft => { + screen.get_active_tab_mut().unwrap().resize_left(); + } + ScreenInstruction::ResizeRight => { + screen.get_active_tab_mut().unwrap().resize_right(); + } + ScreenInstruction::ResizeDown => { + screen.get_active_tab_mut().unwrap().resize_down(); + } + ScreenInstruction::ResizeUp => { + screen.get_active_tab_mut().unwrap().resize_up(); + } + ScreenInstruction::MoveFocus => { + screen.get_active_tab_mut().unwrap().move_focus(); + } + ScreenInstruction::MoveFocusLeft => { + screen.get_active_tab_mut().unwrap().move_focus_left(); + } + ScreenInstruction::MoveFocusDown => { + screen.get_active_tab_mut().unwrap().move_focus_down(); + } + ScreenInstruction::MoveFocusRight => { + screen.get_active_tab_mut().unwrap().move_focus_right(); + } + ScreenInstruction::MoveFocusUp => { + screen.get_active_tab_mut().unwrap().move_focus_up(); + } + ScreenInstruction::ScrollUp => { + screen + .get_active_tab_mut() + .unwrap() + .scroll_active_terminal_up(); + } + ScreenInstruction::ScrollDown => { + screen + .get_active_tab_mut() + .unwrap() + .scroll_active_terminal_down(); + } + ScreenInstruction::ClearScroll => { + screen + .get_active_tab_mut() + .unwrap() + .clear_active_terminal_scroll(); + } + ScreenInstruction::CloseFocusedPane => { + screen.get_active_tab_mut().unwrap().close_focused_pane(); + screen.render(); + } + ScreenInstruction::ClosePane(id) => { + screen.get_active_tab_mut().unwrap().close_pane(id); + screen.render(); + } + ScreenInstruction::ToggleActiveTerminalFullscreen => { + screen + .get_active_tab_mut() + .unwrap() + .toggle_active_terminal_fullscreen(); + } + ScreenInstruction::NewTab(pane_id) => { + screen.new_tab(pane_id); + command_is_executing.done_opening_new_pane(); + } + ScreenInstruction::SwitchTabNext => screen.switch_tab_next(), + ScreenInstruction::SwitchTabPrev => screen.switch_tab_prev(), + ScreenInstruction::CloseTab => screen.close_tab(), + ScreenInstruction::ApplyLayout((layout, new_pane_pids)) => { + screen.apply_layout(layout, new_pane_pids) + } + ScreenInstruction::Quit => { + break; + } } } } diff --git a/src/tab.rs b/src/tab.rs index 2032cca4b..e647c8d72 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -3,7 +3,6 @@ use std::io::Write; use std::os::unix::io::RawFd; use crate::boundaries::Boundaries; -use crate::boundaries::Rect; use crate::layout::Layout; use crate::os_input_output::OsApi; use crate::pty_bus::{PtyInstruction, VteEvent}; @@ -56,7 +55,7 @@ enum PaneKind { } pub struct Tab { pub index: usize, - panes: BTreeMap, + panes: BTreeMap>, panes_to_hide: HashSet, active_terminal: Option, max_panes: Option, @@ -67,6 +66,82 @@ pub struct Tab { pub send_app_instructions: SenderWithContext, } +pub trait Pane { + fn x(&self) -> usize; + fn y(&self) -> usize; + fn rows(&self) -> usize; + fn columns(&self) -> usize; + fn reset_size_and_position_override(&mut self); + fn change_size_p(&mut self, position_and_size: &PositionAndSize); + fn get_rows(&self) -> usize; + fn get_columns(&self) -> usize; + fn change_size(&mut self, ws: &PositionAndSize); + fn override_size_and_position(&mut self, x: usize, y: usize, size: &PositionAndSize); + fn handle_event(&mut self, event: VteEvent); + fn cursor_coordinates(&self) -> Option<(usize, usize)>; + fn adjust_input_to_terminal(&self, input_bytes: Vec) -> Vec; + + fn position_and_size_override(&self) -> Option; + fn should_render(&self) -> bool; + fn set_should_render(&mut self, should_render: bool); + fn buffer_as_vte_output(&mut self) -> Option; + fn pid(&self) -> RawFd; + fn reduce_height_down(&mut self, count: usize); + fn increase_height_down(&mut self, count: usize); + fn increase_height_up(&mut self, count: usize); + fn reduce_height_up(&mut self, count: usize); + fn increase_width_right(&mut self, count: usize); + fn reduce_width_right(&mut self, count: usize); + fn reduce_width_left(&mut self, count: usize); + fn increase_width_left(&mut self, count: usize); + fn scroll_up(&mut self, count: usize); + fn scroll_down(&mut self, count: usize); + fn clear_scroll(&mut self); + + fn right_boundary_x_coords(&self) -> usize { + self.x() + self.columns() + } + fn bottom_boundary_y_coords(&self) -> usize { + self.y() + self.rows() + } + fn is_directly_right_of(&self, other: &Box) -> bool { + self.x() == other.x() + other.columns() + 1 + } + fn is_directly_left_of(&self, other: &Box) -> bool { + self.x() + self.columns() + 1 == other.x() + } + fn is_directly_below(&self, other: &Box) -> bool { + self.y() == other.y() + other.rows() + 1 + } + fn is_directly_above(&self, other: &Box) -> bool { + self.y() + self.rows() + 1 == other.y() + } + fn horizontally_overlaps_with(&self, other: &Box) -> bool { + (self.y() >= other.y() && self.y() <= (other.y() + other.rows())) + || ((self.y() + self.rows()) <= (other.y() + other.rows()) + && (self.y() + self.rows()) > other.y()) + || (self.y() <= other.y() && (self.y() + self.rows() >= (other.y() + other.rows()))) + || (other.y() <= self.y() && (other.y() + other.rows() >= (self.y() + self.rows()))) + } + fn get_horizontal_overlap_with(&self, other: &Box) -> usize { + std::cmp::min(self.y() + self.rows(), other.y() + other.rows()) + - std::cmp::max(self.y(), other.y()) + } + fn vertically_overlaps_with(&self, other: &Box) -> bool { + (self.x() >= other.x() && self.x() <= (other.x() + other.columns())) + || ((self.x() + self.columns()) <= (other.x() + other.columns()) + && (self.x() + self.columns()) > other.x()) + || (self.x() <= other.x() + && (self.x() + self.columns() >= (other.x() + other.columns()))) + || (other.x() <= self.x() + && (other.x() + other.columns() >= (self.x() + self.columns()))) + } + fn get_vertical_overlap_with(&self, other: &Box) -> usize { + std::cmp::min(self.x() + self.columns(), other.x() + other.columns()) + - std::cmp::max(self.x(), other.x()) + } +} + impl Tab { pub fn new( index: usize, @@ -84,8 +159,8 @@ impl Tab { new_terminal.get_columns() as u16, new_terminal.get_rows() as u16, ); - let mut panes = BTreeMap::new(); - panes.insert(PaneKind::Terminal(pid), new_terminal); + let mut panes: BTreeMap> = BTreeMap::new(); + panes.insert(PaneKind::Terminal(pid), Box::new(new_terminal)); panes } else { BTreeMap::new() @@ -152,7 +227,8 @@ impl Tab { new_terminal.get_columns() as u16, new_terminal.get_rows() as u16, ); - self.panes.insert(PaneKind::Terminal(*pid), new_terminal); + self.panes + .insert(PaneKind::Terminal(*pid), Box::new(new_terminal)); } for unused_pid in new_pids { // this is a bit of a hack and happens because we don't have any central location that @@ -186,7 +262,8 @@ impl Tab { new_terminal.get_columns() as u16, new_terminal.get_rows() as u16, ); - self.panes.insert(PaneKind::Terminal(pid), new_terminal); + self.panes + .insert(PaneKind::Terminal(pid), Box::new(new_terminal)); self.active_terminal = Some(pid); } else { // TODO: check minimum size of active terminal @@ -211,8 +288,8 @@ impl Tab { let terminal_ws = PositionAndSize { rows: terminal_to_split.get_rows(), columns: terminal_to_split.get_columns(), - x: terminal_to_split.get_x(), - y: terminal_to_split.get_y(), + x: terminal_to_split.x(), + y: terminal_to_split.y(), }; if terminal_to_split.get_rows() * CURSOR_HEIGHT_WIDTH_RATIO > terminal_to_split.get_columns() @@ -227,7 +304,8 @@ impl Tab { bottom_winsize.rows as u16, ); terminal_to_split.change_size(&top_winsize); - self.panes.insert(PaneKind::Terminal(pid), new_terminal); + self.panes + .insert(PaneKind::Terminal(pid), Box::new(new_terminal)); self.os_api.set_terminal_size_using_fd( terminal_id_to_split, top_winsize.columns as u16, @@ -245,7 +323,8 @@ impl Tab { right_winsize.rows as u16, ); terminal_to_split.change_size(&left_winszie); - self.panes.insert(PaneKind::Terminal(pid), new_terminal); + self.panes + .insert(PaneKind::Terminal(pid), Box::new(new_terminal)); self.os_api.set_terminal_size_using_fd( terminal_id_to_split, left_winszie.columns as u16, @@ -270,7 +349,8 @@ impl Tab { new_terminal.get_columns() as u16, new_terminal.get_rows() as u16, ); - self.panes.insert(PaneKind::Terminal(pid), new_terminal); + self.panes + .insert(PaneKind::Terminal(pid), Box::new(new_terminal)); self.active_terminal = Some(pid); } else { // TODO: check minimum size of active terminal @@ -283,8 +363,8 @@ impl Tab { x: 0, y: 0, }, - active_terminal.get_x(), - active_terminal.get_y(), + active_terminal.x(), + active_terminal.y(), ) }; let (top_winsize, bottom_winsize) = split_horizontally_with_gap(&active_terminal_ws); @@ -306,7 +386,8 @@ impl Tab { active_terminal.change_size(&top_winsize); } - self.panes.insert(PaneKind::Terminal(pid), new_terminal); + self.panes + .insert(PaneKind::Terminal(pid), Box::new(new_terminal)); let active_terminal_pid = self.get_active_terminal_id().unwrap(); self.os_api.set_terminal_size_using_fd( active_terminal_pid, @@ -331,7 +412,8 @@ impl Tab { new_terminal.get_columns() as u16, new_terminal.get_rows() as u16, ); - self.panes.insert(PaneKind::Terminal(pid), new_terminal); + self.panes + .insert(PaneKind::Terminal(pid), Box::new(new_terminal)); self.active_terminal = Some(pid); } else { // TODO: check minimum size of active terminal @@ -344,8 +426,8 @@ impl Tab { x: 0, y: 0, }, - active_terminal.get_x(), - active_terminal.get_y(), + active_terminal.x(), + active_terminal.y(), ) }; let (left_winszie, right_winsize) = split_vertically_with_gap(&active_terminal_ws); @@ -367,7 +449,8 @@ impl Tab { active_terminal.change_size(&left_winszie); } - self.panes.insert(PaneKind::Terminal(pid), new_terminal); + self.panes + .insert(PaneKind::Terminal(pid), Box::new(new_terminal)); let active_terminal_pid = self.get_active_terminal_id().unwrap(); self.os_api.set_terminal_size_using_fd( active_terminal_pid, @@ -378,22 +461,14 @@ impl Tab { self.render(); } } - pub fn get_active_terminal(&self) -> Option<&TerminalPane> { + pub fn get_active_terminal(&self) -> Option<&Box> { match self.active_terminal { Some(active_terminal) => self.panes.get(&PaneKind::Terminal(active_terminal)), None => None, } } fn get_active_terminal_id(&self) -> Option { - match self.active_terminal { - Some(active_terminal) => Some( - self.panes - .get(&PaneKind::Terminal(active_terminal)) - .unwrap() - .pid, - ), - None => None, - } + self.active_terminal } pub fn handle_pty_event(&mut self, pid: RawFd, event: VteEvent) { // if we don't have the terminal in self.terminals it's probably because @@ -423,8 +498,8 @@ impl Tab { active_terminal .cursor_coordinates() .map(|(x_in_terminal, y_in_terminal)| { - let x = active_terminal.get_x() + x_in_terminal; - let y = active_terminal.get_y() + y_in_terminal; + let x = active_terminal.x() + x_in_terminal; + let y = active_terminal.y() + y_in_terminal; (x, y) }) } @@ -433,14 +508,14 @@ impl Tab { if self .get_active_terminal() .unwrap() - .position_and_size_override + .position_and_size_override() .is_some() { for terminal_id in self.panes_to_hide.iter() { self.panes .get_mut(&PaneKind::Terminal(*terminal_id)) .unwrap() - .should_render = true; + .set_should_render(true); } self.panes_to_hide.clear(); let active_terminal = self @@ -540,7 +615,7 @@ impl Tab { } } } - fn get_terminals(&self) -> impl Iterator { + fn get_terminals(&self) -> impl Iterator)> { self.panes .iter() .filter_map(|(pane_kind, terminal_pane)| match pane_kind { @@ -555,11 +630,11 @@ impl Tab { fn terminal_ids_directly_left_of(&self, id: &RawFd) -> Option> { let mut ids = vec![]; let terminal_to_check = self.panes.get(&PaneKind::Terminal(*id)).unwrap(); - if terminal_to_check.get_x() == 0 { + if terminal_to_check.x() == 0 { return None; } for (pid, terminal) in self.get_terminals() { - if terminal.get_x() + terminal.get_columns() == terminal_to_check.get_x() - 1 { + if terminal.x() + terminal.get_columns() == terminal_to_check.x() - 1 { ids.push(pid); } } @@ -573,7 +648,7 @@ impl Tab { let mut ids = vec![]; let terminal_to_check = self.panes.get(&PaneKind::Terminal(*id)).unwrap(); for (pid, terminal) in self.get_terminals() { - if terminal.get_x() == terminal_to_check.get_x() + terminal_to_check.get_columns() + 1 { + if terminal.x() == terminal_to_check.x() + terminal_to_check.get_columns() + 1 { ids.push(pid); } } @@ -587,7 +662,7 @@ impl Tab { let mut ids = vec![]; let terminal_to_check = self.panes.get(&PaneKind::Terminal(*id)).unwrap(); for (pid, terminal) in self.get_terminals() { - if terminal.get_y() == terminal_to_check.get_y() + terminal_to_check.get_rows() + 1 { + if terminal.y() == terminal_to_check.y() + terminal_to_check.get_rows() + 1 { ids.push(pid); } } @@ -601,7 +676,7 @@ impl Tab { let mut ids = vec![]; let terminal_to_check = self.panes.get(&PaneKind::Terminal(*id)).unwrap(); for (pid, terminal) in self.get_terminals() { - if terminal.get_y() + terminal.get_rows() + 1 == terminal_to_check.get_y() { + if terminal.y() + terminal.get_rows() + 1 == terminal_to_check.y() { ids.push(pid); } } @@ -611,39 +686,38 @@ impl Tab { Some(ids) } } - fn panes_top_aligned_with_pane(&self, pane: &TerminalPane) -> Vec<&TerminalPane> { + fn panes_top_aligned_with_pane(&self, pane: &Box) -> Vec<&Box> { self.panes .keys() .map(|t_id| self.panes.get(&t_id).unwrap()) - .filter(|terminal| terminal.pid != pane.pid && terminal.get_y() == pane.get_y()) + .filter(|terminal| terminal.pid() != pane.pid() && terminal.y() == pane.y()) .collect() } - fn panes_bottom_aligned_with_pane(&self, pane: &TerminalPane) -> Vec<&TerminalPane> { + fn panes_bottom_aligned_with_pane(&self, pane: &Box) -> Vec<&Box> { self.panes .keys() .map(|t_id| self.panes.get(&t_id).unwrap()) .filter(|terminal| { - terminal.pid != pane.pid - && terminal.get_y() + terminal.get_rows() == pane.get_y() + pane.get_rows() + terminal.pid() != pane.pid() + && terminal.y() + terminal.get_rows() == pane.y() + pane.get_rows() }) .collect() } - fn panes_right_aligned_with_pane(&self, pane: &TerminalPane) -> Vec<&TerminalPane> { + fn panes_right_aligned_with_pane(&self, pane: &Box) -> Vec<&Box> { self.panes .keys() .map(|t_id| self.panes.get(&t_id).unwrap()) .filter(|terminal| { - terminal.pid != pane.pid - && terminal.get_x() + terminal.get_columns() - == pane.get_x() + pane.get_columns() + terminal.pid() != pane.pid() + && terminal.x() + terminal.get_columns() == pane.x() + pane.get_columns() }) .collect() } - fn panes_left_aligned_with_pane(&self, pane: &TerminalPane) -> Vec<&TerminalPane> { + fn panes_left_aligned_with_pane(&self, pane: &&Box) -> Vec<&Box> { self.panes .keys() .map(|t_id| self.panes.get(&t_id).unwrap()) - .filter(|terminal| terminal.pid != pane.pid && terminal.get_x() == pane.get_x()) + .filter(|terminal| terminal.pid() != pane.pid() && terminal.x() == pane.x()) .collect() } fn right_aligned_contiguous_panes_above( @@ -658,17 +732,17 @@ impl Tab { .expect("terminal id does not exist"); let mut right_aligned_terminals = self.panes_right_aligned_with_pane(&terminal_to_check); // terminals that are next to each other up to current - right_aligned_terminals.sort_by(|a, b| b.get_y().cmp(&a.get_y())); + right_aligned_terminals.sort_by(|a, b| b.y().cmp(&a.y())); for terminal in right_aligned_terminals { let terminal_to_check = terminals.last().unwrap_or(&terminal_to_check); - if terminal.get_y() + terminal.get_rows() + 1 == terminal_to_check.get_y() { + if terminal.y() + terminal.get_rows() + 1 == terminal_to_check.y() { terminals.push(terminal); } } // top-most border aligned with a pane border to the right let mut top_resize_border = 0; for terminal in &terminals { - let bottom_terminal_boundary = terminal.get_y() + terminal.get_rows(); + let bottom_terminal_boundary = terminal.y() + terminal.get_rows(); if terminal_borders_to_the_right .get(&(bottom_terminal_boundary + 1)) .is_some() @@ -677,15 +751,15 @@ impl Tab { top_resize_border = bottom_terminal_boundary + 1; } } - terminals.retain(|terminal| terminal.get_y() >= top_resize_border); + terminals.retain(|terminal| terminal.y() >= top_resize_border); // if there are no adjacent panes to resize, we use the border of the main pane we're // resizing let top_resize_border = if terminals.is_empty() { - terminal_to_check.get_y() + terminal_to_check.y() } else { top_resize_border }; - let terminal_ids: Vec = terminals.iter().map(|t| t.pid).collect(); + let terminal_ids: Vec = terminals.iter().map(|t| t.pid()).collect(); (top_resize_border, terminal_ids) } fn right_aligned_contiguous_panes_below( @@ -700,17 +774,17 @@ impl Tab { .expect("terminal id does not exist"); let mut right_aligned_terminals = self.panes_right_aligned_with_pane(&terminal_to_check); // terminals that are next to each other up to current - right_aligned_terminals.sort_by(|a, b| a.get_y().cmp(&b.get_y())); + right_aligned_terminals.sort_by(|a, b| a.y().cmp(&b.y())); for terminal in right_aligned_terminals { let terminal_to_check = terminals.last().unwrap_or(&terminal_to_check); - if terminal.get_y() == terminal_to_check.get_y() + terminal_to_check.get_rows() + 1 { + if terminal.y() == terminal_to_check.y() + terminal_to_check.get_rows() + 1 { terminals.push(terminal); } } // bottom-most border aligned with a pane border to the right let mut bottom_resize_border = self.full_screen_ws.rows; for terminal in &terminals { - let top_terminal_boundary = terminal.get_y(); + let top_terminal_boundary = terminal.y(); if terminal_borders_to_the_right .get(&(top_terminal_boundary)) .is_some() @@ -719,15 +793,15 @@ impl Tab { bottom_resize_border = top_terminal_boundary; } } - terminals.retain(|terminal| terminal.get_y() + terminal.get_rows() <= bottom_resize_border); + terminals.retain(|terminal| terminal.y() + terminal.get_rows() <= bottom_resize_border); // if there are no adjacent panes to resize, we use the border of the main pane we're // resizing let bottom_resize_border = if terminals.is_empty() { - terminal_to_check.get_y() + terminal_to_check.get_rows() + terminal_to_check.y() + terminal_to_check.get_rows() } else { bottom_resize_border }; - let terminal_ids: Vec = terminals.iter().map(|t| t.pid).collect(); + let terminal_ids: Vec = terminals.iter().map(|t| t.pid()).collect(); (bottom_resize_border, terminal_ids) } fn left_aligned_contiguous_panes_above( @@ -742,17 +816,17 @@ impl Tab { .expect("terminal id does not exist"); let mut left_aligned_terminals = self.panes_left_aligned_with_pane(&terminal_to_check); // terminals that are next to each other up to current - left_aligned_terminals.sort_by(|a, b| b.get_y().cmp(&a.get_y())); + left_aligned_terminals.sort_by(|a, b| b.y().cmp(&a.y())); for terminal in left_aligned_terminals { let terminal_to_check = terminals.last().unwrap_or(&terminal_to_check); - if terminal.get_y() + terminal.get_rows() + 1 == terminal_to_check.get_y() { + if terminal.y() + terminal.get_rows() + 1 == terminal_to_check.y() { terminals.push(terminal); } } // top-most border aligned with a pane border to the right let mut top_resize_border = 0; for terminal in &terminals { - let bottom_terminal_boundary = terminal.get_y() + terminal.get_rows(); + let bottom_terminal_boundary = terminal.y() + terminal.get_rows(); if terminal_borders_to_the_left .get(&(bottom_terminal_boundary + 1)) .is_some() @@ -761,15 +835,15 @@ impl Tab { top_resize_border = bottom_terminal_boundary + 1; } } - terminals.retain(|terminal| terminal.get_y() >= top_resize_border); + terminals.retain(|terminal| terminal.y() >= top_resize_border); // if there are no adjacent panes to resize, we use the border of the main pane we're // resizing let top_resize_border = if terminals.is_empty() { - terminal_to_check.get_y() + terminal_to_check.y() } else { top_resize_border }; - let terminal_ids: Vec = terminals.iter().map(|t| t.pid).collect(); + let terminal_ids: Vec = terminals.iter().map(|t| t.pid()).collect(); (top_resize_border, terminal_ids) } fn left_aligned_contiguous_panes_below( @@ -784,17 +858,17 @@ impl Tab { .expect("terminal id does not exist"); let mut left_aligned_terminals = self.panes_left_aligned_with_pane(&terminal_to_check); // terminals that are next to each other up to current - left_aligned_terminals.sort_by(|a, b| a.get_y().cmp(&b.get_y())); + left_aligned_terminals.sort_by(|a, b| a.y().cmp(&b.y())); for terminal in left_aligned_terminals { let terminal_to_check = terminals.last().unwrap_or(&terminal_to_check); - if terminal.get_y() == terminal_to_check.get_y() + terminal_to_check.get_rows() + 1 { + if terminal.y() == terminal_to_check.y() + terminal_to_check.get_rows() + 1 { terminals.push(terminal); } } // bottom-most border aligned with a pane border to the left let mut bottom_resize_border = self.full_screen_ws.rows; for terminal in &terminals { - let top_terminal_boundary = terminal.get_y(); + let top_terminal_boundary = terminal.y(); if terminal_borders_to_the_left .get(&(top_terminal_boundary)) .is_some() @@ -804,17 +878,17 @@ impl Tab { } } terminals.retain(|terminal| { - // terminal.get_y() + terminal.get_rows() < bottom_resize_border - terminal.get_y() + terminal.get_rows() <= bottom_resize_border + // terminal.y() + terminal.get_rows() < bottom_resize_border + terminal.y() + terminal.get_rows() <= bottom_resize_border }); // if there are no adjacent panes to resize, we use the border of the main pane we're // resizing let bottom_resize_border = if terminals.is_empty() { - terminal_to_check.get_y() + terminal_to_check.get_rows() + terminal_to_check.y() + terminal_to_check.get_rows() } else { bottom_resize_border }; - let terminal_ids: Vec = terminals.iter().map(|t| t.pid).collect(); + let terminal_ids: Vec = terminals.iter().map(|t| t.pid()).collect(); (bottom_resize_border, terminal_ids) } fn top_aligned_contiguous_panes_to_the_left( @@ -829,17 +903,17 @@ impl Tab { .expect("terminal id does not exist"); let mut top_aligned_terminals = self.panes_top_aligned_with_pane(&terminal_to_check); // terminals that are next to each other up to current - top_aligned_terminals.sort_by(|a, b| b.get_x().cmp(&a.get_x())); + top_aligned_terminals.sort_by(|a, b| b.x().cmp(&a.x())); for terminal in top_aligned_terminals { let terminal_to_check = terminals.last().unwrap_or(&terminal_to_check); - if terminal.get_x() + terminal.get_columns() + 1 == terminal_to_check.get_x() { + if terminal.x() + terminal.get_columns() + 1 == terminal_to_check.x() { terminals.push(terminal); } } // leftmost border aligned with a pane border above let mut left_resize_border = 0; for terminal in &terminals { - let right_terminal_boundary = terminal.get_x() + terminal.get_columns(); + let right_terminal_boundary = terminal.x() + terminal.get_columns(); if terminal_borders_above .get(&(right_terminal_boundary + 1)) .is_some() @@ -848,15 +922,15 @@ impl Tab { left_resize_border = right_terminal_boundary + 1; } } - terminals.retain(|terminal| terminal.get_x() >= left_resize_border); + terminals.retain(|terminal| terminal.x() >= left_resize_border); // if there are no adjacent panes to resize, we use the border of the main pane we're // resizing let left_resize_border = if terminals.is_empty() { - terminal_to_check.get_x() + terminal_to_check.x() } else { left_resize_border }; - let terminal_ids: Vec = terminals.iter().map(|t| t.pid).collect(); + let terminal_ids: Vec = terminals.iter().map(|t| t.pid()).collect(); (left_resize_border, terminal_ids) } fn top_aligned_contiguous_panes_to_the_right( @@ -868,17 +942,17 @@ impl Tab { let terminal_to_check = self.panes.get(&PaneKind::Terminal(*id)).unwrap(); let mut top_aligned_terminals = self.panes_top_aligned_with_pane(&terminal_to_check); // terminals that are next to each other up to current - top_aligned_terminals.sort_by(|a, b| a.get_x().cmp(&b.get_x())); + top_aligned_terminals.sort_by(|a, b| a.x().cmp(&b.x())); for terminal in top_aligned_terminals { let terminal_to_check = terminals.last().unwrap_or(&terminal_to_check); - if terminal.get_x() == terminal_to_check.get_x() + terminal_to_check.get_columns() + 1 { + if terminal.x() == terminal_to_check.x() + terminal_to_check.get_columns() + 1 { terminals.push(terminal); } } // rightmost border aligned with a pane border above let mut right_resize_border = self.full_screen_ws.columns; for terminal in &terminals { - let left_terminal_boundary = terminal.get_x(); + let left_terminal_boundary = terminal.x(); if terminal_borders_above .get(&left_terminal_boundary) .is_some() @@ -887,16 +961,15 @@ impl Tab { right_resize_border = left_terminal_boundary; } } - terminals - .retain(|terminal| terminal.get_x() + terminal.get_columns() <= right_resize_border); + terminals.retain(|terminal| terminal.x() + terminal.get_columns() <= right_resize_border); // if there are no adjacent panes to resize, we use the border of the main pane we're // resizing let right_resize_border = if terminals.is_empty() { - terminal_to_check.get_x() + terminal_to_check.get_columns() + terminal_to_check.x() + terminal_to_check.get_columns() } else { right_resize_border }; - let terminal_ids: Vec = terminals.iter().map(|t| t.pid).collect(); + let terminal_ids: Vec = terminals.iter().map(|t| t.pid()).collect(); (right_resize_border, terminal_ids) } fn bottom_aligned_contiguous_panes_to_the_left( @@ -907,18 +980,18 @@ impl Tab { let mut terminals = vec![]; let terminal_to_check = self.panes.get(&PaneKind::Terminal(*id)).unwrap(); let mut bottom_aligned_terminals = self.panes_bottom_aligned_with_pane(&terminal_to_check); - bottom_aligned_terminals.sort_by(|a, b| b.get_x().cmp(&a.get_x())); + bottom_aligned_terminals.sort_by(|a, b| b.x().cmp(&a.x())); // terminals that are next to each other up to current for terminal in bottom_aligned_terminals { let terminal_to_check = terminals.last().unwrap_or(&terminal_to_check); - if terminal.get_x() + terminal.get_columns() + 1 == terminal_to_check.get_x() { + if terminal.x() + terminal.get_columns() + 1 == terminal_to_check.x() { terminals.push(terminal); } } // leftmost border aligned with a pane border above let mut left_resize_border = 0; for terminal in &terminals { - let right_terminal_boundary = terminal.get_x() + terminal.get_columns(); + let right_terminal_boundary = terminal.x() + terminal.get_columns(); if terminal_borders_below .get(&(right_terminal_boundary + 1)) .is_some() @@ -927,15 +1000,15 @@ impl Tab { left_resize_border = right_terminal_boundary + 1; } } - terminals.retain(|terminal| terminal.get_x() >= left_resize_border); + terminals.retain(|terminal| terminal.x() >= left_resize_border); // if there are no adjacent panes to resize, we use the border of the main pane we're // resizing let left_resize_border = if terminals.is_empty() { - terminal_to_check.get_x() + terminal_to_check.x() } else { left_resize_border }; - let terminal_ids: Vec = terminals.iter().map(|t| t.pid).collect(); + let terminal_ids: Vec = terminals.iter().map(|t| t.pid()).collect(); (left_resize_border, terminal_ids) } fn bottom_aligned_contiguous_panes_to_the_right( @@ -946,18 +1019,18 @@ impl Tab { let mut terminals = vec![]; let terminal_to_check = self.panes.get(&PaneKind::Terminal(*id)).unwrap(); let mut bottom_aligned_terminals = self.panes_bottom_aligned_with_pane(&terminal_to_check); - bottom_aligned_terminals.sort_by(|a, b| a.get_x().cmp(&b.get_x())); + bottom_aligned_terminals.sort_by(|a, b| a.x().cmp(&b.x())); // terminals that are next to each other up to current for terminal in bottom_aligned_terminals { let terminal_to_check = terminals.last().unwrap_or(&terminal_to_check); - if terminal.get_x() == terminal_to_check.get_x() + terminal_to_check.get_columns() + 1 { + if terminal.x() == terminal_to_check.x() + terminal_to_check.get_columns() + 1 { terminals.push(terminal); } } // leftmost border aligned with a pane border above let mut right_resize_border = self.full_screen_ws.columns; for terminal in &terminals { - let left_terminal_boundary = terminal.get_x(); + let left_terminal_boundary = terminal.x(); if terminal_borders_below .get(&left_terminal_boundary) .is_some() @@ -966,14 +1039,13 @@ impl Tab { right_resize_border = left_terminal_boundary; } } - terminals - .retain(|terminal| terminal.get_x() + terminal.get_columns() <= right_resize_border); + terminals.retain(|terminal| terminal.x() + terminal.get_columns() <= right_resize_border); let right_resize_border = if terminals.is_empty() { - terminal_to_check.get_x() + terminal_to_check.get_columns() + terminal_to_check.x() + terminal_to_check.get_columns() } else { right_resize_border }; - let terminal_ids: Vec = terminals.iter().map(|t| t.pid).collect(); + let terminal_ids: Vec = terminals.iter().map(|t| t.pid()).collect(); (right_resize_border, terminal_ids) } fn reduce_pane_height_down(&mut self, id: &RawFd, count: usize) { @@ -998,7 +1070,7 @@ impl Tab { let terminal = self.panes.get_mut(&PaneKind::Terminal(*id)).unwrap(); terminal.increase_height_down(count); self.os_api.set_terminal_size_using_fd( - terminal.pid, + terminal.pid(), terminal.get_columns() as u16, terminal.get_rows() as u16, ); @@ -1007,7 +1079,7 @@ impl Tab { let terminal = self.panes.get_mut(&PaneKind::Terminal(*id)).unwrap(); terminal.increase_height_up(count); self.os_api.set_terminal_size_using_fd( - terminal.pid, + terminal.pid(), terminal.get_columns() as u16, terminal.get_rows() as u16, ); @@ -1016,7 +1088,7 @@ impl Tab { let terminal = self.panes.get_mut(&PaneKind::Terminal(*id)).unwrap(); terminal.increase_width_right(count); self.os_api.set_terminal_size_using_fd( - terminal.pid, + terminal.pid(), terminal.get_columns() as u16, terminal.get_rows() as u16, ); @@ -1025,7 +1097,7 @@ impl Tab { let terminal = self.panes.get_mut(&PaneKind::Terminal(*id)).unwrap(); terminal.increase_width_left(count); self.os_api.set_terminal_size_using_fd( - terminal.pid, + terminal.pid(), terminal.get_columns() as u16, terminal.get_rows() as u16, ); @@ -1034,7 +1106,7 @@ impl Tab { let terminal = self.panes.get_mut(&PaneKind::Terminal(*id)).unwrap(); terminal.reduce_width_right(count); self.os_api.set_terminal_size_using_fd( - terminal.pid, + terminal.pid(), terminal.get_columns() as u16, terminal.get_rows() as u16, ); @@ -1043,7 +1115,7 @@ impl Tab { let terminal = self.panes.get_mut(&PaneKind::Terminal(*id)).unwrap(); terminal.reduce_width_left(count); self.os_api.set_terminal_size_using_fd( - terminal.pid, + terminal.pid(), terminal.get_columns() as u16, terminal.get_rows() as u16, ); @@ -1058,8 +1130,7 @@ impl Tab { .panes .get(&PaneKind::Terminal(*id)) .expect("could not find terminal to check between borders"); - terminal.get_x() >= left_border_x - && terminal.get_x() + terminal.get_columns() <= right_border_x + terminal.x() >= left_border_x && terminal.x() + terminal.get_columns() <= right_border_x } fn pane_is_between_horizontal_borders( &self, @@ -1071,8 +1142,7 @@ impl Tab { .panes .get(&PaneKind::Terminal(*id)) .expect("could not find terminal to check between borders"); - terminal.get_y() >= top_border_y - && terminal.get_y() + terminal.get_rows() <= bottom_border_y + terminal.y() >= top_border_y && terminal.y() + terminal.get_rows() <= bottom_border_y } fn reduce_pane_and_surroundings_up(&mut self, id: &RawFd, count: usize) { let mut terminals_below = self @@ -1080,7 +1150,7 @@ impl Tab { .expect("can't reduce pane size up if there are no terminals below"); let terminal_borders_below: HashSet = terminals_below .iter() - .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().get_x()) + .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().x()) .collect(); let (left_resize_border, terminals_to_the_left) = self.bottom_aligned_contiguous_panes_to_the_left(&id, &terminal_borders_below); @@ -1106,7 +1176,7 @@ impl Tab { .expect("can't reduce pane size down if there are no terminals above"); let terminal_borders_above: HashSet = terminals_above .iter() - .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().get_x()) + .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().x()) .collect(); let (left_resize_border, terminals_to_the_left) = self.top_aligned_contiguous_panes_to_the_left(&id, &terminal_borders_above); @@ -1132,7 +1202,7 @@ impl Tab { .expect("can't reduce pane size right if there are no terminals to the left"); let terminal_borders_to_the_left: HashSet = terminals_to_the_left .iter() - .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().get_y()) + .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().y()) .collect(); let (top_resize_border, terminals_above) = self.left_aligned_contiguous_panes_above(&id, &terminal_borders_to_the_left); @@ -1155,7 +1225,7 @@ impl Tab { .expect("can't reduce pane size left if there are no terminals to the right"); let terminal_borders_to_the_right: HashSet = terminals_to_the_right .iter() - .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().get_y()) + .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().y()) .collect(); let (top_resize_border, terminals_above) = self.right_aligned_contiguous_panes_above(&id, &terminal_borders_to_the_right); @@ -1178,7 +1248,7 @@ impl Tab { .expect("can't increase pane size up if there are no terminals above"); let terminal_borders_above: HashSet = terminals_above .iter() - .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().get_x()) + .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().x()) .collect(); let (left_resize_border, terminals_to_the_left) = self.top_aligned_contiguous_panes_to_the_left(&id, &terminal_borders_above); @@ -1204,7 +1274,7 @@ impl Tab { .expect("can't increase pane size down if there are no terminals below"); let terminal_borders_below: HashSet = terminals_below .iter() - .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().get_x()) + .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().x()) .collect(); let (left_resize_border, terminals_to_the_left) = self.bottom_aligned_contiguous_panes_to_the_left(&id, &terminal_borders_below); @@ -1230,7 +1300,7 @@ impl Tab { .expect("can't increase pane size right if there are no terminals to the right"); let terminal_borders_to_the_right: HashSet = terminals_to_the_right .iter() - .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().get_y()) + .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().y()) .collect(); let (top_resize_border, terminals_above) = self.right_aligned_contiguous_panes_above(&id, &terminal_borders_to_the_right); @@ -1253,7 +1323,7 @@ impl Tab { .expect("can't increase pane size right if there are no terminals to the right"); let terminal_borders_to_the_left: HashSet = terminals_to_the_left .iter() - .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().get_y()) + .map(|t| self.panes.get(&PaneKind::Terminal(*t)).unwrap().y()) .collect(); let (top_resize_border, terminals_above) = self.left_aligned_contiguous_panes_above(&id, &terminal_borders_to_the_left); @@ -1275,28 +1345,28 @@ impl Tab { .panes .get(&PaneKind::Terminal(*pane_id)) .expect("pane does not exist"); - pane.get_y() > 0 + pane.y() > 0 } fn panes_exist_below(&self, pane_id: &RawFd) -> bool { let pane = self .panes .get(&PaneKind::Terminal(*pane_id)) .expect("pane does not exist"); - pane.get_y() + pane.get_rows() < self.full_screen_ws.rows + pane.y() + pane.get_rows() < self.full_screen_ws.rows } fn panes_exist_to_the_right(&self, pane_id: &RawFd) -> bool { let pane = self .panes .get(&PaneKind::Terminal(*pane_id)) .expect("pane does not exist"); - pane.get_x() + pane.get_columns() < self.full_screen_ws.columns + pane.x() + pane.get_columns() < self.full_screen_ws.columns } fn panes_exist_to_the_left(&self, pane_id: &RawFd) -> bool { let pane = self .panes .get(&PaneKind::Terminal(*pane_id)) .expect("pane does not exist"); - pane.get_x() > 0 + pane.x() > 0 } pub fn resize_right(&mut self) { // TODO: find out by how much we actually reduced and only reduce by that much @@ -1392,11 +1462,11 @@ impl Tab { self.active_terminal = Some(p); } None => { - self.active_terminal = Some(active.pid); + self.active_terminal = Some(active.pid()); } } } else { - self.active_terminal = Some(active_terminal.unwrap().pid); + self.active_terminal = Some(active_terminal.unwrap().pid()); } self.render(); } @@ -1422,11 +1492,11 @@ impl Tab { self.active_terminal = Some(p); } None => { - self.active_terminal = Some(active.pid); + self.active_terminal = Some(active.pid()); } } } else { - self.active_terminal = Some(active_terminal.unwrap().pid); + self.active_terminal = Some(active_terminal.unwrap().pid()); } self.render(); } @@ -1452,11 +1522,11 @@ impl Tab { self.active_terminal = Some(p); } None => { - self.active_terminal = Some(active.pid); + self.active_terminal = Some(active.pid()); } } } else { - self.active_terminal = Some(active_terminal.unwrap().pid); + self.active_terminal = Some(active_terminal.unwrap().pid()); } self.render(); } @@ -1482,34 +1552,34 @@ impl Tab { self.active_terminal = Some(p); } None => { - self.active_terminal = Some(active.pid); + self.active_terminal = Some(active.pid()); } } } else { - self.active_terminal = Some(active_terminal.unwrap().pid); + self.active_terminal = Some(active_terminal.unwrap().pid()); } self.render(); } fn horizontal_borders(&self, terminals: &[RawFd]) -> HashSet { terminals.iter().fold(HashSet::new(), |mut borders, t| { let terminal = self.panes.get(&PaneKind::Terminal(*t)).unwrap(); - borders.insert(terminal.get_y()); - borders.insert(terminal.get_y() + terminal.get_rows() + 1); // 1 for the border width + borders.insert(terminal.y()); + borders.insert(terminal.y() + terminal.get_rows() + 1); // 1 for the border width borders }) } fn vertical_borders(&self, terminals: &[RawFd]) -> HashSet { terminals.iter().fold(HashSet::new(), |mut borders, t| { let terminal = self.panes.get(&PaneKind::Terminal(*t)).unwrap(); - borders.insert(terminal.get_x()); - borders.insert(terminal.get_x() + terminal.get_columns() + 1); // 1 for the border width + borders.insert(terminal.x()); + borders.insert(terminal.x() + terminal.get_columns() + 1); // 1 for the border width borders }) } fn terminals_to_the_left_between_aligning_borders(&self, id: RawFd) -> Option> { if let Some(terminal) = &self.panes.get(&PaneKind::Terminal(id)) { - let upper_close_border = terminal.get_y(); - let lower_close_border = terminal.get_y() + terminal.get_rows() + 1; + let upper_close_border = terminal.y(); + let lower_close_border = terminal.y() + terminal.get_rows() + 1; if let Some(mut terminals_to_the_left) = self.terminal_ids_directly_left_of(&id) { let terminal_borders_to_the_left = self.horizontal_borders(&terminals_to_the_left); @@ -1531,8 +1601,8 @@ impl Tab { } fn terminals_to_the_right_between_aligning_borders(&self, id: RawFd) -> Option> { if let Some(terminal) = &self.panes.get(&PaneKind::Terminal(id)) { - let upper_close_border = terminal.get_y(); - let lower_close_border = terminal.get_y() + terminal.get_rows() + 1; + let upper_close_border = terminal.y(); + let lower_close_border = terminal.y() + terminal.get_rows() + 1; if let Some(mut terminals_to_the_right) = self.terminal_ids_directly_right_of(&id) { let terminal_borders_to_the_right = @@ -1555,8 +1625,8 @@ impl Tab { } fn terminals_above_between_aligning_borders(&self, id: RawFd) -> Option> { if let Some(terminal) = &self.panes.get(&PaneKind::Terminal(id)) { - let left_close_border = terminal.get_x(); - let right_close_border = terminal.get_x() + terminal.get_columns() + 1; + let left_close_border = terminal.x(); + let right_close_border = terminal.x() + terminal.get_columns() + 1; if let Some(mut terminals_above) = self.terminal_ids_directly_above(&id) { let terminal_borders_above = self.vertical_borders(&terminals_above); @@ -1578,8 +1648,8 @@ impl Tab { } fn terminals_below_between_aligning_borders(&self, id: RawFd) -> Option> { if let Some(terminal) = &self.panes.get(&PaneKind::Terminal(id)) { - let left_close_border = terminal.get_x(); - let right_close_border = terminal.get_x() + terminal.get_columns() + 1; + let left_close_border = terminal.x(); + let right_close_border = terminal.x() + terminal.get_columns() + 1; if let Some(mut terminals_below) = self.terminal_ids_directly_below(&id) { let terminal_borders_below = self.vertical_borders(&terminals_below); diff --git a/src/terminal_pane/terminal_pane.rs b/src/terminal_pane/terminal_pane.rs index 0d5a108ba..ab96d6084 100644 --- a/src/terminal_pane/terminal_pane.rs +++ b/src/terminal_pane/terminal_pane.rs @@ -1,13 +1,11 @@ #![allow(clippy::clippy::if_same_then_else)] +use crate::tab::Pane; use ::nix::pty::Winsize; use ::std::os::unix::io::RawFd; use ::vte::Perform; -use crate::boundaries::Rect; -use crate::terminal_pane::terminal_character::{ - AnsiCode, CharacterStyles, NamedColor, TerminalCharacter, -}; +use crate::terminal_pane::terminal_character::{CharacterStyles, NamedColor, TerminalCharacter}; use crate::terminal_pane::Scroll; use crate::utils::logging::debug_log_to_file; use crate::VteEvent; @@ -42,7 +40,7 @@ pub struct TerminalPane { pending_styles: CharacterStyles, } -impl Rect for TerminalPane { +impl Pane for TerminalPane { fn x(&self) -> usize { self.get_x() } @@ -55,9 +53,234 @@ impl Rect for TerminalPane { fn columns(&self) -> usize { self.get_columns() } + fn reset_size_and_position_override(&mut self) { + self.position_and_size_override = None; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn change_size_p(&mut self, position_and_size: &PositionAndSize) { + self.position_and_size = *position_and_size; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn get_rows(&self) -> usize { + match &self.position_and_size_override.as_ref() { + Some(position_and_size_override) => position_and_size_override.rows, + None => self.position_and_size.rows as usize, + } + } + fn get_columns(&self) -> usize { + match &self.position_and_size_override.as_ref() { + Some(position_and_size_override) => position_and_size_override.columns, + None => self.position_and_size.columns as usize, + } + } + fn change_size(&mut self, ws: &PositionAndSize) { + self.position_and_size.columns = ws.columns; + self.position_and_size.rows = ws.rows; + self.reflow_lines(); + self.mark_for_rerender(); + } + + fn override_size_and_position(&mut self, x: usize, y: usize, size: &PositionAndSize) { + let position_and_size_override = PositionAndSize { + x, + y, + rows: size.rows, + columns: size.columns, + }; + self.position_and_size_override = Some(position_and_size_override); + self.reflow_lines(); + self.mark_for_rerender(); + } + fn handle_event(&mut self, event: VteEvent) { + match event { + VteEvent::Print(c) => { + self.print(c); + self.mark_for_rerender(); + } + VteEvent::Execute(byte) => { + self.execute(byte); + } + VteEvent::Hook(params, intermediates, ignore, c) => { + self.hook(¶ms, &intermediates, ignore, c); + } + VteEvent::Put(byte) => { + self.put(byte); + } + VteEvent::Unhook => { + self.unhook(); + } + VteEvent::OscDispatch(params, bell_terminated) => { + let params: Vec<&[u8]> = params.iter().map(|p| &p[..]).collect(); + self.osc_dispatch(¶ms[..], bell_terminated); + } + VteEvent::CsiDispatch(params, intermediates, ignore, c) => { + self.csi_dispatch(¶ms, &intermediates, ignore, c); + } + VteEvent::EscDispatch(intermediates, ignore, byte) => { + self.esc_dispatch(&intermediates, ignore, byte); + } + } + } + fn cursor_coordinates(&self) -> Option<(usize, usize)> { + // (x, y) + self.scroll.cursor_coordinates_on_screen() + } + fn adjust_input_to_terminal(&self, input_bytes: Vec) -> Vec { + // there are some cases in which the terminal state means that input sent to it + // needs to be adjusted. + // here we match against those cases - if need be, we adjust the input and if not + // we send back the original input + match input_bytes.as_slice() { + [27, 91, 68] => { + // left arrow + if self.cursor_key_mode { + // please note that in the line below, there is an ANSI escape code (27) at the beginning of the string, + // some editors will not show this + return "OD".as_bytes().to_vec(); + } + } + [27, 91, 67] => { + // right arrow + if self.cursor_key_mode { + // please note that in the line below, there is an ANSI escape code (27) at the beginning of the string, + // some editors will not show this + return "OC".as_bytes().to_vec(); + } + } + [27, 91, 65] => { + // up arrow + if self.cursor_key_mode { + // please note that in the line below, there is an ANSI escape code (27) at the beginning of the string, + // some editors will not show this + return "OA".as_bytes().to_vec(); + } + } + [27, 91, 66] => { + // down arrow + if self.cursor_key_mode { + // please note that in the line below, there is an ANSI escape code (27) at the beginning of the string, + // some editors will not show this + return "OB".as_bytes().to_vec(); + } + } + _ => {} + }; + input_bytes + } + + fn position_and_size_override(&self) -> Option { + self.position_and_size_override + } + fn should_render(&self) -> bool { + self.should_render + } + fn set_should_render(&mut self, should_render: bool) { + self.should_render = should_render; + } + fn buffer_as_vte_output(&mut self) -> Option { + // TODO: rename to render + // if self.should_render { + if true { + // while checking should_render rather than rendering each pane every time + // is more performant, it causes some problems when the pane to the left should be + // rendered and has wide characters (eg. Chinese characters or emoji) + // as a (hopefully) temporary hack, we render all panes until we find a better solution + let mut vte_output = String::new(); + let buffer_lines = &self.read_buffer_as_lines(); + let display_cols = self.get_columns(); + let mut character_styles = CharacterStyles::new(); + for (row, line) in buffer_lines.iter().enumerate() { + let x = self.get_x(); + let y = self.get_y(); + vte_output = format!("{}\u{1b}[{};{}H\u{1b}[m", vte_output, y + row + 1, x + 1); // goto row/col and reset styles + for (col, t_character) in line.iter().enumerate() { + if col < display_cols { + // in some cases (eg. while resizing) some characters will spill over + // before they are corrected by the shell (for the prompt) or by reflowing + // lines + if let Some(new_styles) = + character_styles.update_and_return_diff(&t_character.styles) + { + // the terminal keeps the previous styles as long as we're in the same + // line, so we only want to update the new styles here (this also + // includes resetting previous styles as needed) + vte_output = format!("{}{}", vte_output, new_styles); + } + vte_output.push(t_character.character); + } + } + character_styles.clear(); + } + self.mark_for_rerender(); + Some(vte_output) + } else { + None + } + } + fn pid(&self) -> RawFd { + self.pid + } + fn reduce_height_down(&mut self, count: usize) { + self.position_and_size.y += count; + self.position_and_size.rows -= count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn increase_height_down(&mut self, count: usize) { + self.position_and_size.rows += count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn increase_height_up(&mut self, count: usize) { + self.position_and_size.y -= count; + self.position_and_size.rows += count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn reduce_height_up(&mut self, count: usize) { + self.position_and_size.rows -= count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn reduce_width_right(&mut self, count: usize) { + self.position_and_size.x += count; + self.position_and_size.columns -= count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn reduce_width_left(&mut self, count: usize) { + self.position_and_size.columns -= count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn increase_width_left(&mut self, count: usize) { + self.position_and_size.x -= count; + self.position_and_size.columns += count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn increase_width_right(&mut self, count: usize) { + self.position_and_size.columns += count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn scroll_up(&mut self, count: usize) { + self.scroll.move_viewport_up(count); + self.mark_for_rerender(); + } + fn scroll_down(&mut self, count: usize) { + self.scroll.move_viewport_down(count); + self.mark_for_rerender(); + } + fn clear_scroll(&mut self) { + self.scroll.reset_viewport(); + self.mark_for_rerender(); + } } -impl Rect for &mut TerminalPane { +impl Pane for &mut TerminalPane { fn x(&self) -> usize { self.get_x() } @@ -70,6 +293,231 @@ impl Rect for &mut TerminalPane { fn columns(&self) -> usize { self.get_columns() } + fn reset_size_and_position_override(&mut self) { + self.position_and_size_override = None; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn change_size_p(&mut self, position_and_size: &PositionAndSize) { + self.position_and_size = *position_and_size; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn get_rows(&self) -> usize { + match &self.position_and_size_override.as_ref() { + Some(position_and_size_override) => position_and_size_override.rows, + None => self.position_and_size.rows as usize, + } + } + fn get_columns(&self) -> usize { + match &self.position_and_size_override.as_ref() { + Some(position_and_size_override) => position_and_size_override.columns, + None => self.position_and_size.columns as usize, + } + } + fn change_size(&mut self, ws: &PositionAndSize) { + self.position_and_size.columns = ws.columns; + self.position_and_size.rows = ws.rows; + self.reflow_lines(); + self.mark_for_rerender(); + } + + fn override_size_and_position(&mut self, x: usize, y: usize, size: &PositionAndSize) { + let position_and_size_override = PositionAndSize { + x, + y, + rows: size.rows, + columns: size.columns, + }; + self.position_and_size_override = Some(position_and_size_override); + self.reflow_lines(); + self.mark_for_rerender(); + } + fn handle_event(&mut self, event: VteEvent) { + match event { + VteEvent::Print(c) => { + self.print(c); + self.mark_for_rerender(); + } + VteEvent::Execute(byte) => { + self.execute(byte); + } + VteEvent::Hook(params, intermediates, ignore, c) => { + self.hook(¶ms, &intermediates, ignore, c); + } + VteEvent::Put(byte) => { + self.put(byte); + } + VteEvent::Unhook => { + self.unhook(); + } + VteEvent::OscDispatch(params, bell_terminated) => { + let params: Vec<&[u8]> = params.iter().map(|p| &p[..]).collect(); + self.osc_dispatch(¶ms[..], bell_terminated); + } + VteEvent::CsiDispatch(params, intermediates, ignore, c) => { + self.csi_dispatch(¶ms, &intermediates, ignore, c); + } + VteEvent::EscDispatch(intermediates, ignore, byte) => { + self.esc_dispatch(&intermediates, ignore, byte); + } + } + } + fn cursor_coordinates(&self) -> Option<(usize, usize)> { + // (x, y) + self.scroll.cursor_coordinates_on_screen() + } + fn adjust_input_to_terminal(&self, input_bytes: Vec) -> Vec { + // there are some cases in which the terminal state means that input sent to it + // needs to be adjusted. + // here we match against those cases - if need be, we adjust the input and if not + // we send back the original input + match input_bytes.as_slice() { + [27, 91, 68] => { + // left arrow + if self.cursor_key_mode { + // please note that in the line below, there is an ANSI escape code (27) at the beginning of the string, + // some editors will not show this + return "OD".as_bytes().to_vec(); + } + } + [27, 91, 67] => { + // right arrow + if self.cursor_key_mode { + // please note that in the line below, there is an ANSI escape code (27) at the beginning of the string, + // some editors will not show this + return "OC".as_bytes().to_vec(); + } + } + [27, 91, 65] => { + // up arrow + if self.cursor_key_mode { + // please note that in the line below, there is an ANSI escape code (27) at the beginning of the string, + // some editors will not show this + return "OA".as_bytes().to_vec(); + } + } + [27, 91, 66] => { + // down arrow + if self.cursor_key_mode { + // please note that in the line below, there is an ANSI escape code (27) at the beginning of the string, + // some editors will not show this + return "OB".as_bytes().to_vec(); + } + } + _ => {} + }; + input_bytes + } + + fn position_and_size_override(&self) -> Option { + self.position_and_size_override + } + fn should_render(&self) -> bool { + self.should_render + } + fn set_should_render(&mut self, should_render: bool) { + self.should_render = should_render; + } + fn buffer_as_vte_output(&mut self) -> Option { + // TODO: rename to render + // if self.should_render { + if true { + // while checking should_render rather than rendering each pane every time + // is more performant, it causes some problems when the pane to the left should be + // rendered and has wide characters (eg. Chinese characters or emoji) + // as a (hopefully) temporary hack, we render all panes until we find a better solution + let mut vte_output = String::new(); + let buffer_lines = &self.read_buffer_as_lines(); + let display_cols = self.get_columns(); + let mut character_styles = CharacterStyles::new(); + for (row, line) in buffer_lines.iter().enumerate() { + let x = self.get_x(); + let y = self.get_y(); + vte_output = format!("{}\u{1b}[{};{}H\u{1b}[m", vte_output, y + row + 1, x + 1); // goto row/col and reset styles + for (col, t_character) in line.iter().enumerate() { + if col < display_cols { + // in some cases (eg. while resizing) some characters will spill over + // before they are corrected by the shell (for the prompt) or by reflowing + // lines + if let Some(new_styles) = + character_styles.update_and_return_diff(&t_character.styles) + { + // the terminal keeps the previous styles as long as we're in the same + // line, so we only want to update the new styles here (this also + // includes resetting previous styles as needed) + vte_output = format!("{}{}", vte_output, new_styles); + } + vte_output.push(t_character.character); + } + } + character_styles.clear(); + } + self.mark_for_rerender(); + Some(vte_output) + } else { + None + } + } + fn pid(&self) -> RawFd { + self.pid + } + fn reduce_height_down(&mut self, count: usize) { + self.position_and_size.y += count; + self.position_and_size.rows -= count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn increase_height_down(&mut self, count: usize) { + self.position_and_size.rows += count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn increase_height_up(&mut self, count: usize) { + self.position_and_size.y -= count; + self.position_and_size.rows += count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn reduce_height_up(&mut self, count: usize) { + self.position_and_size.rows -= count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn reduce_width_right(&mut self, count: usize) { + self.position_and_size.x += count; + self.position_and_size.columns -= count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn reduce_width_left(&mut self, count: usize) { + self.position_and_size.columns -= count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn increase_width_left(&mut self, count: usize) { + self.position_and_size.x -= count; + self.position_and_size.columns += count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn increase_width_right(&mut self, count: usize) { + self.position_and_size.columns += count; + self.reflow_lines(); + self.mark_for_rerender(); + } + fn scroll_up(&mut self, count: usize) { + self.scroll.move_viewport_up(count); + self.mark_for_rerender(); + } + fn scroll_down(&mut self, count: usize) { + self.scroll.move_viewport_down(count); + self.mark_for_rerender(); + } + fn clear_scroll(&mut self) { + self.scroll.reset_viewport(); + self.mark_for_rerender(); + } } impl TerminalPane { @@ -125,55 +573,6 @@ impl TerminalPane { } } } - pub fn reduce_width_right(&mut self, count: usize) { - self.position_and_size.x += count; - self.position_and_size.columns -= count; - self.reflow_lines(); - self.mark_for_rerender(); - } - pub fn reduce_width_left(&mut self, count: usize) { - self.position_and_size.columns -= count; - self.reflow_lines(); - self.mark_for_rerender(); - } - pub fn increase_width_left(&mut self, count: usize) { - self.position_and_size.x -= count; - self.position_and_size.columns += count; - self.reflow_lines(); - self.mark_for_rerender(); - } - pub fn increase_width_right(&mut self, count: usize) { - self.position_and_size.columns += count; - self.reflow_lines(); - self.mark_for_rerender(); - } - pub fn reduce_height_down(&mut self, count: usize) { - self.position_and_size.y += count; - self.position_and_size.rows -= count; - self.reflow_lines(); - self.mark_for_rerender(); - } - pub fn increase_height_down(&mut self, count: usize) { - self.position_and_size.rows += count; - self.reflow_lines(); - self.mark_for_rerender(); - } - pub fn increase_height_up(&mut self, count: usize) { - self.position_and_size.y -= count; - self.position_and_size.rows += count; - self.reflow_lines(); - self.mark_for_rerender(); - } - pub fn reduce_height_up(&mut self, count: usize) { - self.position_and_size.rows -= count; - self.reflow_lines(); - self.mark_for_rerender(); - } - pub fn change_size_p(&mut self, position_and_size: &PositionAndSize) { - self.position_and_size = *position_and_size; - self.reflow_lines(); - self.mark_for_rerender(); - } // TODO: merge these two methods pub fn change_size(&mut self, ws: &PositionAndSize) { self.position_and_size.columns = ws.columns; @@ -288,53 +687,7 @@ impl TerminalPane { self.reflow_lines(); self.mark_for_rerender(); } - pub fn reset_size_and_position_override(&mut self) { - self.position_and_size_override = None; - self.reflow_lines(); - self.mark_for_rerender(); - } - pub fn adjust_input_to_terminal(&self, input_bytes: Vec) -> Vec { - // there are some cases in which the terminal state means that input sent to it - // needs to be adjusted. - // here we match against those cases - if need be, we adjust the input and if not - // we send back the original input - match input_bytes.as_slice() { - [27, 91, 68] => { - // left arrow - if self.cursor_key_mode { - // please note that in the line below, there is an ANSI escape code (27) at the beginning of the string, - // some editors will not show this - return "OD".as_bytes().to_vec(); - } - } - [27, 91, 67] => { - // right arrow - if self.cursor_key_mode { - // please note that in the line below, there is an ANSI escape code (27) at the beginning of the string, - // some editors will not show this - return "OC".as_bytes().to_vec(); - } - } - [27, 91, 65] => { - // up arrow - if self.cursor_key_mode { - // please note that in the line below, there is an ANSI escape code (27) at the beginning of the string, - // some editors will not show this - return "OA".as_bytes().to_vec(); - } - } - [27, 91, 66] => { - // down arrow - if self.cursor_key_mode { - // please note that in the line below, there is an ANSI escape code (27) at the beginning of the string, - // some editors will not show this - return "OB".as_bytes().to_vec(); - } - } - _ => {} - }; - input_bytes - } + fn add_newline(&mut self) { self.scroll.add_canonical_line(); // self.reset_all_ansi_codes(); // TODO: find out if we should be resetting here or not From 22890c53fe78cdaa17dc542d0864fbd21a02b4aa Mon Sep 17 00:00:00 2001 From: Brooks Rady Date: Wed, 30 Dec 2020 08:59:32 +0000 Subject: [PATCH 2/2] fix(plugins): fully Working WebAssembly Loading! (#125) * Fully Working WebAssembly Loading! * Move some wasm code to it's own module --- Cargo.lock | 101 +++++++++++++++++++++++++++++++++---------------- Cargo.toml | 4 +- src/main.rs | 66 ++++++++++++-------------------- src/wasm_vm.rs | 41 ++++++++++++++++++++ 4 files changed, 136 insertions(+), 76 deletions(-) create mode 100644 src/wasm_vm.rs diff --git a/Cargo.lock b/Cargo.lock index 3c7bf2c6d..27c91846b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,7 +110,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "miniz_oxide", - "object 0.22.0", + "object", "rustc-demangle", ] @@ -329,7 +329,7 @@ dependencies = [ "const_fn", "crossbeam-utils 0.8.0", "lazy_static", - "memoffset", + "memoffset 0.5.6", "scopeguard", ] @@ -832,6 +832,15 @@ version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +[[package]] +name = "memmap2" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e73be3b7d04a0123e933fea1d50d126cc7196bbc0362c0ce426694f777194eee" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.5.6" @@ -841,6 +850,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" +dependencies = [ + "autocfg", +] + [[package]] name = "miniz_oxide" version = "0.4.3" @@ -915,20 +933,14 @@ dependencies = [ [[package]] name = "object" -version = "0.21.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37fd5004feb2ce328a52b0b3d01dbf4ffff72583493900ed15f22d4111c51693" +checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" dependencies = [ "crc32fast", "indexmap", ] -[[package]] -name = "object" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" - [[package]] name = "once_cell" version = "1.4.0" @@ -1678,8 +1690,9 @@ checksum = "93b162580e34310e5931c4b792560108b10fd14d64915d7fff8ff00180e70092" [[package]] name = "wasmer" -version = "1.0.0-alpha5" -source = "git+https://github.com/wasmerio/wasmer.git#5e2dc65463a49b08c14bf9fb48eb45fa7d79d4c2" +version = "1.0.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe7fb8734c3e522aea0bed12315115e4c5d684c3d312db5f3ef6a8a312b1b47" dependencies = [ "cfg-if 0.1.10", "indexmap", @@ -1688,6 +1701,7 @@ dependencies = [ "thiserror", "wasmer-compiler", "wasmer-compiler-cranelift", + "wasmer-derive", "wasmer-engine", "wasmer-engine-jit", "wasmer-engine-native", @@ -1699,8 +1713,9 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "1.0.0-alpha5" -source = "git+https://github.com/wasmerio/wasmer.git#5e2dc65463a49b08c14bf9fb48eb45fa7d79d4c2" +version = "1.0.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97789fdc5968ea3d29528648dc2422e0c795ca195b88a59c30a56f0e52805690" dependencies = [ "enumset", "raw-cpuid", @@ -1716,8 +1731,9 @@ dependencies = [ [[package]] name = "wasmer-compiler-cranelift" -version = "1.0.0-alpha5" -source = "git+https://github.com/wasmerio/wasmer.git#5e2dc65463a49b08c14bf9fb48eb45fa7d79d4c2" +version = "1.0.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e80c86796019ef6d4519e1a66f2b99ab73b937a4e43e723772956b3e8c8df23" dependencies = [ "cranelift-codegen", "cranelift-frontend", @@ -1732,14 +1748,28 @@ dependencies = [ "wasmer-vm", ] +[[package]] +name = "wasmer-derive" +version = "1.0.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c74a84dc4ba0d60e9419f335734fa807097caf4938b2b44bc0703688a42b467" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "wasmer-engine" -version = "1.0.0-alpha5" -source = "git+https://github.com/wasmerio/wasmer.git#5e2dc65463a49b08c14bf9fb48eb45fa7d79d4c2" +version = "1.0.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e787fb8e42b5ad32c1c8dcf105e42d2919dfb3ea4b8e286de3e43f306ae1457b" dependencies = [ "backtrace", "bincode", "lazy_static", + "memmap2", "more-asserts", "rustc-demangle", "serde", @@ -1753,8 +1783,9 @@ dependencies = [ [[package]] name = "wasmer-engine-jit" -version = "1.0.0-alpha5" -source = "git+https://github.com/wasmerio/wasmer.git#5e2dc65463a49b08c14bf9fb48eb45fa7d79d4c2" +version = "1.0.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552f4252f8d7984279c55df0970ca1d42b1e4c63d918e7af1cd004e427e5008c" dependencies = [ "bincode", "cfg-if 0.1.10", @@ -1770,8 +1801,9 @@ dependencies = [ [[package]] name = "wasmer-engine-native" -version = "1.0.0-alpha5" -source = "git+https://github.com/wasmerio/wasmer.git#5e2dc65463a49b08c14bf9fb48eb45fa7d79d4c2" +version = "1.0.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5264031a9b398a071fa128fe89fb55bc75f9c0ac5eaa7f1f9ef9efcee08afa1c" dependencies = [ "bincode", "cfg-if 0.1.10", @@ -1790,10 +1822,11 @@ dependencies = [ [[package]] name = "wasmer-object" -version = "1.0.0-alpha5" -source = "git+https://github.com/wasmerio/wasmer.git#5e2dc65463a49b08c14bf9fb48eb45fa7d79d4c2" +version = "1.0.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22ccf03052d73b3588bd30de94db9ee949957a543d0c317122f2b87b7d1f309" dependencies = [ - "object 0.21.1", + "object", "thiserror", "wasmer-compiler", "wasmer-types", @@ -1801,24 +1834,27 @@ dependencies = [ [[package]] name = "wasmer-types" -version = "1.0.0-alpha5" -source = "git+https://github.com/wasmerio/wasmer.git#5e2dc65463a49b08c14bf9fb48eb45fa7d79d4c2" +version = "1.0.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3ea5b135db86baf39ce45f6cf98cc97d6e4234d3f75ac56a026f94bd8b68b1" dependencies = [ "cranelift-entity", "serde", + "thiserror", ] [[package]] name = "wasmer-vm" -version = "1.0.0-alpha5" -source = "git+https://github.com/wasmerio/wasmer.git#5e2dc65463a49b08c14bf9fb48eb45fa7d79d4c2" +version = "1.0.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d766b8db150b7e524c83b244e14a1180bf919b4f8bea6f063bae9a8e8d4156" dependencies = [ "backtrace", "cc", "cfg-if 0.1.10", "indexmap", "libc", - "memoffset", + "memoffset 0.6.1", "more-asserts", "region", "serde", @@ -1829,8 +1865,9 @@ dependencies = [ [[package]] name = "wasmer-wasi" -version = "1.0.0-alpha5" -source = "git+https://github.com/wasmerio/wasmer.git#5e2dc65463a49b08c14bf9fb48eb45fa7d79d4c2" +version = "1.0.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b9e383c0a20fb697080b8e87613a0bb2e901a9f06ca710030b4a521ebcc398" dependencies = [ "bincode", "byteorder", diff --git a/Cargo.toml b/Cargo.toml index 41dd31753..792792e0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,11 +27,11 @@ version = "1.3.0" features = ["unstable"] [dependencies.wasmer] -git = "https://github.com/wasmerio/wasmer.git" +version = "1.0.0-rc" optional = true [dependencies.wasmer-wasi] -git = "https://github.com/wasmerio/wasmer.git" +version = "1.0.0-rc" optional = true [features] diff --git a/src/main.rs b/src/main.rs index c59fe1c4f..7ec9475c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,8 @@ mod screen; mod tab; mod terminal_pane; mod utils; +#[cfg(feature = "wasm-wip")] +mod wasm_vm; use std::io::Write; use std::os::unix::net::UnixStream; @@ -396,51 +398,39 @@ pub fn start(mut os_input: Box, opts: Opt) { .spawn(move || { // TODO: Clone shared state here move || -> Result<(), Box> { + use crate::wasm_vm::{mosaic_imports, wasi_stdout}; use std::io; - use std::sync::{Arc, Mutex}; - use wasmer::{Exports, Function, Instance, Module, Store, Value}; - use wasmer_wasi::WasiState; + use wasmer::{ChainableNamedResolver, Instance, Module, Store, Value}; + use wasmer_wasi::{Pipe, WasiState}; + let store = Store::default(); println!("Compiling module..."); - // FIXME: Switch to a higher performance compiler (`Store::default()`) and cache this on disk - // I could use `(de)serialize_to_file()` for that + // FIXME: Cache this compiled module on disk. I could use `(de)serialize_to_file()` for that let module = if let Ok(m) = Module::from_file(&store, "strider.wasm") { m } else { return Ok(()); // Just abort this thread quietly if the WASM isn't found }; - // FIXME: Upstream the `Pipe` struct - //let output = fluff::Pipe::new(); - //let input = fluff::Pipe::new(); + let output = Pipe::new(); + let input = Pipe::new(); let mut wasi_env = WasiState::new("mosaic") .env("CLICOLOR_FORCE", "1") .preopen(|p| { - p.directory(".") // TODO: Change this to a more meaningful dir + p.directory(".") // FIXME: Change this to a more meaningful dir .alias(".") .read(true) .write(true) .create(true) })? - //.stdin(Box::new(input)) - //.stdout(Box::new(output)) + .stdin(Box::new(input)) + .stdout(Box::new(output)) .finalize()?; - let mut import_object = wasi_env.import_object(&module)?; - // FIXME: Upstream an `ImportObject` merge method - let mut host_exports = Exports::new(); - /* host_exports.insert( - "host_open_file", - Function::new_native_with_env(&store, Arc::clone(&wasi_env.state), host_open_file), - ); */ - fn noop() {} - host_exports.insert("host_open_file", Function::new_native(&store, noop)); - import_object.register("mosaic", host_exports); - let instance = Instance::new(&module, &import_object)?; - - // WASI requires to explicitly set the memory for the `WasiEnv` - wasi_env.set_memory(instance.exports.get_memory("memory")?.clone()); + let wasi = wasi_env.import_object(&module)?; + let mosaic = mosaic_imports(&store, &wasi_env); + let instance = Instance::new(&module, &mosaic.chain_back(wasi))?; let start = instance.exports.get_function("_start")?; let handle_key = instance.exports.get_function("handle_key")?; @@ -451,39 +441,31 @@ pub fn start(mut os_input: Box, opts: Opt) { #[warn(clippy::never_loop)] loop { - break; - //let (cols, rows) = terminal::size()?; - //draw.call(&[Value::I32(rows as i32), Value::I32(cols as i32)])?; + let (cols, rows) = (80, 24); //terminal::size()?; + draw.call(&[Value::I32(rows), Value::I32(cols)])?; - // FIXME: This downcasting mess needs to be abstracted away - /* let mut state = wasi_env.state(); - let wasi_file = state.fs.stdout_mut()?.as_mut().unwrap(); - let output: &mut fluff::Pipe = wasi_file.downcast_mut().unwrap(); // Needed because raw mode doesn't implicitly return to the start of the line write!( io::stdout(), "{}\n\r", - output.to_string().lines().collect::>().join("\n\r") + wasi_stdout(&wasi_env) + .lines() + .collect::>() + .join("\n\r") )?; - output.clear(); - let wasi_file = state.fs.stdin_mut()?.as_mut().unwrap(); - let input: &mut fluff::Pipe = wasi_file.downcast_mut().unwrap(); - input.clear(); */ - - /* match event::read()? { + /* match event::read().unwrap() { Event::Key(KeyEvent { code: KeyCode::Char('q'), .. }) => break, Event::Key(e) => { - writeln!(input, "{}\r", serde_json::to_string(&e)?)?; - drop(state); - // Need to release the implicit `state` mutex or I deadlock! + wasi_write_string(&wasi_env, serde_json::to_string(&e).unwrap()); handle_key.call(&[])?; } _ => (), } */ + break; } debug_log_to_file("WASM module loaded and exited cleanly :)".to_string())?; Ok(()) diff --git a/src/wasm_vm.rs b/src/wasm_vm.rs new file mode 100644 index 000000000..334ad0b1d --- /dev/null +++ b/src/wasm_vm.rs @@ -0,0 +1,41 @@ +use std::process::{Command, Stdio}; +use wasmer::{imports, Function, ImportObject, Store}; +use wasmer_wasi::WasiEnv; + +// Plugin API ----------------------------------------------------------------- + +pub fn mosaic_imports(store: &Store, wasi_env: &WasiEnv) -> ImportObject { + imports! { + "mosaic" => { + "host_open_file" => Function::new_native_with_env(store, wasi_env.clone(), host_open_file) + } + } +} + +fn host_open_file(wasi_env: &WasiEnv) { + Command::new("xdg-open") + .arg(format!( + "./{}", + wasi_stdout(wasi_env).lines().next().unwrap() + )) + .stderr(Stdio::null()) + .spawn() + .unwrap(); +} + +// Helper Functions ----------------------------------------------------------- + +// FIXME: Unwrap city +pub fn wasi_stdout(wasi_env: &WasiEnv) -> String { + let mut state = wasi_env.state(); + let wasi_file = state.fs.stdout_mut().unwrap().as_mut().unwrap(); + let mut buf = String::new(); + wasi_file.read_to_string(&mut buf).unwrap(); + buf +} + +pub fn _wasi_write_string(wasi_env: &WasiEnv, buf: &str) { + let mut state = wasi_env.state(); + let wasi_file = state.fs.stdin_mut().unwrap().as_mut().unwrap(); + writeln!(wasi_file, "{}\r", buf).unwrap(); +}