diff --git a/Cargo.lock b/Cargo.lock index ad8705d6..23049df6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,6 +40,9 @@ name = "anyhow" version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" +dependencies = [ + "backtrace", +] [[package]] name = "arc-swap" diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 012cc557..fcb1de8c 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -40,8 +40,10 @@ use zellij_utils::{ /// /// - screen: An instance of `Screen` to operate on /// - client_id: The client_id, usually taken from the `ScreenInstruction` that's being processed -/// - closure: A closure satisfying `|tab: &mut Tab| -> ()` - +/// - closure: A closure satisfying `|tab: &mut Tab| -> ()` OR `|tab: &mut Tab| -> Result` (see +/// '?' below) +/// - ?: A literal "?", to append a `?` to the closure when it returns a `Result` type. This +/// argument is optional and not needed when the closure returns `()` macro_rules! active_tab { ($screen:ident, $client_id:ident, $closure:expr) => { if let Some(active_tab) = $screen.get_active_tab_mut($client_id) { @@ -54,7 +56,16 @@ macro_rules! active_tab { log::error!("Active tab not found for client id: {:?}", $client_id); } }; + // Same as above, but with an added `?` for when the close returns a `Result` type. + ($screen:ident, $client_id:ident, $closure:expr, ?) => { + if let Some(active_tab) = $screen.get_active_tab_mut($client_id) { + $closure(active_tab)?; + } else { + log::error!("Active tab not found for client id: {:?}", $client_id); + } + }; } + macro_rules! active_tab_and_connected_client_id { ($screen:ident, $client_id:ident, $closure:expr) => { match $screen.get_active_tab_mut($client_id) { @@ -71,6 +82,30 @@ macro_rules! active_tab_and_connected_client_id { log::error!("Active tab not found for client id: {:?}", $client_id); }, } + } else { + log::error!("No client ids in screen found"); + }; + }, + } + }; + // Same as above, but with an added `?` for when the closure returns a `Result` type. + ($screen:ident, $client_id:ident, $closure:expr, ?) => { + match $screen.get_active_tab_mut($client_id) { + Some(active_tab) => { + $closure(active_tab, $client_id)?; + }, + None => { + if let Some(client_id) = $screen.get_first_client_id() { + match $screen.get_active_tab_mut(client_id) { + Some(active_tab) => { + $closure(active_tab, client_id)?; + }, + None => { + log::error!("Active tab not found for client id: {:?}", $client_id); + }, + } + } else { + log::error!("No client ids in screen found"); }; }, } @@ -393,32 +428,44 @@ impl Screen { fn move_clients_from_closed_tab( &mut self, client_ids_and_mode_infos: Vec<(ClientId, ModeInfo)>, - ) { + ) -> Result<()> { + let err_context = || "failed to move clients from closed tab".to_string(); + if self.tabs.is_empty() { log::error!( "No tabs left, cannot move clients: {:?} from closed tab", client_ids_and_mode_infos ); - return; + return Ok(()); } - let first_tab_index = *self.tabs.keys().next().unwrap(); + let first_tab_index = *self + .tabs + .keys() + .next() + .context("screen contained no tabs") + .with_context(err_context)?; for (client_id, client_mode_info) in client_ids_and_mode_infos { let client_tab_history = self.tab_history.entry(client_id).or_insert_with(Vec::new); if let Some(client_previous_tab) = client_tab_history.pop() { if let Some(client_active_tab) = self.tabs.get_mut(&client_previous_tab) { self.active_tab_indices .insert(client_id, client_previous_tab); - client_active_tab.add_client(client_id, Some(client_mode_info)); + client_active_tab + .add_client(client_id, Some(client_mode_info)) + .with_context(err_context)?; continue; } } self.active_tab_indices.insert(client_id, first_tab_index); self.tabs .get_mut(&first_tab_index) - .unwrap() - .add_client(client_id, Some(client_mode_info)); + .with_context(err_context)? + .add_client(client_id, Some(client_mode_info)) + .with_context(err_context)?; } + Ok(()) } + fn move_clients_between_tabs( &mut self, source_tab_index: usize, @@ -440,13 +487,18 @@ impl Screen { .get_indexed_tab_mut(destination_tab_index) .context("failed to get destination tab by index") .with_context(err_context)?; - destination_tab.add_multiple_clients(client_mode_info_in_source_tab); - destination_tab.update_input_modes(); + destination_tab + .add_multiple_clients(client_mode_info_in_source_tab) + .with_context(err_context)?; + destination_tab + .update_input_modes() + .with_context(err_context)?; destination_tab.set_force_render(); - destination_tab.visible(true); + destination_tab.visible(true).with_context(err_context)?; } Ok(()) } + fn update_client_tab_focus(&mut self, client_id: ClientId, new_tab_index: usize) { match self.active_tab_indices.remove(&client_id) { Some(old_active_index) => { @@ -498,7 +550,7 @@ impl Screen { if let Some(current_tab) = self.get_indexed_tab_mut(current_tab_index) { if current_tab.has_no_connected_clients() { - current_tab.visible(false); + current_tab.visible(false).with_context(err_context)?; } } else { log::error!("Tab index: {:?} not found", current_tab_index); @@ -564,6 +616,7 @@ impl Screen { fn close_tab_at_index(&mut self, tab_index: usize) -> Result<()> { let err_context = || format!("failed to close tab at index {tab_index:?}"); + let mut tab_to_close = self.tabs.remove(&tab_index).with_context(err_context)?; let pane_ids = tab_to_close.get_all_pane_ids(); // below we don't check the result of sending the CloseTab instruction to the pty thread @@ -581,13 +634,14 @@ impl Screen { .with_context(err_context) } else { let client_mode_infos_in_closed_tab = tab_to_close.drain_connected_clients(None); - self.move_clients_from_closed_tab(client_mode_infos_in_closed_tab); + self.move_clients_from_closed_tab(client_mode_infos_in_closed_tab) + .with_context(err_context)?; let visible_tab_indices: HashSet = self.active_tab_indices.values().copied().collect(); for t in self.tabs.values_mut() { if visible_tab_indices.contains(&t.index) { t.set_force_render(); - t.visible(true); + t.visible(true).with_context(err_context)?; } if t.position > tab_to_close.position { t.position -= 1; @@ -683,7 +737,8 @@ impl Screen { for (tab_index, tab) in &mut self.tabs { if tab.has_selectable_tiled_panes() { let vte_overlay = overlay.generate_overlay(size); - tab.render(&mut output, Some(vte_overlay)); + tab.render(&mut output, Some(vte_overlay)) + .context(err_context)?; } else { tabs_to_close.push(*tab_index); } @@ -793,13 +848,15 @@ impl Screen { self.terminal_emulator_colors.clone(), self.terminal_emulator_color_codes.clone(), ); - tab.apply_layout(layout, new_pids, tab_index, client_id); + tab.apply_layout(layout, new_pids, tab_index, client_id) + .with_context(err_context)?; if self.session_is_mirrored { if let Some(active_tab) = self.get_active_tab_mut(client_id) { let client_mode_infos_in_source_tab = active_tab.drain_connected_clients(None); - tab.add_multiple_clients(client_mode_infos_in_source_tab); + tab.add_multiple_clients(client_mode_infos_in_source_tab) + .with_context(err_context)?; if active_tab.has_no_connected_clients() { - active_tab.visible(false); + active_tab.visible(false).with_context(err_context)?; } } let all_connected_clients: Vec = @@ -810,14 +867,15 @@ impl Screen { } else if let Some(active_tab) = self.get_active_tab_mut(client_id) { let client_mode_info_in_source_tab = active_tab.drain_connected_clients(Some(vec![client_id])); - tab.add_multiple_clients(client_mode_info_in_source_tab); + tab.add_multiple_clients(client_mode_info_in_source_tab) + .with_context(err_context)?; if active_tab.has_no_connected_clients() { - active_tab.visible(false); + active_tab.visible(false).with_context(err_context)?; } self.update_client_tab_focus(client_id, tab_index); } - tab.update_input_modes(); - tab.visible(true); + tab.update_input_modes().with_context(err_context)?; + tab.visible(true).with_context(err_context)?; self.tabs.insert(tab_index, tab); if !self.active_tab_indices.contains_key(&client_id) { // this means this is a new client and we need to add it to our state properly @@ -829,6 +887,10 @@ impl Screen { } pub fn add_client(&mut self, client_id: ClientId) -> Result<()> { + let err_context = |tab_index| { + format!("failed to attach client {client_id} to tab with index {tab_index}") + }; + let mut tab_history = vec![]; if let Some((_first_client, first_tab_history)) = self.tab_history.iter().next() { tab_history = first_tab_history.clone(); @@ -843,7 +905,7 @@ impl Screen { } else if let Some(tab_index) = self.tabs.keys().next() { tab_index.to_owned() } else { - panic!("Can't find a valid tab to attach client to!"); + bail!("Can't find a valid tab to attach client to!"); }; self.active_tab_indices.insert(client_id, tab_index); @@ -851,18 +913,20 @@ impl Screen { self.tab_history.insert(client_id, tab_history); self.tabs .get_mut(&tab_index) - .with_context(|| format!("Failed to attach client to tab with index {tab_index}"))? - .add_client(client_id, None); - Ok(()) + .with_context(|| err_context(tab_index))? + .add_client(client_id, None) + .with_context(|| err_context(tab_index)) } pub fn remove_client(&mut self, client_id: ClientId) -> Result<()> { - self.tabs.iter_mut().for_each(|(_, tab)| { + let err_context = || format!("failed to remove client {client_id}"); + + for (_, tab) in self.tabs.iter_mut() { tab.remove_client(client_id); if tab.has_no_connected_clients() { - tab.visible(false); + tab.visible(false).with_context(err_context)?; } - }); + } if self.active_tab_indices.contains_key(&client_id) { self.active_tab_indices.remove(&client_id); } @@ -870,8 +934,7 @@ impl Screen { self.tab_history.remove(&client_id); } self.connected_clients.borrow_mut().remove(&client_id); - self.update_tabs() - .with_context(|| format!("failed to remove client {client_id:?}")) + self.update_tabs().with_context(err_context) } pub fn update_tabs(&self) -> Result<()> { @@ -908,12 +971,8 @@ impl Screen { Some(*client_id), Event::TabUpdate(tab_data), )) - .or_else(|err| { - let (_, error_context) = err.0; - Err(anyhow!("failed to send data to plugins")) - .context(error_context) - .context("failed to update tabs") - })?; + .to_anyhow() + .context("failed to update tabs")?; } Ok(()) } @@ -978,13 +1037,20 @@ impl Screen { } } - pub fn change_mode(&mut self, mode_info: ModeInfo, client_id: ClientId) { + pub fn change_mode(&mut self, mode_info: ModeInfo, client_id: ClientId) -> Result<()> { let previous_mode = self .mode_info .get(&client_id) .unwrap_or(&self.default_mode_info) .mode; + let err_context = || { + format!( + "failed to change from mode '{:?}' to mode '{:?}' for client {client_id}", + previous_mode, mode_info.mode + ) + }; + // If we leave the Search-related modes, we need to clear all previous searches let search_related_modes = [InputMode::EnterSearch, InputMode::Search, InputMode::Scroll]; if search_related_modes.contains(&previous_mode) @@ -997,7 +1063,9 @@ impl Screen { && (mode_info.mode == InputMode::Normal || mode_info.mode == InputMode::Locked) { if let Some(active_tab) = self.get_active_tab_mut(client_id) { - active_tab.clear_active_terminal_scroll(client_id); + active_tab + .clear_active_terminal_scroll(client_id) + .with_context(err_context)?; } } @@ -1023,16 +1091,27 @@ impl Screen { tab.change_mode_info(mode_info.clone(), client_id); tab.mark_active_pane_for_rerender(client_id); } + Ok(()) } - pub fn change_mode_for_all_clients(&mut self, mode_info: ModeInfo) { + + pub fn change_mode_for_all_clients(&mut self, mode_info: ModeInfo) -> Result<()> { + let err_context = || { + format!( + "failed to change input mode to {:?} for all clients", + mode_info.mode + ) + }; + let connected_client_ids: Vec = self.active_tab_indices.keys().copied().collect(); for client_id in connected_client_ids { - self.change_mode(mode_info.clone(), client_id); + self.change_mode(mode_info.clone(), client_id) + .with_context(err_context)?; if let Some(os_input) = &mut self.bus.os_input { let _ = os_input .send_to_client(client_id, ServerToClientMsg::SwitchToMode(mode_info.mode)); } } + Ok(()) } pub fn move_focus_left_or_previous_tab(&mut self, client_id: ClientId) -> Result<()> { let client_id = if self.get_active_tab(client_id).is_some() { @@ -1131,8 +1210,7 @@ pub(crate) fn screen_thread_main( let (event, mut err_ctx) = screen .bus .recv() - .context("failed to receive event on channel") - .fatal(); + .context("failed to receive event on channel")?; err_ctx.add_call(ContextType::Screen((&event).into())); match event { @@ -1140,7 +1218,8 @@ pub(crate) fn screen_thread_main( let all_tabs = screen.get_tabs_mut(); for tab in all_tabs.values_mut() { if tab.has_terminal_pid(pid) { - tab.handle_pty_bytes(pid, vte_bytes); + tab.handle_pty_bytes(pid, vte_bytes) + .context("failed to process pty bytes")?; break; } } @@ -1151,15 +1230,14 @@ pub(crate) fn screen_thread_main( ScreenInstruction::NewPane(pid, client_or_tab_index) => { match client_or_tab_index { ClientOrTabIndex::ClientId(client_id) => { - active_tab_and_connected_client_id!( - screen, - client_id, - |tab: &mut Tab, client_id: ClientId| tab.new_pane(pid, Some(client_id)) - ); + active_tab_and_connected_client_id!(screen, client_id, |tab: &mut Tab, + client_id: ClientId| tab .new_pane(pid, + Some(client_id)), + ?); }, ClientOrTabIndex::TabIndex(tab_index) => { if let Some(active_tab) = screen.tabs.get_mut(&tab_index) { - active_tab.new_pane(pid, None); + active_tab.new_pane(pid, None)?; } else { log::error!("Tab index not found: {:?}", tab_index); } @@ -1172,32 +1250,26 @@ pub(crate) fn screen_thread_main( }, ScreenInstruction::OpenInPlaceEditor(pid, client_id) => { active_tab!(screen, client_id, |tab: &mut Tab| tab - .suppress_active_pane(pid, client_id)); + .suppress_active_pane(pid, client_id), ?); screen.unblock_input()?; screen.update_tabs()?; screen.render()?; }, ScreenInstruction::TogglePaneEmbedOrFloating(client_id) => { - active_tab_and_connected_client_id!( - screen, - client_id, - |tab: &mut Tab, client_id: ClientId| tab - .toggle_pane_embed_or_floating(client_id) - ); + active_tab_and_connected_client_id!(screen, client_id, |tab: &mut Tab, client_id: ClientId| tab + .toggle_pane_embed_or_floating(client_id), ?); screen.unblock_input()?; screen.update_tabs()?; // update tabs so that the ui indication will be send to the plugins + screen.render()?; }, ScreenInstruction::ToggleFloatingPanes(client_id, default_shell) => { - active_tab_and_connected_client_id!( - screen, - client_id, - |tab: &mut Tab, client_id: ClientId| tab - .toggle_floating_panes(client_id, default_shell) - ); + active_tab_and_connected_client_id!(screen, client_id, |tab: &mut Tab, client_id: ClientId| tab + .toggle_floating_panes(client_id, default_shell), ?); screen.unblock_input()?; screen.update_tabs()?; // update tabs so that the ui indication will be send to the plugins + screen.render()?; }, ScreenInstruction::ShowFloatingPanes(client_id) => { @@ -1208,6 +1280,7 @@ pub(crate) fn screen_thread_main( ); screen.unblock_input()?; screen.update_tabs()?; // update tabs so that the ui indication will be send to the plugins + screen.render()?; }, ScreenInstruction::HideFloatingPanes(client_id) => { @@ -1218,13 +1291,15 @@ pub(crate) fn screen_thread_main( ); screen.unblock_input()?; screen.update_tabs()?; // update tabs so that the ui indication will be send to the plugins + screen.render()?; }, ScreenInstruction::HorizontalSplit(pid, client_id) => { active_tab_and_connected_client_id!( screen, client_id, - |tab: &mut Tab, client_id: ClientId| tab.horizontal_split(pid, client_id) + |tab: &mut Tab, client_id: ClientId| tab.horizontal_split(pid, client_id), + ? ); screen.unblock_input()?; screen.update_tabs()?; @@ -1234,7 +1309,8 @@ pub(crate) fn screen_thread_main( active_tab_and_connected_client_id!( screen, client_id, - |tab: &mut Tab, client_id: ClientId| tab.vertical_split(pid, client_id) + |tab: &mut Tab, client_id: ClientId| tab.vertical_split(pid, client_id), + ? ); screen.unblock_input()?; screen.update_tabs()?; @@ -1249,7 +1325,8 @@ pub(crate) fn screen_thread_main( true => tab.write_to_terminals_on_current_tab(bytes), false => tab.write_to_active_terminal(bytes, client_id), } - } + }, + ? ); }, ScreenInstruction::ResizeLeft(client_id) => { @@ -1393,7 +1470,8 @@ pub(crate) fn screen_thread_main( active_tab_and_connected_client_id!( screen, client_id, - |tab: &mut Tab, client_id: ClientId| tab.edit_scrollback(client_id) + |tab: &mut Tab, client_id: ClientId| tab.edit_scrollback(client_id), + ? ); screen.render()?; }, @@ -1456,7 +1534,7 @@ pub(crate) fn screen_thread_main( screen, client_id, |tab: &mut Tab, client_id: ClientId| tab - .handle_scrollwheel_up(&point, 3, client_id) + .handle_scrollwheel_up(&point, 3, client_id), ? ); screen.render()?; screen.unblock_input()?; @@ -1465,7 +1543,7 @@ pub(crate) fn screen_thread_main( active_tab_and_connected_client_id!( screen, client_id, - |tab: &mut Tab, client_id: ClientId| tab.scroll_active_terminal_down(client_id) + |tab: &mut Tab, client_id: ClientId| tab.scroll_active_terminal_down(client_id), ? ); screen.render()?; screen.unblock_input()?; @@ -1475,7 +1553,7 @@ pub(crate) fn screen_thread_main( screen, client_id, |tab: &mut Tab, client_id: ClientId| tab - .handle_scrollwheel_down(&point, 3, client_id) + .handle_scrollwheel_down(&point, 3, client_id), ? ); screen.render()?; screen.unblock_input()?; @@ -1485,7 +1563,7 @@ pub(crate) fn screen_thread_main( screen, client_id, |tab: &mut Tab, client_id: ClientId| tab - .scroll_active_terminal_to_bottom(client_id) + .scroll_active_terminal_to_bottom(client_id), ? ); screen.render()?; screen.unblock_input()?; @@ -1505,7 +1583,7 @@ pub(crate) fn screen_thread_main( screen, client_id, |tab: &mut Tab, client_id: ClientId| tab - .scroll_active_terminal_down_page(client_id) + .scroll_active_terminal_down_page(client_id), ? ); screen.render()?; screen.unblock_input()?; @@ -1525,7 +1603,7 @@ pub(crate) fn screen_thread_main( screen, client_id, |tab: &mut Tab, client_id: ClientId| tab - .scroll_active_terminal_down_half_page(client_id) + .scroll_active_terminal_down_half_page(client_id), ? ); screen.render()?; screen.unblock_input()?; @@ -1535,7 +1613,7 @@ pub(crate) fn screen_thread_main( screen, client_id, |tab: &mut Tab, client_id: ClientId| tab - .clear_active_terminal_scroll(client_id) + .clear_active_terminal_scroll(client_id), ? ); screen.render()?; screen.unblock_input()?; @@ -1544,7 +1622,7 @@ pub(crate) fn screen_thread_main( active_tab_and_connected_client_id!( screen, client_id, - |tab: &mut Tab, client_id: ClientId| tab.close_focused_pane(client_id) + |tab: &mut Tab, client_id: ClientId| tab.close_focused_pane(client_id), ? ); screen.update_tabs()?; screen.render()?; @@ -1585,7 +1663,7 @@ pub(crate) fn screen_thread_main( active_tab_and_connected_client_id!( screen, client_id, - |tab: &mut Tab, client_id: ClientId| tab.update_active_pane_name(c, client_id) + |tab: &mut Tab, client_id: ClientId| tab.update_active_pane_name(c, client_id), ? ); screen.render()?; screen.unblock_input()?; @@ -1594,7 +1672,7 @@ pub(crate) fn screen_thread_main( active_tab_and_connected_client_id!( screen, client_id, - |tab: &mut Tab, client_id: ClientId| tab.undo_active_rename_pane(client_id) + |tab: &mut Tab, client_id: ClientId| tab.undo_active_rename_pane(client_id), ? ); screen.render()?; screen.unblock_input()?; @@ -1641,7 +1719,10 @@ pub(crate) fn screen_thread_main( ScreenInstruction::GoToTab(tab_index, client_id) => { let client_id = if client_id.is_none() { None - } else if screen.active_tab_indices.contains_key(&client_id.unwrap()) { + } else if screen + .active_tab_indices + .contains_key(&client_id.expect("This is checked above")) + { client_id } else { screen.active_tab_indices.keys().next().copied() @@ -1679,12 +1760,12 @@ pub(crate) fn screen_thread_main( screen.update_terminal_color_registers(color_registers); }, ScreenInstruction::ChangeMode(mode_info, client_id) => { - screen.change_mode(mode_info, client_id); + screen.change_mode(mode_info, client_id)?; screen.render()?; screen.unblock_input()?; }, ScreenInstruction::ChangeModeForAllClients(mode_info) => { - screen.change_mode_for_all_clients(mode_info); + screen.change_mode_for_all_clients(mode_info)?; screen.render()?; screen.unblock_input()?; }, @@ -1700,62 +1781,59 @@ pub(crate) fn screen_thread_main( }, ScreenInstruction::LeftClick(point, client_id) => { active_tab!(screen, client_id, |tab: &mut Tab| tab - .handle_left_click(&point, client_id)); + .handle_left_click(&point, client_id), ?); screen.update_tabs()?; screen.render()?; screen.unblock_input()?; }, ScreenInstruction::RightClick(point, client_id) => { active_tab!(screen, client_id, |tab: &mut Tab| tab - .handle_right_click(&point, client_id)); + .handle_right_click(&point, client_id), ?); screen.update_tabs()?; screen.render()?; screen.unblock_input()?; }, ScreenInstruction::MiddleClick(point, client_id) => { active_tab!(screen, client_id, |tab: &mut Tab| tab - .handle_middle_click(&point, client_id)); + .handle_middle_click(&point, client_id), ?); screen.update_tabs()?; screen.render()?; screen.unblock_input()?; }, ScreenInstruction::LeftMouseRelease(point, client_id) => { active_tab!(screen, client_id, |tab: &mut Tab| tab - .handle_left_mouse_release(&point, client_id)); + .handle_left_mouse_release(&point, client_id), ?); screen.render()?; screen.unblock_input()?; }, ScreenInstruction::RightMouseRelease(point, client_id) => { active_tab!(screen, client_id, |tab: &mut Tab| tab - .handle_right_mouse_release(&point, client_id)); + .handle_right_mouse_release(&point, client_id), ?); screen.render()?; }, ScreenInstruction::MiddleMouseRelease(point, client_id) => { active_tab!(screen, client_id, |tab: &mut Tab| tab - .handle_middle_mouse_release(&point, client_id)); + .handle_middle_mouse_release(&point, client_id), ?); screen.render()?; }, ScreenInstruction::MouseHoldLeft(point, client_id) => { - active_tab!(screen, client_id, |tab: &mut Tab| { - tab.handle_mouse_hold_left(&point, client_id); - }); + active_tab!(screen, client_id, |tab: &mut Tab| tab + .handle_mouse_hold_left(&point, client_id), ?); screen.render()?; }, ScreenInstruction::MouseHoldRight(point, client_id) => { - active_tab!(screen, client_id, |tab: &mut Tab| { - tab.handle_mouse_hold_right(&point, client_id); - }); + active_tab!(screen, client_id, |tab: &mut Tab| tab + .handle_mouse_hold_right(&point, client_id), ?); screen.render()?; }, ScreenInstruction::MouseHoldMiddle(point, client_id) => { - active_tab!(screen, client_id, |tab: &mut Tab| { - tab.handle_mouse_hold_middle(&point, client_id); - }); + active_tab!(screen, client_id, |tab: &mut Tab| tab + .handle_mouse_hold_middle(&point, client_id), ?); screen.render()?; }, ScreenInstruction::Copy(client_id) => { active_tab!(screen, client_id, |tab: &mut Tab| tab - .copy_selection(client_id)); + .copy_selection(client_id), ?); screen.render()?; }, ScreenInstruction::Exit => { @@ -1807,7 +1885,7 @@ pub(crate) fn screen_thread_main( active_tab_and_connected_client_id!( screen, client_id, - |tab: &mut Tab, client_id: ClientId| tab.update_search_term(c, client_id) + |tab: &mut Tab, client_id: ClientId| tab.update_search_term(c, client_id), ? ); screen.render()?; }, diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index 883caf0d..7a3554df 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -7,6 +7,7 @@ mod copy_command; use copy_command::CopyCommand; use std::env::temp_dir; use uuid::Uuid; +use zellij_utils::errors::prelude::*; use zellij_utils::position::{Column, Line}; use zellij_utils::{position::Position, serde}; @@ -458,7 +459,12 @@ impl Tab { new_pids: Vec, tab_index: usize, client_id: ClientId, - ) { + ) -> Result<()> { + let err_context = || { + format!( + "failed to apply layout {layout:#?} in tab {tab_index} for client id {client_id}" + ) + }; if self.tiled_panes.has_panes() { log::error!( "Applying a layout to a tab with existing panes - this is not yet supported!" @@ -491,12 +497,17 @@ impl Tab { let pane_title = run.location.to_string(); self.senders .send_to_plugin(PluginInstruction::Load(pid_tx, run, tab_index, client_id)) - .unwrap(); - let pid = pid_rx.recv().unwrap(); + .to_anyhow() + .with_context(err_context)?; + let pid = pid_rx.recv().with_context(err_context)?; let mut new_plugin = PluginPane::new( pid, *position_and_size, - self.senders.to_plugin.as_ref().unwrap().clone(), + self.senders + .to_plugin + .as_ref() + .with_context(err_context)? + .clone(), pane_title, layout.name.clone().unwrap_or_default(), ); @@ -506,7 +517,7 @@ impl Tab { set_focus_pane_id(layout, PaneId::Plugin(pid)); } else { // there are still panes left to fill, use the pids we received in this method - let pid = new_pids.next().unwrap(); // if this crashes it means we got less pids than there are panes in this layout + let pid = new_pids.next().with_context(err_context)?; // if this crashes it means we got less pids than there are panes in this layout let next_terminal_position = self.get_next_terminal_position(); let mut new_pane = TerminalPane::new( *pid, @@ -532,7 +543,7 @@ impl Tab { // fixing this will require a bit of an architecture change self.senders .send_to_pty(PtyInstruction::ClosePane(PaneId::Terminal(*unused_pid))) - .unwrap(); + .with_context(err_context)?; } // FIXME: This is another hack to crop the viewport to fixed-size panes. Once you can have // non-fixed panes that are part of the viewport, get rid of this! @@ -564,8 +575,9 @@ impl Tab { }, } } + Ok(()) } - pub fn update_input_modes(&mut self) { + pub fn update_input_modes(&mut self) -> Result<()> { // this updates all plugins with the client's input mode let mode_infos = self.mode_info.borrow(); for client_id in self.connected_clients.borrow().iter() { @@ -576,10 +588,17 @@ impl Tab { Some(*client_id), Event::ModeUpdate(mode_info.clone()), )) - .unwrap(); + .to_anyhow() + .with_context(|| { + format!( + "failed to update plugins with mode info {:?}", + mode_info.mode + ) + })?; } + Ok(()) } - pub fn add_client(&mut self, client_id: ClientId, mode_info: Option) { + pub fn add_client(&mut self, client_id: ClientId, mode_info: Option) -> Result<()> { let other_clients_exist_in_tab = { !self.connected_clients.borrow().is_empty() }; if other_clients_exist_in_tab { if let Some(first_active_floating_pane_id) = @@ -601,13 +620,17 @@ impl Tab { let mut pane_ids: Vec = self.tiled_panes.pane_ids().copied().collect(); if pane_ids.is_empty() { // no panes here, bye bye - return; + return Ok(()); } - let focus_pane_id = self.focus_pane_id.unwrap_or_else(|| { + let focus_pane_id = if let Some(id) = self.focus_pane_id { + id + } else { pane_ids.sort(); // TODO: make this predictable pane_ids.retain(|p| !self.tiled_panes.panes_to_hide_contains(*p)); - *pane_ids.get(0).unwrap() - }); + *(pane_ids.get(0).with_context(|| { + format!("failed to acquire id of focused pane while adding client {client_id}",) + })?) + }; self.tiled_panes.focus_pane(focus_pane_id, client_id); self.connected_clients.borrow_mut().insert(client_id); self.mode_info.borrow_mut().insert( @@ -616,18 +639,26 @@ impl Tab { ); } self.set_force_render(); - self.update_input_modes(); + self.update_input_modes() + .with_context(|| format!("failed to add client {client_id} to tab")) } + pub fn change_mode_info(&mut self, mode_info: ModeInfo, client_id: ClientId) { self.mode_info.borrow_mut().insert(client_id, mode_info); } - pub fn add_multiple_clients(&mut self, client_ids_to_mode_infos: Vec<(ClientId, ModeInfo)>) { + + pub fn add_multiple_clients( + &mut self, + client_ids_to_mode_infos: Vec<(ClientId, ModeInfo)>, + ) -> Result<()> { for (client_id, client_mode_info) in client_ids_to_mode_infos { - self.add_client(client_id, None); + self.add_client(client_id, None) + .context("failed to add clients")?; self.mode_info .borrow_mut() .insert(client_id, client_mode_info); } + Ok(()) } pub fn remove_client(&mut self, client_id: ClientId) { self.focus_pane_id = None; @@ -659,16 +690,18 @@ impl Tab { pub fn has_no_connected_clients(&self) -> bool { self.connected_clients.borrow().is_empty() } - pub fn toggle_pane_embed_or_floating(&mut self, client_id: ClientId) { + pub fn toggle_pane_embed_or_floating(&mut self, client_id: ClientId) -> Result<()> { if self.tiled_panes.fullscreen_is_active() { self.tiled_panes.unset_fullscreen(); } if self.floating_panes.panes_are_visible() { if let Some(focused_floating_pane_id) = self.floating_panes.active_pane_id(client_id) { if self.tiled_panes.has_room_for_new_pane() { - // this unwrap is safe because floating panes should not be visible if there are no floating panes - let floating_pane_to_embed = - self.close_pane(focused_floating_pane_id, true).unwrap(); + let floating_pane_to_embed = self + .close_pane(focused_floating_pane_id, true) + .with_context(|| format!( + "failed to find floating pane (ID: {focused_floating_pane_id:?}) to embed for client {client_id}", + ))?; self.tiled_panes .insert_pane(focused_floating_pane_id, floating_pane_to_embed); self.should_clear_display_before_rendering = true; @@ -681,7 +714,7 @@ impl Tab { if let Some(new_pane_geom) = self.floating_panes.find_room_for_new_pane() { if self.get_selectable_tiled_panes().count() <= 1 { // don't close the only pane on screen... - return; + return Ok(()); } if let Some(mut embedded_pane_to_float) = self.close_pane(focused_pane_id, true) { embedded_pane_to_float.set_geom(new_pane_geom); @@ -694,12 +727,13 @@ impl Tab { } } } + Ok(()) } pub fn toggle_floating_panes( &mut self, client_id: ClientId, default_shell: Option, - ) { + ) -> Result<()> { if self.floating_panes.panes_are_visible() { self.floating_panes.toggle_show_panes(false); self.set_force_render(); @@ -727,23 +761,30 @@ impl Tab { default_shell, ClientOrTabIndex::ClientId(client_id), ); - self.senders.send_to_pty(instruction).unwrap(); + self.senders.send_to_pty(instruction).with_context(|| { + format!("failed to open a floating pane for client {client_id}") + })?; }, } self.floating_panes.set_force_render(); } self.set_force_render(); + Ok(()) } + pub fn show_floating_panes(&mut self) { self.floating_panes.toggle_show_panes(true); self.set_force_render(); } + pub fn hide_floating_panes(&mut self) { self.floating_panes.toggle_show_panes(false); self.set_force_render(); } - pub fn new_pane(&mut self, pid: PaneId, client_id: Option) { - self.close_down_to_max_terminals(); + + pub fn new_pane(&mut self, pid: PaneId, client_id: Option) -> Result<()> { + self.close_down_to_max_terminals() + .with_context(|| format!("failed to create new pane with id {pid:?}"))?; if self.floating_panes.panes_are_visible() { if let Some(new_pane_geom) = self.floating_panes.find_room_for_new_pane() { let next_terminal_position = self.get_next_terminal_position(); @@ -793,8 +834,9 @@ impl Tab { } } } + Ok(()) } - pub fn suppress_active_pane(&mut self, pid: PaneId, client_id: ClientId) { + pub fn suppress_active_pane(&mut self, pid: PaneId, client_id: ClientId) -> Result<()> { // this method creates a new pane from pid and replaces it with the active pane // the active pane is then suppressed (hidden and not rendered) until the current // created pane is closed, in which case it will be replaced back by it @@ -824,7 +866,11 @@ impl Tab { Some(replaced_pane) => { self.suppressed_panes .insert(PaneId::Terminal(pid), replaced_pane); - let current_active_pane = self.get_active_pane(client_id).unwrap(); // this will be the newly replaced pane we just created + // this will be the newly replaced pane we just created + let current_active_pane = + self.get_active_pane(client_id).with_context(|| { + format!("failed to suppress active pane for client {client_id}") + })?; resize_pty!(current_active_pane, self.os_api); }, None => { @@ -836,12 +882,18 @@ impl Tab { // TBD, currently unsupported }, } + Ok(()) } - pub fn horizontal_split(&mut self, pid: PaneId, client_id: ClientId) { + + pub fn horizontal_split(&mut self, pid: PaneId, client_id: ClientId) -> Result<()> { + let err_context = + || format!("failed to split pane {pid:?} horizontally for client {client_id}"); + if self.floating_panes.panes_are_visible() { - return; + return Ok(()); } - self.close_down_to_max_terminals(); + self.close_down_to_max_terminals() + .with_context(err_context)?; if self.tiled_panes.fullscreen_is_active() { self.toggle_active_pane_fullscreen(client_id); } @@ -866,12 +918,18 @@ impl Tab { self.tiled_panes.focus_pane(pid, client_id); } } + Ok(()) } - pub fn vertical_split(&mut self, pid: PaneId, client_id: ClientId) { + + pub fn vertical_split(&mut self, pid: PaneId, client_id: ClientId) -> Result<()> { + let err_context = + || format!("failed to split pane {pid:?} vertically for client {client_id}"); + if self.floating_panes.panes_are_visible() { - return; + return Ok(()); } - self.close_down_to_max_terminals(); + self.close_down_to_max_terminals() + .with_context(err_context)?; if self.tiled_panes.fullscreen_is_active() { self.toggle_active_pane_fullscreen(client_id); } @@ -896,7 +954,9 @@ impl Tab { self.tiled_panes.focus_pane(pid, client_id); } } + Ok(()) } + pub fn get_active_pane(&self, client_id: ClientId) -> Option<&dyn Pane> { self.get_active_pane_id(client_id).and_then(|ap| { if self.floating_panes.panes_are_visible() { @@ -947,7 +1007,9 @@ impl Tab { .values() .any(|s_p| s_p.pid() == PaneId::Terminal(pid)) } - pub fn handle_pty_bytes(&mut self, pid: RawFd, bytes: VteBytes) { + pub fn handle_pty_bytes(&mut self, pid: RawFd, bytes: VteBytes) -> Result<()> { + let err_context = || format!("failed to handle pty bytes from fd {pid}"); + if let Some(terminal_output) = self .tiled_panes .get_pane_mut(PaneId::Terminal(pid)) @@ -965,23 +1027,30 @@ impl Tab { // Reset scroll - and process all pending events for this pane if evs.len() >= MAX_PENDING_VTE_EVENTS { terminal_output.clear_scroll(); - self.process_pending_vte_events(pid); + self.process_pending_vte_events(pid) + .with_context(err_context)?; } } - return; + return Ok(()); } } - self.process_pty_bytes(pid, bytes); + self.process_pty_bytes(pid, bytes).with_context(err_context) } - pub fn process_pending_vte_events(&mut self, pid: RawFd) { + + pub fn process_pending_vte_events(&mut self, pid: RawFd) -> Result<()> { if let Some(pending_vte_events) = self.pending_vte_events.get_mut(&pid) { let vte_events: Vec = pending_vte_events.drain(..).collect(); for vte_event in vte_events { - self.process_pty_bytes(pid, vte_event); + self.process_pty_bytes(pid, vte_event) + .context("failed to process pending vte events")?; } } + Ok(()) } - fn process_pty_bytes(&mut self, pid: RawFd, bytes: VteBytes) { + + fn process_pty_bytes(&mut self, pid: RawFd, bytes: VteBytes) -> Result<()> { + let err_context = || format!("failed to process pty bytes from pid {pid}"); + if let Some(terminal_output) = self .tiled_panes .get_pane_mut(PaneId::Terminal(pid)) @@ -996,45 +1065,88 @@ impl Tab { let messages_to_pty = terminal_output.drain_messages_to_pty(); let clipboard_update = terminal_output.drain_clipboard_update(); for message in messages_to_pty { - self.write_to_pane_id(message, PaneId::Terminal(pid)); + self.write_to_pane_id(message, PaneId::Terminal(pid)) + .with_context(err_context)?; } if let Some(string) = clipboard_update { - self.write_selection_to_clipboard(&string); + self.write_selection_to_clipboard(&string) + .with_context(err_context)?; } } + Ok(()) } - pub fn write_to_terminals_on_current_tab(&mut self, input_bytes: Vec) { + + pub fn write_to_terminals_on_current_tab(&mut self, input_bytes: Vec) -> Result<()> { let pane_ids = self.get_static_and_floating_pane_ids(); - pane_ids.iter().for_each(|&pane_id| { - self.write_to_pane_id(input_bytes.clone(), pane_id); - }); + for pane_id in pane_ids { + self.write_to_pane_id(input_bytes.clone(), pane_id) + .context("failed to write to terminals on current tab")?; + } + Ok(()) } - pub fn write_to_active_terminal(&mut self, input_bytes: Vec, client_id: ClientId) { + + pub fn write_to_active_terminal( + &mut self, + input_bytes: Vec, + client_id: ClientId, + ) -> Result<()> { + let err_context = || { + format!( + "failed to write to active terminal for client {client_id} - msg: {input_bytes:?}" + ) + }; + self.clear_search(client_id); // this is an inexpensive operation if empty, if we need more such cleanups we should consider moving this and the rest to some sort of cleanup method let pane_id = if self.floating_panes.panes_are_visible() { self.floating_panes .get_active_pane_id(client_id) - .unwrap_or_else(|| self.tiled_panes.get_active_pane_id(client_id).unwrap()) + .or_else(|| self.tiled_panes.get_active_pane_id(client_id)) + .ok_or_else(|| { + anyhow!(format!( + "failed to find active pane id for client {client_id}" + )) + }) + .with_context(err_context)? } else { - self.tiled_panes.get_active_pane_id(client_id).unwrap() + self.tiled_panes + .get_active_pane_id(client_id) + .with_context(err_context)? }; - self.write_to_pane_id(input_bytes, pane_id); + // Can't use 'err_context' here since it borrows 'input_bytes' + self.write_to_pane_id(input_bytes, pane_id) + .with_context(|| format!("failed to write to active terminal for client {client_id}")) } - pub fn write_to_terminal_at(&mut self, input_bytes: Vec, position: &Position) { + + pub fn write_to_terminal_at( + &mut self, + input_bytes: Vec, + position: &Position, + ) -> Result<()> { + let err_context = || format!("failed to write to terminal at position {position:?}"); + if self.floating_panes.panes_are_visible() { let pane_id = self.floating_panes.get_pane_id_at(position, false); if let Some(pane_id) = pane_id { - self.write_to_pane_id(input_bytes, pane_id); - return; + return self + .write_to_pane_id(input_bytes, pane_id) + .with_context(err_context); } } - let pane_id = self.get_pane_id_at(position, false); + let pane_id = self + .get_pane_id_at(position, false) + .with_context(err_context)?; if let Some(pane_id) = pane_id { - self.write_to_pane_id(input_bytes, pane_id); + return self + .write_to_pane_id(input_bytes, pane_id) + .with_context(err_context); } + Ok(()) } - pub fn write_to_pane_id(&mut self, input_bytes: Vec, pane_id: PaneId) { + + pub fn write_to_pane_id(&mut self, input_bytes: Vec, pane_id: PaneId) -> Result<()> { + let err_context = || format!("failed to write to pane with id {pane_id:?}"); + match pane_id { PaneId::Terminal(active_terminal_id) => { let active_terminal = self @@ -1042,7 +1154,8 @@ impl Tab { .get(&pane_id) .or_else(|| self.tiled_panes.get_pane(pane_id)) .or_else(|| self.suppressed_panes.get(&pane_id)) - .unwrap(); + .ok_or_else(|| anyhow!(format!("failed to find pane with id {pane_id:?}"))) + .with_context(err_context)?; let adjusted_input = active_terminal.adjust_input_to_terminal(input_bytes); self.senders @@ -1050,16 +1163,18 @@ impl Tab { adjusted_input, active_terminal_id, )) - .unwrap(); + .with_context(err_context)?; }, PaneId::Plugin(pid) => { for key in parse_keys(&input_bytes) { self.senders .send_to_plugin(PluginInstruction::Update(Some(pid), None, Event::Key(key))) - .unwrap() + .to_anyhow() + .with_context(err_context)?; } }, } + Ok(()) } pub fn get_active_terminal_cursor_position( &self, @@ -1124,7 +1239,7 @@ impl Tab { active_pane.set_should_render(true); } } - fn update_active_panes_in_pty_thread(&self) { + fn update_active_panes_in_pty_thread(&self) -> Result<()> { // this is a bit hacky and we should ideally not keep this state in two different places at // some point let connected_clients: Vec = @@ -1135,16 +1250,21 @@ impl Tab { self.get_active_pane_id(client_id), client_id, )) - .unwrap(); + .with_context(|| format!("failed to update active pane for client {client_id}"))?; } + Ok(()) } - pub fn render(&mut self, output: &mut Output, overlay: Option) { + + pub fn render(&mut self, output: &mut Output, overlay: Option) -> Result<()> { + let err_context = || "failed to render tab".to_string(); + let connected_clients: HashSet = { self.connected_clients.borrow().iter().copied().collect() }; if connected_clients.is_empty() || !self.tiled_panes.has_active_panes() { - return; + return Ok(()); } - self.update_active_panes_in_pty_thread(); + self.update_active_panes_in_pty_thread() + .with_context(err_context)?; let floating_panes_stack = self.floating_panes.stack(); output.add_clients( @@ -1169,7 +1289,9 @@ impl Tab { } self.render_cursor(output); + Ok(()) } + fn hide_cursor_and_clear_display_as_needed(&mut self, output: &mut Output) { let hide_cursor = "\u{1b}[?25l"; let connected_clients: Vec = @@ -1489,16 +1611,17 @@ impl Tab { self.tiled_panes.move_active_pane_left(client_id); } } - fn close_down_to_max_terminals(&mut self) { + fn close_down_to_max_terminals(&mut self) -> Result<()> { if let Some(max_panes) = self.max_panes { let terminals = self.get_tiled_pane_ids(); for &pid in terminals.iter().skip(max_panes - 1) { self.senders .send_to_pty(PtyInstruction::ClosePane(pid)) - .unwrap(); + .context("failed to close down to max terminals")?; self.close_pane(pid, false); } } + Ok(()) } pub fn get_tiled_pane_ids(&self) -> Vec { self.get_tiled_panes().map(|(&pid, _)| pid).collect() @@ -1594,22 +1717,27 @@ impl Tab { replaced_pane }) } - pub fn close_focused_pane(&mut self, client_id: ClientId) { + pub fn close_focused_pane(&mut self, client_id: ClientId) -> Result<()> { + let err_context = |pane_id| { + format!("failed to close focused pane (ID {pane_id:?}) for client {client_id}") + }; + if self.floating_panes.panes_are_visible() { if let Some(active_floating_pane_id) = self.floating_panes.active_pane_id(client_id) { self.close_pane(active_floating_pane_id, false); self.senders .send_to_pty(PtyInstruction::ClosePane(active_floating_pane_id)) - .unwrap(); - return; + .with_context(|| err_context(active_floating_pane_id))?; + return Ok(()); } } if let Some(active_pane_id) = self.tiled_panes.get_active_pane_id(client_id) { self.close_pane(active_pane_id, false); self.senders .send_to_pty(PtyInstruction::ClosePane(active_pane_id)) - .unwrap(); + .with_context(|| err_context(active_pane_id))?; } + Ok(()) } pub fn dump_active_terminal_screen(&mut self, file: Option, client_id: ClientId) { if let Some(active_pane) = self.get_active_pane_or_floating_pane_mut(client_id) { @@ -1617,7 +1745,7 @@ impl Tab { self.os_api.write_to_file(dump, file); } } - pub fn edit_scrollback(&mut self, client_id: ClientId) { + pub fn edit_scrollback(&mut self, client_id: ClientId) -> Result<()> { let mut file = temp_dir(); file.push(format!("{}.dump", Uuid::new_v4())); self.dump_active_terminal_screen(Some(String::from(file.to_string_lossy())), client_id); @@ -1630,23 +1758,29 @@ impl Tab { line_number, client_id, )) - .unwrap(); + .with_context(|| format!("failed to edit scrollback for client {client_id}")) } pub fn scroll_active_terminal_up(&mut self, client_id: ClientId) { if let Some(active_pane) = self.get_active_pane_or_floating_pane_mut(client_id) { active_pane.scroll_up(1, client_id); } } - pub fn scroll_active_terminal_down(&mut self, client_id: ClientId) { + + pub fn scroll_active_terminal_down(&mut self, client_id: ClientId) -> Result<()> { + let err_context = || format!("failed to scroll down active pane for client {client_id}"); + if let Some(active_pane) = self.get_active_pane_or_floating_pane_mut(client_id) { active_pane.scroll_down(1, client_id); if !active_pane.is_scrolled() { if let PaneId::Terminal(raw_fd) = active_pane.pid() { - self.process_pending_vte_events(raw_fd); + self.process_pending_vte_events(raw_fd) + .with_context(err_context)?; } } } + Ok(()) } + pub fn scroll_active_terminal_up_page(&mut self, client_id: ClientId) { if let Some(active_pane) = self.get_active_pane_or_floating_pane_mut(client_id) { // prevent overflow when row == 0 @@ -1654,17 +1788,24 @@ impl Tab { active_pane.scroll_up(scroll_rows, client_id); } } - pub fn scroll_active_terminal_down_page(&mut self, client_id: ClientId) { + + pub fn scroll_active_terminal_down_page(&mut self, client_id: ClientId) -> Result<()> { + let err_context = + || format!("failed to scroll down one page in active pane for client {client_id}"); + if let Some(active_pane) = self.get_active_pane_or_floating_pane_mut(client_id) { let scroll_rows = active_pane.get_content_rows(); active_pane.scroll_down(scroll_rows, client_id); if !active_pane.is_scrolled() { if let PaneId::Terminal(raw_fd) = active_pane.pid() { - self.process_pending_vte_events(raw_fd); + self.process_pending_vte_events(raw_fd) + .with_context(err_context)?; } } } + Ok(()) } + pub fn scroll_active_terminal_up_half_page(&mut self, client_id: ClientId) { if let Some(active_pane) = self.get_active_pane_or_floating_pane_mut(client_id) { // prevent overflow when row == 0 @@ -1672,116 +1813,183 @@ impl Tab { active_pane.scroll_up(scroll_rows, client_id); } } - pub fn scroll_active_terminal_down_half_page(&mut self, client_id: ClientId) { + + pub fn scroll_active_terminal_down_half_page(&mut self, client_id: ClientId) -> Result<()> { + let err_context = + || format!("failed to scroll down half a page in active pane for client {client_id}"); + if let Some(active_pane) = self.get_active_pane_or_floating_pane_mut(client_id) { let scroll_rows = (active_pane.rows().max(1) - 1) / 2; active_pane.scroll_down(scroll_rows, client_id); if !active_pane.is_scrolled() { if let PaneId::Terminal(raw_fd) = active_pane.pid() { - self.process_pending_vte_events(raw_fd); + self.process_pending_vte_events(raw_fd) + .with_context(err_context)?; } } } + Ok(()) } - pub fn scroll_active_terminal_to_bottom(&mut self, client_id: ClientId) { + + pub fn scroll_active_terminal_to_bottom(&mut self, client_id: ClientId) -> Result<()> { + let err_context = + || format!("failed to scroll to bottom in active pane for client {client_id}"); + if let Some(active_pane) = self.get_active_pane_or_floating_pane_mut(client_id) { active_pane.clear_scroll(); if !active_pane.is_scrolled() { if let PaneId::Terminal(raw_fd) = active_pane.pid() { - self.process_pending_vte_events(raw_fd); + self.process_pending_vte_events(raw_fd) + .with_context(err_context)?; } } } + Ok(()) } - pub fn clear_active_terminal_scroll(&mut self, client_id: ClientId) { + + pub fn clear_active_terminal_scroll(&mut self, client_id: ClientId) -> Result<()> { // TODO: is this a thing? + let err_context = + || format!("failed to clear scroll in active pane for client {client_id}"); + if let Some(active_pane) = self.get_active_pane_or_floating_pane_mut(client_id) { active_pane.clear_scroll(); if !active_pane.is_scrolled() { if let PaneId::Terminal(raw_fd) = active_pane.pid() { - self.process_pending_vte_events(raw_fd); + self.process_pending_vte_events(raw_fd) + .with_context(err_context)?; } } } + Ok(()) } - pub fn handle_scrollwheel_up(&mut self, point: &Position, lines: usize, client_id: ClientId) { - if let Some(pane) = self.get_pane_at(point, false) { + + pub fn handle_scrollwheel_up( + &mut self, + point: &Position, + lines: usize, + client_id: ClientId, + ) -> Result<()> { + let err_context = || { + format!("failed to handle scrollwheel up at position {point:?} for client {client_id}") + }; + + if let Some(pane) = self.get_pane_at(point, false).with_context(err_context)? { let relative_position = pane.relative_position(point); if let Some(mouse_event) = pane.mouse_scroll_up(&relative_position) { - self.write_to_terminal_at(mouse_event.into_bytes(), point); + self.write_to_terminal_at(mouse_event.into_bytes(), point) + .with_context(err_context)?; } else if pane.is_alternate_mode_active() { // faux scrolling, send UP n times // do n separate writes to make sure the sequence gets adjusted for cursor keys mode for _ in 0..lines { self.write_to_terminal_at("\u{1b}[A".as_bytes().to_owned(), point) + .with_context(err_context)?; } } else { pane.scroll_up(lines, client_id); } } + Ok(()) } - pub fn handle_scrollwheel_down(&mut self, point: &Position, lines: usize, client_id: ClientId) { - if let Some(pane) = self.get_pane_at(point, false) { + + pub fn handle_scrollwheel_down( + &mut self, + point: &Position, + lines: usize, + client_id: ClientId, + ) -> Result<()> { + let err_context = || { + format!( + "failed to handle scrollwheel down at position {point:?} for client {client_id}" + ) + }; + + if let Some(pane) = self.get_pane_at(point, false).with_context(err_context)? { let relative_position = pane.relative_position(point); if let Some(mouse_event) = pane.mouse_scroll_down(&relative_position) { - self.write_to_terminal_at(mouse_event.into_bytes(), point); + self.write_to_terminal_at(mouse_event.into_bytes(), point) + .with_context(err_context)?; } else if pane.is_alternate_mode_active() { // faux scrolling, send DOWN n times // do n separate writes to make sure the sequence gets adjusted for cursor keys mode for _ in 0..lines { self.write_to_terminal_at("\u{1b}[B".as_bytes().to_owned(), point) + .with_context(err_context)?; } } else { pane.scroll_down(lines, client_id); if !pane.is_scrolled() { if let PaneId::Terminal(pid) = pane.pid() { - self.process_pending_vte_events(pid); + self.process_pending_vte_events(pid) + .with_context(err_context)?; } } } } + Ok(()) } + fn get_pane_at( &mut self, point: &Position, search_selectable: bool, - ) -> Option<&mut Box> { + ) -> Result>> { if self.floating_panes.panes_are_visible() { if let Some(pane_id) = self.floating_panes.get_pane_id_at(point, search_selectable) { - return self.floating_panes.get_pane_mut(pane_id); + return Ok(self.floating_panes.get_pane_mut(pane_id)); } } - if let Some(pane_id) = self.get_pane_id_at(point, search_selectable) { - self.tiled_panes.get_pane_mut(pane_id) + if let Some(pane_id) = self + .get_pane_id_at(point, search_selectable) + .with_context(|| format!("failed to get pane at position {point:?}"))? + { + Ok(self.tiled_panes.get_pane_mut(pane_id)) } else { - None + Ok(None) } } - fn get_pane_id_at(&self, point: &Position, search_selectable: bool) -> Option { - if self.tiled_panes.fullscreen_is_active() && self.is_position_inside_viewport(point) { - let first_client_id = { - self.connected_clients - .borrow() - .iter() - .copied() - .next() - .unwrap() - }; // TODO: instead of doing this, record the pane that is in fullscreen - return self.tiled_panes.get_active_pane_id(first_client_id); + fn get_pane_id_at(&self, point: &Position, search_selectable: bool) -> Result> { + let err_context = || format!("failed to get id of pane at position {point:?}"); + + if self.tiled_panes.fullscreen_is_active() + && self + .is_position_inside_viewport(point) + .with_context(err_context)? + { + // TODO: instead of doing this, record the pane that is in fullscreen + let first_client_id = self + .connected_clients + .borrow() + .iter() + .copied() + .next() + .with_context(err_context)?; + return Ok(self.tiled_panes.get_active_pane_id(first_client_id)); } if search_selectable { - self.get_selectable_tiled_panes() + Ok(self + .get_selectable_tiled_panes() .find(|(_, p)| p.contains(point)) - .map(|(&id, _)| id) + .map(|(&id, _)| id)) } else { - self.get_tiled_panes() + Ok(self + .get_tiled_panes() .find(|(_, p)| p.contains(point)) - .map(|(&id, _)| id) + .map(|(&id, _)| id)) } } - pub fn handle_left_click(&mut self, position: &Position, client_id: ClientId) { - self.focus_pane_at(position, client_id); + + pub fn handle_left_click(&mut self, position: &Position, client_id: ClientId) -> Result<()> { + let err_context = || { + format!( + "failed to handle mouse left click at position {position:?} for client {client_id}" + ) + }; + + self.focus_pane_at(position, client_id) + .with_context(err_context)?; let search_selectable = false; if self.floating_panes.panes_are_visible() @@ -1790,14 +1998,18 @@ impl Tab { .move_pane_with_mouse(*position, search_selectable) { self.set_force_render(); - return; + return Ok(()); } - if let Some(pane) = self.get_pane_at(position, false) { + if let Some(pane) = self + .get_pane_at(position, false) + .with_context(err_context)? + { let relative_position = pane.relative_position(position); if let Some(mouse_event) = pane.mouse_left_click(&relative_position, false) { if !pane.position_is_on_frame(position) { - self.write_to_active_terminal(mouse_event.into_bytes(), client_id); + self.write_to_active_terminal(mouse_event.into_bytes(), client_id) + .with_context(err_context)?; } } else { pane.start_selection(&relative_position, client_id); @@ -1806,42 +2018,73 @@ impl Tab { } } }; + Ok(()) } - pub fn handle_right_click(&mut self, position: &Position, client_id: ClientId) { - self.focus_pane_at(position, client_id); - if let Some(pane) = self.get_pane_at(position, false) { + pub fn handle_right_click(&mut self, position: &Position, client_id: ClientId) -> Result<()> { + let err_context = || { + format!( + "failed to handle mouse right click at position {position:?} for client {client_id}" + ) + }; + + self.focus_pane_at(position, client_id) + .with_context(err_context)?; + + if let Some(pane) = self + .get_pane_at(position, false) + .with_context(err_context)? + { let relative_position = pane.relative_position(position); if let Some(mouse_event) = pane.mouse_right_click(&relative_position, false) { if !pane.position_is_on_frame(position) { - self.write_to_active_terminal(mouse_event.into_bytes(), client_id); + self.write_to_active_terminal(mouse_event.into_bytes(), client_id) + .with_context(err_context)?; } } else { pane.handle_right_click(&relative_position, client_id); } }; + Ok(()) } - pub fn handle_middle_click(&mut self, position: &Position, client_id: ClientId) { - self.focus_pane_at(position, client_id); - if let Some(pane) = self.get_pane_at(position, false) { + pub fn handle_middle_click(&mut self, position: &Position, client_id: ClientId) -> Result<()> { + let err_context = || { + format!( + "failed to handle mouse middle click at position {position:?} for client {client_id}" + ) + }; + + self.focus_pane_at(position, client_id) + .with_context(err_context)?; + + if let Some(pane) = self + .get_pane_at(position, false) + .with_context(err_context)? + { let relative_position = pane.relative_position(position); if let Some(mouse_event) = pane.mouse_middle_click(&relative_position, false) { if !pane.position_is_on_frame(position) { - self.write_to_active_terminal(mouse_event.into_bytes(), client_id); + self.write_to_active_terminal(mouse_event.into_bytes(), client_id) + .with_context(err_context)?; } } }; + Ok(()) } - fn focus_pane_at(&mut self, point: &Position, client_id: ClientId) { + + fn focus_pane_at(&mut self, point: &Position, client_id: ClientId) -> Result<()> { + let err_context = + || format!("failed to focus pane at position {point:?} for client {client_id}"); + if self.floating_panes.panes_are_visible() { if let Some(clicked_pane) = self.floating_panes.get_pane_id_at(point, true) { self.floating_panes.focus_pane(clicked_pane, client_id); self.set_pane_active_at(clicked_pane); - return; + return Ok(()); } } - if let Some(clicked_pane) = self.get_pane_id_at(point, true) { + if let Some(clicked_pane) = self.get_pane_id_at(point, true).with_context(err_context)? { self.tiled_panes.focus_pane(clicked_pane, client_id); self.set_pane_active_at(clicked_pane); if self.floating_panes.panes_are_visible() { @@ -1849,8 +2092,18 @@ impl Tab { self.set_force_render(); } } + Ok(()) } - pub fn handle_right_mouse_release(&mut self, position: &Position, client_id: ClientId) { + + pub fn handle_right_mouse_release( + &mut self, + position: &Position, + client_id: ClientId, + ) -> Result<()> { + let err_context = || { + format!("failed to handle right mouse release at position {position:?} for client {client_id}") + }; + self.last_mouse_hold_position = None; let active_pane = self.get_active_pane_or_floating_pane_mut(client_id); if let Some(active_pane) = active_pane { @@ -1868,11 +2121,22 @@ impl Tab { ); if let Some(mouse_event) = active_pane.mouse_right_click_release(&relative_position) { - self.write_to_active_terminal(mouse_event.into_bytes(), client_id); + self.write_to_active_terminal(mouse_event.into_bytes(), client_id) + .with_context(err_context)?; } } + Ok(()) } - pub fn handle_middle_mouse_release(&mut self, position: &Position, client_id: ClientId) { + + pub fn handle_middle_mouse_release( + &mut self, + position: &Position, + client_id: ClientId, + ) -> Result<()> { + let err_context = || { + format!("failed to handle middle mouse release at position {position:?} for client {client_id}") + }; + self.last_mouse_hold_position = None; let active_pane = self.get_active_pane_or_floating_pane_mut(client_id); if let Some(active_pane) = active_pane { @@ -1890,18 +2154,29 @@ impl Tab { ); if let Some(mouse_event) = active_pane.mouse_middle_click_release(&relative_position) { - self.write_to_active_terminal(mouse_event.into_bytes(), client_id); + self.write_to_active_terminal(mouse_event.into_bytes(), client_id) + .with_context(err_context)?; } } + Ok(()) } - pub fn handle_left_mouse_release(&mut self, position: &Position, client_id: ClientId) { + + pub fn handle_left_mouse_release( + &mut self, + position: &Position, + client_id: ClientId, + ) -> Result<()> { + let err_context = || { + format!("failed to handle left mouse release at position {position:?} for client {client_id}") + }; + self.last_mouse_hold_position = None; if self.floating_panes.panes_are_visible() && self.floating_panes.pane_is_being_moved_with_mouse() { self.floating_panes.stop_moving_pane_with_mouse(*position); - return; + return Ok(()); } // read these here to avoid use of borrowed `*self`, since we are holding active_pane @@ -1924,7 +2199,8 @@ impl Tab { ); if let Some(mouse_event) = active_pane.mouse_left_click_release(&relative_position) { - self.write_to_active_terminal(mouse_event.into_bytes(), client_id); + self.write_to_active_terminal(mouse_event.into_bytes(), client_id) + .with_context(err_context)?; } else { let relative_position = active_pane.relative_position(position); if let PaneId::Terminal(_) = active_pane.pid() { @@ -1934,7 +2210,8 @@ impl Tab { active_pane.reset_selection(); if let Some(selected_text) = selected_text { - self.write_selection_to_clipboard(&selected_text); + self.write_selection_to_clipboard(&selected_text) + .with_context(err_context)?; } } } else { @@ -1944,12 +2221,18 @@ impl Tab { self.selecting_with_mouse = false; } } + Ok(()) } + pub fn handle_mouse_hold_left( &mut self, position_on_screen: &Position, client_id: ClientId, - ) -> bool { + ) -> Result { + let err_context = || { + format!("failed to handle left mouse hold at position {position_on_screen:?} for client {client_id}") + }; + // return value indicates whether we should trigger a render // determine if event is repeated to enable smooth scrolling let is_repeated = if let Some(last_position) = self.last_mouse_hold_position { @@ -1968,8 +2251,8 @@ impl Tab { .move_pane_with_mouse(*position_on_screen, search_selectable) { self.set_force_render(); - return !is_repeated; // we don't need to re-render in this case if the pane did not move - // return; + return Ok(!is_repeated); // we don't need to re-render in this case if the pane did not move + // return; } let selecting = self.selecting_with_mouse; @@ -1991,21 +2274,27 @@ impl Tab { .min(active_pane.get_content_rows() as isize), ); if let Some(mouse_event) = active_pane.mouse_left_click(&relative_position, true) { - self.write_to_active_terminal(mouse_event.into_bytes(), client_id); - return true; // we need to re-render in this case so the selection disappears + self.write_to_active_terminal(mouse_event.into_bytes(), client_id) + .with_context(err_context)?; + return Ok(true); // we need to re-render in this case so the selection disappears } } else if selecting { active_pane.update_selection(&relative_position, client_id); - return true; // we need to re-render in this case so the selection is updated + return Ok(true); // we need to re-render in this case so the selection is updated } } - false // we shouldn't even get here, but might as well not needlessly render if we do + Ok(false) // we shouldn't even get here, but might as well not needlessly render if we do } + pub fn handle_mouse_hold_right( &mut self, position_on_screen: &Position, client_id: ClientId, - ) -> bool { + ) -> Result { + let err_context = || { + format!("failed to handle left mouse hold at position {position_on_screen:?} for client {client_id}") + }; + // return value indicates whether we should trigger a render // determine if event is repeated to enable smooth scrolling let is_repeated = if let Some(last_position) = self.last_mouse_hold_position { @@ -2032,18 +2321,24 @@ impl Tab { .min(active_pane.get_content_rows() as isize), ); if let Some(mouse_event) = active_pane.mouse_right_click(&relative_position, true) { - self.write_to_active_terminal(mouse_event.into_bytes(), client_id); - return true; // we need to re-render in this case so the selection disappears + self.write_to_active_terminal(mouse_event.into_bytes(), client_id) + .with_context(err_context)?; + return Ok(true); // we need to re-render in this case so the selection disappears } } } - false // we shouldn't even get here, but might as well not needlessly render if we do + Ok(false) // we shouldn't even get here, but might as well not needlessly render if we do } + pub fn handle_mouse_hold_middle( &mut self, position_on_screen: &Position, client_id: ClientId, - ) -> bool { + ) -> Result { + let err_context = || { + format!("failed to handle left mouse hold at position {position_on_screen:?} for client {client_id}") + }; + // return value indicates whether we should trigger a render // determine if event is repeated to enable smooth scrolling let is_repeated = if let Some(last_position) = self.last_mouse_hold_position { @@ -2071,31 +2366,40 @@ impl Tab { ); if let Some(mouse_event) = active_pane.mouse_middle_click(&relative_position, true) { - self.write_to_active_terminal(mouse_event.into_bytes(), client_id); - return true; // we need to re-render in this case so the selection disappears + self.write_to_active_terminal(mouse_event.into_bytes(), client_id) + .with_context(err_context)?; + return Ok(true); // we need to re-render in this case so the selection disappears } } } - false // we shouldn't even get here, but might as well not needlessly render if we do + Ok(false) // we shouldn't even get here, but might as well not needlessly render if we do } - pub fn copy_selection(&self, client_id: ClientId) { + pub fn copy_selection(&self, client_id: ClientId) -> Result<()> { let selected_text = self .get_active_pane(client_id) .and_then(|p| p.get_selected_text()); if let Some(selected_text) = selected_text { - self.write_selection_to_clipboard(&selected_text); + self.write_selection_to_clipboard(&selected_text) + .with_context(|| { + format!("failed to write selection to clipboard for client {client_id}") + })?; self.senders .send_to_plugin(PluginInstruction::Update( None, None, Event::CopyToClipboard(self.clipboard_provider.as_copy_destination()), )) - .unwrap(); + .to_anyhow() + .with_context(|| { + format!("failed to inform plugins about copy selection for client {client_id}") + }) + .non_fatal(); } + Ok(()) } - fn write_selection_to_clipboard(&self, selection: &str) { + fn write_selection_to_clipboard(&self, selection: &str) -> Result<()> { let mut output = Output::default(); let connected_clients: HashSet = { self.connected_clients.borrow().iter().copied().collect() }; @@ -2110,7 +2414,7 @@ impl Tab { let serialized_output = output.serialize(); self.senders .send_to_server(ServerInstruction::Render(Some(serialized_output))) - .unwrap(); + .context("failed to write selection to clipboard")?; Event::CopyToClipboard(self.clipboard_provider.as_copy_destination()) }, Err(err) => { @@ -2120,7 +2424,11 @@ impl Tab { }; self.senders .send_to_plugin(PluginInstruction::Update(None, None, clipboard_event)) - .unwrap(); + .to_anyhow() + .context("failed to notify plugins about new clipboard event") + .non_fatal(); + + Ok(()) } fn offset_viewport(&mut self, position_and_size: &Viewport) { let mut viewport = self.viewport.borrow_mut(); @@ -2146,7 +2454,7 @@ impl Tab { } } - pub fn visible(&self, visible: bool) { + pub fn visible(&self, visible: bool) -> Result<()> { let pids_in_this_tab = self.tiled_panes.pane_ids().filter_map(|p| match p { PaneId::Plugin(pid) => Some(pid), _ => None, @@ -2158,11 +2466,16 @@ impl Tab { None, Event::Visible(visible), )) - .unwrap(); + .to_anyhow() + .with_context(|| format!("failed to set visibility of tab to {visible}"))?; } + Ok(()) } - pub fn update_active_pane_name(&mut self, buf: Vec, client_id: ClientId) { + pub fn update_active_pane_name(&mut self, buf: Vec, client_id: ClientId) -> Result<()> { + let err_context = + || format!("failed to update name of active pane to '{buf:?}' for client {client_id}"); + if let Some(active_terminal_id) = self.get_active_terminal_id(client_id) { let active_terminal = if self.are_floating_panes_visible() { self.floating_panes @@ -2171,18 +2484,19 @@ impl Tab { self.tiled_panes .get_pane_mut(PaneId::Terminal(active_terminal_id)) } - .unwrap(); + .with_context(err_context)?; // It only allows printable unicode, delete and backspace keys. let is_updatable = buf.iter().all(|u| matches!(u, 0x20..=0x7E | 0x08 | 0x7F)); if is_updatable { - let s = str::from_utf8(&buf).unwrap(); + let s = str::from_utf8(&buf).with_context(err_context)?; active_terminal.update_name(s); } } + Ok(()) } - pub fn undo_active_rename_pane(&mut self, client_id: ClientId) { + pub fn undo_active_rename_pane(&mut self, client_id: ClientId) -> Result<()> { if let Some(active_terminal_id) = self.get_active_terminal_id(client_id) { let active_terminal = if self.are_floating_panes_visible() { self.floating_panes @@ -2191,24 +2505,29 @@ impl Tab { self.tiled_panes .get_pane_mut(PaneId::Terminal(active_terminal_id)) } - .unwrap(); + .with_context(|| { + format!("failed to undo rename of active pane for client {client_id}") + })?; active_terminal.load_pane_name(); } + Ok(()) } - pub fn is_position_inside_viewport(&self, point: &Position) -> bool { + pub fn is_position_inside_viewport(&self, point: &Position) -> Result { let Position { line: Line(line), column: Column(column), } = *point; - let line: usize = line.try_into().unwrap(); + let line: usize = line.try_into().with_context(|| { + format!("failed to determine if position {point:?} is inside viewport") + })?; let viewport = self.viewport.borrow(); - line >= viewport.y + Ok(line >= viewport.y && column >= viewport.x && line <= viewport.y + viewport.rows - && column <= viewport.x + viewport.cols + && column <= viewport.x + viewport.cols) } pub fn set_pane_frames(&mut self, should_set_pane_frames: bool) { @@ -2220,15 +2539,18 @@ impl Tab { self.tiled_panes.panes_to_hide_count() } - pub fn update_search_term(&mut self, buf: Vec, client_id: ClientId) { + pub fn update_search_term(&mut self, buf: Vec, client_id: ClientId) -> Result<()> { if let Some(active_pane) = self.get_active_pane_or_floating_pane_mut(client_id) { // It only allows printable unicode, delete and backspace keys. let is_updatable = buf.iter().all(|u| matches!(u, 0x20..=0x7E | 0x08 | 0x7F)); if is_updatable { - let s = str::from_utf8(&buf).unwrap(); + let s = str::from_utf8(&buf).with_context(|| { + format!("failed to update search term to '{buf:?}' for client {client_id}") + })?; active_pane.update_search_term(s); } } + Ok(()) } pub fn search_down(&mut self, client_id: ClientId) { diff --git a/zellij-server/src/tab/unit/tab_integration_tests.rs b/zellij-server/src/tab/unit/tab_integration_tests.rs index 3b26bc26..632b65b1 100644 --- a/zellij-server/src/tab/unit/tab_integration_tests.rs +++ b/zellij-server/src/tab/unit/tab_integration_tests.rs @@ -212,7 +212,8 @@ fn create_new_tab(size: Size, default_mode: ModeInfo) -> Tab { terminal_emulator_colors, terminal_emulator_color_codes, ); - tab.apply_layout(PaneLayout::default(), vec![1], index, client_id); + tab.apply_layout(PaneLayout::default(), vec![1], index, client_id) + .unwrap(); tab } @@ -267,7 +268,8 @@ fn create_new_tab_with_layout(size: Size, default_mode: ModeInfo, layout: &str) .enumerate() .map(|(i, _)| i as i32) .collect(); - tab.apply_layout(tab_layout, pane_ids, index, client_id); + tab.apply_layout(tab_layout, pane_ids, index, client_id) + .unwrap(); tab } @@ -325,7 +327,8 @@ fn create_new_tab_with_mock_pty_writer( vec![1], index, client_id, - ); + ) + .unwrap(); tab } @@ -379,7 +382,8 @@ fn create_new_tab_with_sixel_support( terminal_emulator_colors, terminal_emulator_color_codes, ); - tab.apply_layout(PaneLayout::default(), vec![1], index, client_id); + tab.apply_layout(PaneLayout::default(), vec![1], index, client_id) + .unwrap(); tab } @@ -487,8 +491,9 @@ fn dump_screen() { file_dumps: map.clone(), }); let new_pane_id = PaneId::Terminal(2); - tab.new_pane(new_pane_id, Some(client_id)); - tab.handle_pty_bytes(2, Vec::from("scratch".as_bytes())); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); + tab.handle_pty_bytes(2, Vec::from("scratch".as_bytes())) + .unwrap(); let file = "/tmp/log.sh"; tab.dump_active_terminal_screen(Some(file.to_string()), client_id); assert_eq!( @@ -508,13 +513,14 @@ fn new_floating_pane() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.render(&mut output, None); + ) + .unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -534,17 +540,18 @@ fn floating_panes_persist_across_toggles() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id, Some(client_id)); - tab.toggle_floating_panes(client_id, None); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); + tab.toggle_floating_panes(client_id, None).unwrap(); // here we send bytes to the pane when it's not visible to make sure they're still handled and // we see them once we toggle the panes back tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.toggle_floating_panes(client_id, None); - tab.render(&mut output, None); + ) + .unwrap(); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -564,14 +571,15 @@ fn toggle_floating_panes_off() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.toggle_floating_panes(client_id, None); - tab.render(&mut output, None); + ) + .unwrap(); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -591,15 +599,16 @@ fn toggle_floating_panes_on() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.toggle_floating_panes(client_id, None); - tab.toggle_floating_panes(client_id, None); - tab.render(&mut output, None); + ) + .unwrap(); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -623,21 +632,26 @@ fn five_new_floating_panes() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); - tab.new_pane(new_pane_id_2, Some(client_id)); - tab.new_pane(new_pane_id_3, Some(client_id)); - tab.new_pane(new_pane_id_4, Some(client_id)); - tab.new_pane(new_pane_id_5, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_2, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_3, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_4, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_5, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())); - tab.render(&mut output, None); + ) + .unwrap(); + tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -657,14 +671,15 @@ fn increase_floating_pane_size() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id_1 = PaneId::Terminal(2); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); + ) + .unwrap(); tab.resize_increase(client_id); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -684,14 +699,15 @@ fn decrease_floating_pane_size() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id_1 = PaneId::Terminal(2); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); + ) + .unwrap(); tab.resize_decrease(client_id); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -711,14 +727,15 @@ fn resize_floating_pane_left() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id_1 = PaneId::Terminal(2); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); + ) + .unwrap(); tab.resize_left(client_id); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -738,14 +755,15 @@ fn resize_floating_pane_right() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id_1 = PaneId::Terminal(2); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); + ) + .unwrap(); tab.resize_right(client_id); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -765,14 +783,15 @@ fn resize_floating_pane_up() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id_1 = PaneId::Terminal(2); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); + ) + .unwrap(); tab.resize_up(client_id); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -792,14 +811,15 @@ fn resize_floating_pane_down() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id_1 = PaneId::Terminal(2); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); + ) + .unwrap(); tab.resize_down(client_id); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -823,22 +843,27 @@ fn move_floating_pane_focus_left() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); - tab.new_pane(new_pane_id_2, Some(client_id)); - tab.new_pane(new_pane_id_3, Some(client_id)); - tab.new_pane(new_pane_id_4, Some(client_id)); - tab.new_pane(new_pane_id_5, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_2, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_3, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_4, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_5, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())); + ) + .unwrap(); + tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); tab.move_focus_left(client_id); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position( output.serialize().get(&client_id).unwrap(), size.rows, @@ -868,23 +893,28 @@ fn move_floating_pane_focus_right() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); - tab.new_pane(new_pane_id_2, Some(client_id)); - tab.new_pane(new_pane_id_3, Some(client_id)); - tab.new_pane(new_pane_id_4, Some(client_id)); - tab.new_pane(new_pane_id_5, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_2, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_3, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_4, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_5, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())); + ) + .unwrap(); + tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); tab.move_focus_left(client_id); tab.move_focus_right(client_id); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position( output.serialize().get(&client_id).unwrap(), size.rows, @@ -914,22 +944,27 @@ fn move_floating_pane_focus_up() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); - tab.new_pane(new_pane_id_2, Some(client_id)); - tab.new_pane(new_pane_id_3, Some(client_id)); - tab.new_pane(new_pane_id_4, Some(client_id)); - tab.new_pane(new_pane_id_5, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_2, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_3, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_4, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_5, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())); + ) + .unwrap(); + tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); tab.move_focus_up(client_id); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position( output.serialize().get(&client_id).unwrap(), size.rows, @@ -959,23 +994,28 @@ fn move_floating_pane_focus_down() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); - tab.new_pane(new_pane_id_2, Some(client_id)); - tab.new_pane(new_pane_id_3, Some(client_id)); - tab.new_pane(new_pane_id_4, Some(client_id)); - tab.new_pane(new_pane_id_5, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_2, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_3, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_4, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_5, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())); + ) + .unwrap(); + tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); tab.move_focus_up(client_id); tab.move_focus_down(client_id); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1005,23 +1045,30 @@ fn move_floating_pane_focus_with_mouse() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); - tab.new_pane(new_pane_id_2, Some(client_id)); - tab.new_pane(new_pane_id_3, Some(client_id)); - tab.new_pane(new_pane_id_4, Some(client_id)); - tab.new_pane(new_pane_id_5, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_2, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_3, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_4, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_5, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_left_click(&Position::new(9, 71), client_id); - tab.handle_left_mouse_release(&Position::new(9, 71), client_id); - tab.render(&mut output, None); + ) + .unwrap(); + tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_left_click(&Position::new(9, 71), client_id) + .unwrap(); + tab.handle_left_mouse_release(&Position::new(9, 71), client_id) + .unwrap(); + tab.render(&mut output, None).unwrap(); let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1051,23 +1098,30 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); - tab.new_pane(new_pane_id_2, Some(client_id)); - tab.new_pane(new_pane_id_3, Some(client_id)); - tab.new_pane(new_pane_id_4, Some(client_id)); - tab.new_pane(new_pane_id_5, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_2, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_3, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_4, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_5, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_left_click(&Position::new(4, 71), client_id); - tab.handle_left_mouse_release(&Position::new(4, 71), client_id); - tab.render(&mut output, None); + ) + .unwrap(); + tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_left_click(&Position::new(4, 71), client_id) + .unwrap(); + tab.handle_left_mouse_release(&Position::new(4, 71), client_id) + .unwrap(); + tab.render(&mut output, None).unwrap(); let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1097,23 +1151,30 @@ fn drag_pane_with_mouse() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); - tab.new_pane(new_pane_id_2, Some(client_id)); - tab.new_pane(new_pane_id_3, Some(client_id)); - tab.new_pane(new_pane_id_4, Some(client_id)); - tab.new_pane(new_pane_id_5, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_2, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_3, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_4, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_5, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_left_click(&Position::new(5, 71), client_id); - tab.handle_left_mouse_release(&Position::new(7, 75), client_id); - tab.render(&mut output, None); + ) + .unwrap(); + tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_left_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_left_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); + tab.render(&mut output, None).unwrap(); let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1143,31 +1204,38 @@ fn mark_text_inside_floating_pane() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); - tab.new_pane(new_pane_id_2, Some(client_id)); - tab.new_pane(new_pane_id_3, Some(client_id)); - tab.new_pane(new_pane_id_4, Some(client_id)); - tab.new_pane(new_pane_id_5, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_2, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_3, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_4, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_5, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_left_click(&Position::new(9, 71), client_id); + ) + .unwrap(); + tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_left_click(&Position::new(9, 71), client_id) + .unwrap(); assert!( tab.selecting_with_mouse, "started selecting with mouse on click" ); - tab.handle_left_mouse_release(&Position::new(8, 50), client_id); + tab.handle_left_mouse_release(&Position::new(8, 50), client_id) + .unwrap(); assert!( !tab.selecting_with_mouse, "stopped selecting with mouse on release" ); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1197,25 +1265,30 @@ fn resize_tab_with_floating_panes() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); - tab.new_pane(new_pane_id_2, Some(client_id)); - tab.new_pane(new_pane_id_3, Some(client_id)); - tab.new_pane(new_pane_id_4, Some(client_id)); - tab.new_pane(new_pane_id_5, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_2, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_3, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_4, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_5, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())); + ) + .unwrap(); + tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); tab.resize_whole_tab(Size { cols: 100, rows: 10, }); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let (snapshot, _cursor_coordinates) = take_snapshot_and_cursor_position( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1240,22 +1313,27 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); - tab.new_pane(new_pane_id_2, Some(client_id)); - tab.new_pane(new_pane_id_3, Some(client_id)); - tab.new_pane(new_pane_id_4, Some(client_id)); - tab.new_pane(new_pane_id_5, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_2, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_3, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_4, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_5, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())); + ) + .unwrap(); + tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); tab.resize_whole_tab(Size { cols: 50, rows: 10 }); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let (snapshot, _cursor_coordinates) = take_snapshot_and_cursor_position( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1280,26 +1358,31 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically_and_expand_b let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id_1, Some(client_id)); - tab.new_pane(new_pane_id_2, Some(client_id)); - tab.new_pane(new_pane_id_3, Some(client_id)); - tab.new_pane(new_pane_id_4, Some(client_id)); - tab.new_pane(new_pane_id_5, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id_1, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_2, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_3, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_4, Some(client_id)).unwrap(); + tab.new_pane(new_pane_id_5, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())); - tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())); + ) + .unwrap(); + tab.handle_pty_bytes(3, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(4, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(5, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(6, Vec::from("\u{1b}#8".as_bytes())) + .unwrap(); tab.resize_whole_tab(Size { cols: 50, rows: 10 }); tab.resize_whole_tab(Size { cols: 121, rows: 20, }); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let (snapshot, _cursor_coordinates) = take_snapshot_and_cursor_position( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1320,14 +1403,15 @@ fn embed_floating_pane() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am scratch terminal".as_bytes()), - ); - tab.toggle_pane_embed_or_floating(client_id); - tab.render(&mut output, None); + ) + .unwrap(); + tab.toggle_pane_embed_or_floating(client_id).unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1347,13 +1431,14 @@ fn float_embedded_pane() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.new_pane(new_pane_id, Some(client_id)); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am an embedded pane".as_bytes()), - ); - tab.toggle_pane_embed_or_floating(client_id); - tab.render(&mut output, None); + ) + .unwrap(); + tab.toggle_pane_embed_or_floating(client_id).unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1375,9 +1460,10 @@ fn cannot_float_only_embedded_pane() { tab.handle_pty_bytes( 1, Vec::from("\n\n\n I am an embedded pane".as_bytes()), - ); - tab.toggle_pane_embed_or_floating(client_id); - tab.render(&mut output, None); + ) + .unwrap(); + tab.toggle_pane_embed_or_floating(client_id).unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1400,8 +1486,8 @@ fn replacing_existing_wide_characters() { let mut tab = create_new_tab(size, ModeInfo::default()); let mut output = Output::default(); let pane_content = read_fixture("ncmpcpp-wide-chars"); - tab.handle_pty_bytes(1, pane_content); - tab.render(&mut output, None); + tab.handle_pty_bytes(1, pane_content).unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1423,9 +1509,11 @@ fn rename_embedded_pane() { tab.handle_pty_bytes( 1, Vec::from("\n\n\n I am an embedded pane".as_bytes()), - ); - tab.update_active_pane_name("Renamed empedded pane".as_bytes().to_vec(), client_id); - tab.render(&mut output, None); + ) + .unwrap(); + tab.update_active_pane_name("Renamed empedded pane".as_bytes().to_vec(), client_id) + .unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1445,14 +1533,16 @@ fn rename_floating_pane() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.new_pane(new_pane_id, Some(client_id)); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); tab.handle_pty_bytes( 2, Vec::from("\n\n\n I am a floating pane".as_bytes()), - ); - tab.toggle_pane_embed_or_floating(client_id); - tab.update_active_pane_name("Renamed floating pane".as_bytes().to_vec(), client_id); - tab.render(&mut output, None); + ) + .unwrap(); + tab.toggle_pane_embed_or_floating(client_id).unwrap(); + tab.update_active_pane_name("Renamed floating pane".as_bytes().to_vec(), client_id) + .unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1473,8 +1563,8 @@ fn wide_characters_in_left_title_side() { let mut tab = create_new_tab(size, ModeInfo::default()); let mut output = Output::default(); let pane_content = read_fixture("title-wide-chars"); - tab.handle_pty_bytes(1, pane_content); - tab.render(&mut output, None); + tab.handle_pty_bytes(1, pane_content).unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1496,11 +1586,12 @@ fn save_cursor_position_across_resizes() { tab.handle_pty_bytes( 1, Vec::from("\n\nI am some text\nI am another line of text\nLet's save the cursor position here \u{1b}[sI should be ovewritten".as_bytes()), - ); + ).unwrap(); tab.resize_whole_tab(Size { cols: 100, rows: 3 }); - tab.handle_pty_bytes(1, Vec::from("\u{1b}[uthis overwrote me!".as_bytes())); + tab.handle_pty_bytes(1, Vec::from("\u{1b}[uthis overwrote me!".as_bytes())) + .unwrap(); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1526,14 +1617,16 @@ fn move_floating_pane_with_sixel_image() { }))); let mut output = Output::new(sixel_image_store.clone(), character_cell_size); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); let fixture = read_fixture("sixel-image-500px.six"); - tab.handle_pty_bytes(2, fixture); - tab.handle_left_click(&Position::new(5, 71), client_id); - tab.handle_left_mouse_release(&Position::new(7, 75), client_id); + tab.handle_pty_bytes(2, fixture).unwrap(); + tab.handle_left_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_left_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot_with_sixel( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1561,14 +1654,16 @@ fn floating_pane_above_sixel_image() { }))); let mut output = Output::new(sixel_image_store.clone(), character_cell_size); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); let fixture = read_fixture("sixel-image-500px.six"); - tab.handle_pty_bytes(1, fixture); - tab.handle_left_click(&Position::new(5, 71), client_id); - tab.handle_left_mouse_release(&Position::new(7, 75), client_id); + tab.handle_pty_bytes(1, fixture).unwrap(); + tab.handle_left_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_left_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot_with_sixel( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1590,9 +1685,10 @@ fn suppress_tiled_pane() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.suppress_active_pane(new_pane_id, client_id); - tab.handle_pty_bytes(2, Vec::from("\n\n\nI am an editor pane".as_bytes())); - tab.render(&mut output, None); + tab.suppress_active_pane(new_pane_id, client_id).unwrap(); + tab.handle_pty_bytes(2, Vec::from("\n\n\nI am an editor pane".as_bytes())) + .unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1614,11 +1710,12 @@ fn suppress_floating_pane() { let editor_pane_id = PaneId::Terminal(3); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id, Some(client_id)); - tab.suppress_active_pane(editor_pane_id, client_id); - tab.handle_pty_bytes(3, Vec::from("\n\n\nI am an editor pane".as_bytes())); - tab.render(&mut output, None); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); + tab.suppress_active_pane(editor_pane_id, client_id).unwrap(); + tab.handle_pty_bytes(3, Vec::from("\n\n\nI am an editor pane".as_bytes())) + .unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1638,11 +1735,13 @@ fn close_suppressing_tiled_pane() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.suppress_active_pane(new_pane_id, client_id); - tab.handle_pty_bytes(2, Vec::from("\n\n\nI am an editor pane".as_bytes())); - tab.handle_pty_bytes(1, Vec::from("\n\n\nI am the original pane".as_bytes())); + tab.suppress_active_pane(new_pane_id, client_id).unwrap(); + tab.handle_pty_bytes(2, Vec::from("\n\n\nI am an editor pane".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(1, Vec::from("\n\n\nI am the original pane".as_bytes())) + .unwrap(); tab.close_pane(new_pane_id, false); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1664,13 +1763,15 @@ fn close_suppressing_floating_pane() { let editor_pane_id = PaneId::Terminal(3); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id, Some(client_id)); - tab.suppress_active_pane(editor_pane_id, client_id); - tab.handle_pty_bytes(3, Vec::from("\n\n\nI am an editor pane".as_bytes())); - tab.handle_pty_bytes(2, Vec::from("\n\n\nI am the original pane".as_bytes())); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); + tab.suppress_active_pane(editor_pane_id, client_id).unwrap(); + tab.handle_pty_bytes(3, Vec::from("\n\n\nI am an editor pane".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(2, Vec::from("\n\n\nI am the original pane".as_bytes())) + .unwrap(); tab.close_pane(editor_pane_id, false); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1690,12 +1791,14 @@ fn suppress_tiled_pane_float_it_and_close() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.suppress_active_pane(new_pane_id, client_id); - tab.handle_pty_bytes(2, Vec::from("\n\n\nI am an editor pane".as_bytes())); - tab.handle_pty_bytes(1, Vec::from("\n\n\nI am the original pane".as_bytes())); - tab.toggle_pane_embed_or_floating(client_id); + tab.suppress_active_pane(new_pane_id, client_id).unwrap(); + tab.handle_pty_bytes(2, Vec::from("\n\n\nI am an editor pane".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(1, Vec::from("\n\n\nI am the original pane".as_bytes())) + .unwrap(); + tab.toggle_pane_embed_or_floating(client_id).unwrap(); tab.close_pane(new_pane_id, false); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1717,14 +1820,16 @@ fn suppress_floating_pane_embed_it_and_close_it() { let editor_pane_id = PaneId::Terminal(3); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id, Some(client_id)); - tab.suppress_active_pane(editor_pane_id, client_id); - tab.handle_pty_bytes(3, Vec::from("\n\n\nI am an editor pane".as_bytes())); - tab.handle_pty_bytes(2, Vec::from("\n\n\nI am the original pane".as_bytes())); - tab.toggle_pane_embed_or_floating(client_id); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); + tab.suppress_active_pane(editor_pane_id, client_id).unwrap(); + tab.handle_pty_bytes(3, Vec::from("\n\n\nI am an editor pane".as_bytes())) + .unwrap(); + tab.handle_pty_bytes(2, Vec::from("\n\n\nI am the original pane".as_bytes())) + .unwrap(); + tab.toggle_pane_embed_or_floating(client_id).unwrap(); tab.close_pane(editor_pane_id, false); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1744,13 +1849,14 @@ fn resize_whole_tab_while_tiled_pane_is_suppressed() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.suppress_active_pane(new_pane_id, client_id); - tab.handle_pty_bytes(2, Vec::from("\n\n\nI am an editor pane".as_bytes())); + tab.suppress_active_pane(new_pane_id, client_id).unwrap(); + tab.handle_pty_bytes(2, Vec::from("\n\n\nI am an editor pane".as_bytes())) + .unwrap(); tab.resize_whole_tab(Size { cols: 100, rows: 10, }); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1772,15 +1878,16 @@ fn resize_whole_tab_while_floting_pane_is_suppressed() { let editor_pane_id = PaneId::Terminal(3); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id, Some(client_id)); - tab.suppress_active_pane(editor_pane_id, client_id); - tab.handle_pty_bytes(3, Vec::from("\n\n\nI am an editor pane".as_bytes())); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); + tab.suppress_active_pane(editor_pane_id, client_id).unwrap(); + tab.handle_pty_bytes(3, Vec::from("\n\n\nI am an editor pane".as_bytes())) + .unwrap(); tab.resize_whole_tab(Size { cols: 100, rows: 10, }); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1804,8 +1911,8 @@ fn enter_search_pane() { let mut tab = create_new_tab(size, mode_info); let mut output = Output::default(); let pane_content = read_fixture("grid_copy"); - tab.handle_pty_bytes(1, pane_content); - tab.render(&mut output, None); + tab.handle_pty_bytes(1, pane_content).unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1817,8 +1924,9 @@ fn enter_search_pane() { // Pane title should show 'tortor' as search term // Only lines containing 'tortor' get marked as render-targets, so // only those are updated (search-styling is not visible here). - tab.update_search_term("tortor".as_bytes().to_vec(), client_id); - tab.render(&mut output, None); + tab.update_search_term("tortor".as_bytes().to_vec(), client_id) + .unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1831,7 +1939,7 @@ fn enter_search_pane() { tab.toggle_search_wrap(client_id); tab.toggle_search_whole_words(client_id); tab.toggle_search_case_sensitivity(client_id); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1845,7 +1953,7 @@ fn enter_search_pane() { tab.toggle_search_whole_words(client_id); tab.toggle_search_case_sensitivity(client_id); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1869,12 +1977,12 @@ fn enter_search_floating_pane() { let mut tab = create_new_tab(size, mode_info); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.toggle_floating_panes(client_id, None); - tab.new_pane(new_pane_id, Some(client_id)); + tab.toggle_floating_panes(client_id, None).unwrap(); + tab.new_pane(new_pane_id, Some(client_id)).unwrap(); let pane_content = read_fixture("grid_copy"); - tab.handle_pty_bytes(2, pane_content); - tab.render(&mut output, None); + tab.handle_pty_bytes(2, pane_content).unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1884,8 +1992,9 @@ fn enter_search_floating_pane() { assert_snapshot!("search_floating_tab_nothing_highlighted", snapshot); // Only the line inside the floating tab which contain 'fring' should be in the new snapshot - tab.update_search_term("fring".as_bytes().to_vec(), client_id); - tab.render(&mut output, None); + tab.update_search_term("fring".as_bytes().to_vec(), client_id) + .unwrap(); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -1912,18 +2021,30 @@ fn pane_in_sgr_button_event_tracking_mouse_mode() { pty_instruction_bus.start(); let sgr_mouse_mode_any_button = String::from("\u{1b}[?1002;1006h"); // button event tracking (1002) with SGR encoding (1006) - tab.handle_pty_bytes(1, sgr_mouse_mode_any_button.as_bytes().to_vec()); - tab.handle_left_click(&Position::new(5, 71), client_id); - tab.handle_mouse_hold_left(&Position::new(9, 72), client_id); - tab.handle_left_mouse_release(&Position::new(7, 75), client_id); - tab.handle_right_click(&Position::new(5, 71), client_id); - tab.handle_mouse_hold_right(&Position::new(9, 72), client_id); - tab.handle_right_mouse_release(&Position::new(7, 75), client_id); - tab.handle_middle_click(&Position::new(5, 71), client_id); - tab.handle_mouse_hold_middle(&Position::new(9, 72), client_id); - tab.handle_middle_mouse_release(&Position::new(7, 75), client_id); - tab.handle_scrollwheel_up(&Position::new(5, 71), 1, client_id); - tab.handle_scrollwheel_down(&Position::new(5, 71), 1, client_id); + tab.handle_pty_bytes(1, sgr_mouse_mode_any_button.as_bytes().to_vec()) + .unwrap(); + tab.handle_left_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_mouse_hold_left(&Position::new(9, 72), client_id) + .unwrap(); + tab.handle_left_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); + tab.handle_right_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_mouse_hold_right(&Position::new(9, 72), client_id) + .unwrap(); + tab.handle_right_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); + tab.handle_middle_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_mouse_hold_middle(&Position::new(9, 72), client_id) + .unwrap(); + tab.handle_middle_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); + tab.handle_scrollwheel_up(&Position::new(5, 71), 1, client_id) + .unwrap(); + tab.handle_scrollwheel_down(&Position::new(5, 71), 1, client_id) + .unwrap(); pty_instruction_bus.exit(); @@ -1962,18 +2083,30 @@ fn pane_in_sgr_normal_event_tracking_mouse_mode() { pty_instruction_bus.start(); let sgr_mouse_mode_any_button = String::from("\u{1b}[?1000;1006h"); // normal event tracking (1000) with sgr encoding (1006) - tab.handle_pty_bytes(1, sgr_mouse_mode_any_button.as_bytes().to_vec()); - tab.handle_left_click(&Position::new(5, 71), client_id); - tab.handle_mouse_hold_left(&Position::new(9, 72), client_id); - tab.handle_left_mouse_release(&Position::new(7, 75), client_id); - tab.handle_right_click(&Position::new(5, 71), client_id); - tab.handle_mouse_hold_right(&Position::new(9, 72), client_id); - tab.handle_right_mouse_release(&Position::new(7, 75), client_id); - tab.handle_middle_click(&Position::new(5, 71), client_id); - tab.handle_mouse_hold_middle(&Position::new(9, 72), client_id); - tab.handle_middle_mouse_release(&Position::new(7, 75), client_id); - tab.handle_scrollwheel_up(&Position::new(5, 71), 1, client_id); - tab.handle_scrollwheel_down(&Position::new(5, 71), 1, client_id); + tab.handle_pty_bytes(1, sgr_mouse_mode_any_button.as_bytes().to_vec()) + .unwrap(); + tab.handle_left_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_mouse_hold_left(&Position::new(9, 72), client_id) + .unwrap(); + tab.handle_left_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); + tab.handle_right_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_mouse_hold_right(&Position::new(9, 72), client_id) + .unwrap(); + tab.handle_right_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); + tab.handle_middle_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_mouse_hold_middle(&Position::new(9, 72), client_id) + .unwrap(); + tab.handle_middle_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); + tab.handle_scrollwheel_up(&Position::new(5, 71), 1, client_id) + .unwrap(); + tab.handle_scrollwheel_down(&Position::new(5, 71), 1, client_id) + .unwrap(); pty_instruction_bus.exit(); @@ -2012,18 +2145,30 @@ fn pane_in_utf8_button_event_tracking_mouse_mode() { pty_instruction_bus.start(); let sgr_mouse_mode_any_button = String::from("\u{1b}[?1002;1005h"); // button event tracking (1002) with utf8 encoding (1005) - tab.handle_pty_bytes(1, sgr_mouse_mode_any_button.as_bytes().to_vec()); - tab.handle_left_click(&Position::new(5, 71), client_id); - tab.handle_mouse_hold_left(&Position::new(9, 72), client_id); - tab.handle_left_mouse_release(&Position::new(7, 75), client_id); - tab.handle_right_click(&Position::new(5, 71), client_id); - tab.handle_mouse_hold_right(&Position::new(9, 72), client_id); - tab.handle_right_mouse_release(&Position::new(7, 75), client_id); - tab.handle_middle_click(&Position::new(5, 71), client_id); - tab.handle_mouse_hold_middle(&Position::new(9, 72), client_id); - tab.handle_middle_mouse_release(&Position::new(7, 75), client_id); - tab.handle_scrollwheel_up(&Position::new(5, 71), 1, client_id); - tab.handle_scrollwheel_down(&Position::new(5, 71), 1, client_id); + tab.handle_pty_bytes(1, sgr_mouse_mode_any_button.as_bytes().to_vec()) + .unwrap(); + tab.handle_left_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_mouse_hold_left(&Position::new(9, 72), client_id) + .unwrap(); + tab.handle_left_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); + tab.handle_right_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_mouse_hold_right(&Position::new(9, 72), client_id) + .unwrap(); + tab.handle_right_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); + tab.handle_middle_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_mouse_hold_middle(&Position::new(9, 72), client_id) + .unwrap(); + tab.handle_middle_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); + tab.handle_scrollwheel_up(&Position::new(5, 71), 1, client_id) + .unwrap(); + tab.handle_scrollwheel_down(&Position::new(5, 71), 1, client_id) + .unwrap(); pty_instruction_bus.exit(); @@ -2062,18 +2207,30 @@ fn pane_in_utf8_normal_event_tracking_mouse_mode() { pty_instruction_bus.start(); let sgr_mouse_mode_any_button = String::from("\u{1b}[?1000;1005h"); // normal event tracking (1000) with sgr encoding (1006) - tab.handle_pty_bytes(1, sgr_mouse_mode_any_button.as_bytes().to_vec()); - tab.handle_left_click(&Position::new(5, 71), client_id); - tab.handle_mouse_hold_left(&Position::new(9, 72), client_id); - tab.handle_left_mouse_release(&Position::new(7, 75), client_id); - tab.handle_right_click(&Position::new(5, 71), client_id); - tab.handle_mouse_hold_right(&Position::new(9, 72), client_id); - tab.handle_right_mouse_release(&Position::new(7, 75), client_id); - tab.handle_middle_click(&Position::new(5, 71), client_id); - tab.handle_mouse_hold_middle(&Position::new(9, 72), client_id); - tab.handle_middle_mouse_release(&Position::new(7, 75), client_id); - tab.handle_scrollwheel_up(&Position::new(5, 71), 1, client_id); - tab.handle_scrollwheel_down(&Position::new(5, 71), 1, client_id); + tab.handle_pty_bytes(1, sgr_mouse_mode_any_button.as_bytes().to_vec()) + .unwrap(); + tab.handle_left_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_mouse_hold_left(&Position::new(9, 72), client_id) + .unwrap(); + tab.handle_left_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); + tab.handle_right_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_mouse_hold_right(&Position::new(9, 72), client_id) + .unwrap(); + tab.handle_right_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); + tab.handle_middle_click(&Position::new(5, 71), client_id) + .unwrap(); + tab.handle_mouse_hold_middle(&Position::new(9, 72), client_id) + .unwrap(); + tab.handle_middle_mouse_release(&Position::new(7, 75), client_id) + .unwrap(); + tab.handle_scrollwheel_up(&Position::new(5, 71), 1, client_id) + .unwrap(); + tab.handle_scrollwheel_down(&Position::new(5, 71), 1, client_id) + .unwrap(); pty_instruction_bus.exit(); @@ -2115,7 +2272,7 @@ fn tab_with_basic_layout() { let client_id = 1; let mut tab = create_new_tab_with_layout(size, ModeInfo::default(), layout); let mut output = Output::default(); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -2155,7 +2312,7 @@ fn tab_with_nested_layout() { let client_id = 1; let mut tab = create_new_tab_with_layout(size, ModeInfo::default(), layout); let mut output = Output::default(); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -2189,7 +2346,7 @@ fn tab_with_nested_uneven_layout() { let client_id = 1; let mut tab = create_new_tab_with_layout(size, ModeInfo::default(), layout); let mut output = Output::default(); - tab.render(&mut output, None); + tab.render(&mut output, None).unwrap(); let snapshot = take_snapshot( output.serialize().get(&client_id).unwrap(), size.rows, @@ -2218,9 +2375,12 @@ fn pane_bracketed_paste_ignored_when_not_in_bracketed_paste_mode() { let bracketed_paste_start = vec![27, 91, 50, 48, 48, 126]; // \u{1b}[200~ let bracketed_paste_end = vec![27, 91, 50, 48, 49, 126]; // \u{1b}[201 - tab.write_to_active_terminal(bracketed_paste_start, client_id); - tab.write_to_active_terminal("test".as_bytes().to_vec(), client_id); - tab.write_to_active_terminal(bracketed_paste_end, client_id); + tab.write_to_active_terminal(bracketed_paste_start, client_id) + .unwrap(); + tab.write_to_active_terminal("test".as_bytes().to_vec(), client_id) + .unwrap(); + tab.write_to_active_terminal(bracketed_paste_end, client_id) + .unwrap(); pty_instruction_bus.exit(); @@ -2248,18 +2408,26 @@ fn pane_faux_scrolling_in_alternate_mode() { let set_application_mode = String::from("\u{1b}[?1h"); // no output since alternate scren not active yet - tab.handle_scrollwheel_up(&Position::new(1, 1), lines_to_scroll, client_id); - tab.handle_scrollwheel_down(&Position::new(1, 1), lines_to_scroll, client_id); + tab.handle_scrollwheel_up(&Position::new(1, 1), lines_to_scroll, client_id) + .unwrap(); + tab.handle_scrollwheel_down(&Position::new(1, 1), lines_to_scroll, client_id) + .unwrap(); - tab.handle_pty_bytes(1, enable_alternate_screen.as_bytes().to_vec()); + tab.handle_pty_bytes(1, enable_alternate_screen.as_bytes().to_vec()) + .unwrap(); // CSI A * lines_to_scroll, CSI B * lines_to_scroll - tab.handle_scrollwheel_up(&Position::new(1, 1), lines_to_scroll, client_id); - tab.handle_scrollwheel_down(&Position::new(1, 1), lines_to_scroll, client_id); + tab.handle_scrollwheel_up(&Position::new(1, 1), lines_to_scroll, client_id) + .unwrap(); + tab.handle_scrollwheel_down(&Position::new(1, 1), lines_to_scroll, client_id) + .unwrap(); - tab.handle_pty_bytes(1, set_application_mode.as_bytes().to_vec()); + tab.handle_pty_bytes(1, set_application_mode.as_bytes().to_vec()) + .unwrap(); // SS3 A * lines_to_scroll, SS3 B * lines_to_scroll - tab.handle_scrollwheel_up(&Position::new(1, 1), lines_to_scroll, client_id); - tab.handle_scrollwheel_down(&Position::new(1, 1), lines_to_scroll, client_id); + tab.handle_scrollwheel_up(&Position::new(1, 1), lines_to_scroll, client_id) + .unwrap(); + tab.handle_scrollwheel_down(&Position::new(1, 1), lines_to_scroll, client_id) + .unwrap(); pty_instruction_bus.exit(); diff --git a/zellij-server/src/tab/unit/tab_tests.rs b/zellij-server/src/tab/unit/tab_tests.rs index 60604b00..3f20ded9 100644 --- a/zellij-server/src/tab/unit/tab_tests.rs +++ b/zellij-server/src/tab/unit/tab_tests.rs @@ -131,7 +131,8 @@ fn create_new_tab(size: Size) -> Tab { terminal_emulator_colors, terminal_emulator_color_codes, ); - tab.apply_layout(PaneLayout::default(), vec![1], index, client_id); + tab.apply_layout(PaneLayout::default(), vec![1], index, client_id) + .unwrap(); tab } @@ -177,7 +178,8 @@ fn create_new_tab_with_cell_size( terminal_emulator_colors, terminal_emulator_color_codes, ); - tab.apply_layout(PaneLayout::default(), vec![1], index, client_id); + tab.apply_layout(PaneLayout::default(), vec![1], index, client_id) + .unwrap(); tab } @@ -188,16 +190,17 @@ fn write_to_suppressed_pane() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); // Suppress pane 2 and remove it from active panes - tab.suppress_active_pane(PaneId::Terminal(2), 1); + tab.suppress_active_pane(PaneId::Terminal(2), 1).unwrap(); tab.tiled_panes.remove_pane(PaneId::Terminal(2)); // Make sure it's suppressed now tab.suppressed_panes.get(&PaneId::Terminal(2)).unwrap(); // Write content to it - tab.write_to_pane_id(vec![34, 127, 31, 82, 17, 182], PaneId::Terminal(2)); + tab.write_to_pane_id(vec![34, 127, 31, 82, 17, 182], PaneId::Terminal(2)) + .unwrap(); } #[test] @@ -208,7 +211,7 @@ fn split_panes_vertically() { }; let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.vertical_split(new_pane_id, 1); + tab.vertical_split(new_pane_id, 1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 2, "The tab has two panes"); assert_eq!( tab.tiled_panes @@ -304,7 +307,7 @@ fn split_panes_horizontally() { }; let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.horizontal_split(new_pane_id, 1); + tab.horizontal_split(new_pane_id, 1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 2, "The tab has two panes"); assert_eq!( @@ -403,7 +406,7 @@ fn split_largest_pane() { let mut tab = create_new_tab(size); for i in 2..5 { let new_pane_id = PaneId::Terminal(i); - tab.new_pane(new_pane_id, Some(1)); + tab.new_pane(new_pane_id, Some(1)).unwrap(); } assert_eq!(tab.tiled_panes.panes.len(), 4, "The tab has four panes"); @@ -584,7 +587,7 @@ fn split_largest_pane() { pub fn cannot_split_panes_vertically_when_active_pane_is_too_small() { let size = Size { cols: 8, rows: 20 }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); assert_eq!( tab.tiled_panes.panes.len(), 1, @@ -596,7 +599,7 @@ pub fn cannot_split_panes_vertically_when_active_pane_is_too_small() { pub fn cannot_split_panes_horizontally_when_active_pane_is_too_small() { let size = Size { cols: 121, rows: 4 }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); assert_eq!( tab.tiled_panes.panes.len(), 1, @@ -608,7 +611,7 @@ pub fn cannot_split_panes_horizontally_when_active_pane_is_too_small() { pub fn cannot_split_largest_pane_when_there_is_no_room() { let size = Size { cols: 8, rows: 4 }; let mut tab = create_new_tab(size); - tab.new_pane(PaneId::Terminal(2), Some(1)); + tab.new_pane(PaneId::Terminal(2), Some(1)).unwrap(); assert_eq!( tab.tiled_panes.panes.len(), 1, @@ -625,7 +628,7 @@ pub fn toggle_focused_pane_fullscreen() { let mut tab = create_new_tab(size); for i in 2..5 { let new_pane_id = PaneId::Terminal(i); - tab.new_pane(new_pane_id, Some(1)); + tab.new_pane(new_pane_id, Some(1)).unwrap(); } tab.toggle_active_pane_fullscreen(1); assert_eq!( @@ -698,10 +701,10 @@ fn switch_to_next_pane_fullscreen() { let mut active_tab = create_new_tab(size); - active_tab.new_pane(PaneId::Terminal(1), Some(1)); - active_tab.new_pane(PaneId::Terminal(2), Some(1)); - active_tab.new_pane(PaneId::Terminal(3), Some(1)); - active_tab.new_pane(PaneId::Terminal(4), Some(1)); + active_tab.new_pane(PaneId::Terminal(1), Some(1)).unwrap(); + active_tab.new_pane(PaneId::Terminal(2), Some(1)).unwrap(); + active_tab.new_pane(PaneId::Terminal(3), Some(1)).unwrap(); + active_tab.new_pane(PaneId::Terminal(4), Some(1)).unwrap(); active_tab.toggle_active_pane_fullscreen(1); // order is now 1 ->2 -> 3 -> 4 due to how new panes are inserted @@ -730,10 +733,10 @@ fn switch_to_prev_pane_fullscreen() { //testing four consecutive switches in fullscreen mode - active_tab.new_pane(PaneId::Terminal(1), Some(1)); - active_tab.new_pane(PaneId::Terminal(2), Some(1)); - active_tab.new_pane(PaneId::Terminal(3), Some(1)); - active_tab.new_pane(PaneId::Terminal(4), Some(1)); + active_tab.new_pane(PaneId::Terminal(1), Some(1)).unwrap(); + active_tab.new_pane(PaneId::Terminal(2), Some(1)).unwrap(); + active_tab.new_pane(PaneId::Terminal(3), Some(1)).unwrap(); + active_tab.new_pane(PaneId::Terminal(4), Some(1)).unwrap(); active_tab.toggle_active_pane_fullscreen(1); // order is now 1 2 3 4 @@ -768,8 +771,8 @@ pub fn close_pane_with_another_pane_above_it() { }; let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.horizontal_split(new_pane_id, 1); - tab.close_focused_pane(1); + tab.horizontal_split(new_pane_id, 1).unwrap(); + tab.close_focused_pane(1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 1, "One pane left in tab"); assert_eq!( @@ -833,9 +836,9 @@ pub fn close_pane_with_another_pane_below_it() { }; let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.horizontal_split(new_pane_id, 1); + tab.horizontal_split(new_pane_id, 1).unwrap(); tab.move_focus_up(1); - tab.close_focused_pane(1); + tab.close_focused_pane(1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 1, "One pane left in tab"); assert_eq!( @@ -896,8 +899,8 @@ pub fn close_pane_with_another_pane_to_the_left() { }; let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.vertical_split(new_pane_id, 1); - tab.close_focused_pane(1); + tab.vertical_split(new_pane_id, 1).unwrap(); + tab.close_focused_pane(1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 1, "One pane left in tab"); assert_eq!( @@ -958,9 +961,9 @@ pub fn close_pane_with_another_pane_to_the_right() { }; let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.vertical_split(new_pane_id, 1); + tab.vertical_split(new_pane_id, 1).unwrap(); tab.move_focus_left(1); - tab.close_focused_pane(1); + tab.close_focused_pane(1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 1, "One pane left in tab"); assert_eq!( @@ -1024,11 +1027,11 @@ pub fn close_pane_with_multiple_panes_above_it() { let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); - tab.horizontal_split(new_pane_id_1, 1); + tab.horizontal_split(new_pane_id_1, 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(new_pane_id_2, 1); + tab.vertical_split(new_pane_id_2, 1).unwrap(); tab.move_focus_down(1); - tab.close_focused_pane(1); + tab.close_focused_pane(1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 2, "Two panes left in tab"); assert_eq!( @@ -1135,10 +1138,10 @@ pub fn close_pane_with_multiple_panes_below_it() { let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); - tab.horizontal_split(new_pane_id_1, 1); - tab.vertical_split(new_pane_id_2, 1); + tab.horizontal_split(new_pane_id_1, 1).unwrap(); + tab.vertical_split(new_pane_id_2, 1).unwrap(); tab.move_focus_up(1); - tab.close_focused_pane(1); + tab.close_focused_pane(1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 2, "Two panes left in tab"); assert_eq!( @@ -1245,11 +1248,11 @@ pub fn close_pane_with_multiple_panes_to_the_left() { let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); - tab.vertical_split(new_pane_id_1, 1); + tab.vertical_split(new_pane_id_1, 1).unwrap(); tab.move_focus_left(1); - tab.horizontal_split(new_pane_id_2, 1); + tab.horizontal_split(new_pane_id_2, 1).unwrap(); tab.move_focus_right(1); - tab.close_focused_pane(1); + tab.close_focused_pane(1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 2, "Two panes left in tab"); assert_eq!( @@ -1356,10 +1359,10 @@ pub fn close_pane_with_multiple_panes_to_the_right() { let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); - tab.vertical_split(new_pane_id_1, 1); - tab.horizontal_split(new_pane_id_2, 1); + tab.vertical_split(new_pane_id_1, 1).unwrap(); + tab.horizontal_split(new_pane_id_2, 1).unwrap(); tab.move_focus_left(1); - tab.close_focused_pane(1); + tab.close_focused_pane(1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 2, "Two panes left in tab"); assert_eq!( @@ -1471,21 +1474,21 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { let new_pane_id_5 = PaneId::Terminal(6); let new_pane_id_6 = PaneId::Terminal(7); - tab.vertical_split(new_pane_id_1, 1); - tab.vertical_split(new_pane_id_2, 1); + tab.vertical_split(new_pane_id_1, 1).unwrap(); + tab.vertical_split(new_pane_id_2, 1).unwrap(); tab.move_focus_left(1); tab.move_focus_left(1); - tab.horizontal_split(new_pane_id_3, 1); + tab.horizontal_split(new_pane_id_3, 1).unwrap(); tab.move_focus_right(1); - tab.horizontal_split(new_pane_id_4, 1); + tab.horizontal_split(new_pane_id_4, 1).unwrap(); tab.move_focus_right(1); - tab.horizontal_split(new_pane_id_5, 1); + tab.horizontal_split(new_pane_id_5, 1).unwrap(); tab.move_focus_left(1); tab.move_focus_up(1); tab.resize_down(1); - tab.vertical_split(new_pane_id_6, 1); + tab.vertical_split(new_pane_id_6, 1).unwrap(); tab.move_focus_down(1); - tab.close_focused_pane(1); + tab.close_focused_pane(1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 6, "Six panes left in tab"); @@ -1771,20 +1774,20 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { let new_pane_id_5 = PaneId::Terminal(6); let new_pane_id_6 = PaneId::Terminal(7); - tab.vertical_split(new_pane_id_1, 1); - tab.vertical_split(new_pane_id_2, 1); + tab.vertical_split(new_pane_id_1, 1).unwrap(); + tab.vertical_split(new_pane_id_2, 1).unwrap(); tab.move_focus_left(1); tab.move_focus_left(1); - tab.horizontal_split(new_pane_id_3, 1); + tab.horizontal_split(new_pane_id_3, 1).unwrap(); tab.move_focus_right(1); - tab.horizontal_split(new_pane_id_4, 1); + tab.horizontal_split(new_pane_id_4, 1).unwrap(); tab.move_focus_right(1); - tab.horizontal_split(new_pane_id_5, 1); + tab.horizontal_split(new_pane_id_5, 1).unwrap(); tab.move_focus_left(1); tab.resize_up(1); - tab.vertical_split(new_pane_id_6, 1); + tab.vertical_split(new_pane_id_6, 1).unwrap(); tab.move_focus_up(1); - tab.close_focused_pane(1); + tab.close_focused_pane(1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 6, "Six panes left in tab"); @@ -2072,23 +2075,23 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { let new_pane_id_5 = PaneId::Terminal(6); let new_pane_id_6 = PaneId::Terminal(7); - tab.horizontal_split(new_pane_id_1, 1); - tab.horizontal_split(new_pane_id_2, 1); + tab.horizontal_split(new_pane_id_1, 1).unwrap(); + tab.horizontal_split(new_pane_id_2, 1).unwrap(); tab.move_focus_up(1); tab.move_focus_up(1); - tab.vertical_split(new_pane_id_3, 1); + tab.vertical_split(new_pane_id_3, 1).unwrap(); tab.move_focus_down(1); - tab.vertical_split(new_pane_id_4, 1); + tab.vertical_split(new_pane_id_4, 1).unwrap(); tab.move_focus_down(1); - tab.vertical_split(new_pane_id_5, 1); + tab.vertical_split(new_pane_id_5, 1).unwrap(); tab.move_focus_up(1); tab.move_focus_left(1); tab.resize_right(1); tab.resize_up(1); tab.resize_up(1); - tab.horizontal_split(new_pane_id_6, 1); + tab.horizontal_split(new_pane_id_6, 1).unwrap(); tab.move_focus_right(1); - tab.close_focused_pane(1); + tab.close_focused_pane(1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 6, "Six panes left in tab"); @@ -2376,22 +2379,22 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { let new_pane_id_5 = PaneId::Terminal(6); let new_pane_id_6 = PaneId::Terminal(7); - tab.horizontal_split(new_pane_id_1, 1); - tab.horizontal_split(new_pane_id_2, 1); + tab.horizontal_split(new_pane_id_1, 1).unwrap(); + tab.horizontal_split(new_pane_id_2, 1).unwrap(); tab.move_focus_up(1); tab.move_focus_up(1); - tab.vertical_split(new_pane_id_3, 1); + tab.vertical_split(new_pane_id_3, 1).unwrap(); tab.move_focus_down(1); - tab.vertical_split(new_pane_id_4, 1); + tab.vertical_split(new_pane_id_4, 1).unwrap(); tab.move_focus_down(1); - tab.vertical_split(new_pane_id_5, 1); + tab.vertical_split(new_pane_id_5, 1).unwrap(); tab.move_focus_up(1); tab.resize_left(1); tab.resize_up(1); tab.resize_up(1); - tab.horizontal_split(new_pane_id_6, 1); + tab.horizontal_split(new_pane_id_6, 1).unwrap(); tab.move_focus_left(1); - tab.close_focused_pane(1); + tab.close_focused_pane(1).unwrap(); assert_eq!(tab.tiled_panes.panes.len(), 6, "Six panes left in tab"); @@ -2663,7 +2666,7 @@ pub fn move_focus_down() { let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.horizontal_split(new_pane_id, 1); + tab.horizontal_split(new_pane_id, 1).unwrap(); tab.move_focus_up(1); tab.move_focus_down(1); @@ -2685,9 +2688,9 @@ pub fn move_focus_down_to_the_most_recently_used_pane() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.horizontal_split(new_pane_id_1, 1); - tab.vertical_split(new_pane_id_2, 1); - tab.vertical_split(new_pane_id_3, 1); + tab.horizontal_split(new_pane_id_1, 1).unwrap(); + tab.vertical_split(new_pane_id_2, 1).unwrap(); + tab.vertical_split(new_pane_id_3, 1).unwrap(); tab.move_focus_up(1); tab.move_focus_down(1); @@ -2712,7 +2715,7 @@ pub fn move_focus_up() { let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.horizontal_split(new_pane_id, 1); + tab.horizontal_split(new_pane_id, 1).unwrap(); tab.move_focus_up(1); assert_eq!( @@ -2733,10 +2736,10 @@ pub fn move_focus_up_to_the_most_recently_used_pane() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.horizontal_split(new_pane_id_1, 1); + tab.horizontal_split(new_pane_id_1, 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(new_pane_id_2, 1); - tab.vertical_split(new_pane_id_3, 1); + tab.vertical_split(new_pane_id_2, 1).unwrap(); + tab.vertical_split(new_pane_id_3, 1).unwrap(); tab.move_focus_down(1); tab.move_focus_up(1); @@ -2761,7 +2764,7 @@ pub fn move_focus_left() { let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.vertical_split(new_pane_id, 1); + tab.vertical_split(new_pane_id, 1).unwrap(); tab.move_focus_left(1); assert_eq!( @@ -2782,10 +2785,10 @@ pub fn move_focus_left_to_the_most_recently_used_pane() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.vertical_split(new_pane_id_1, 1); + tab.vertical_split(new_pane_id_1, 1).unwrap(); tab.move_focus_left(1); - tab.horizontal_split(new_pane_id_2, 1); - tab.horizontal_split(new_pane_id_3, 1); + tab.horizontal_split(new_pane_id_2, 1).unwrap(); + tab.horizontal_split(new_pane_id_3, 1).unwrap(); tab.move_focus_right(1); tab.move_focus_left(1); @@ -2810,7 +2813,7 @@ pub fn move_focus_right() { let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.vertical_split(new_pane_id, 1); + tab.vertical_split(new_pane_id, 1).unwrap(); tab.move_focus_left(1); tab.move_focus_right(1); @@ -2832,9 +2835,9 @@ pub fn move_focus_right_to_the_most_recently_used_pane() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.vertical_split(new_pane_id_1, 1); - tab.horizontal_split(new_pane_id_2, 1); - tab.horizontal_split(new_pane_id_3, 1); + tab.vertical_split(new_pane_id_1, 1).unwrap(); + tab.horizontal_split(new_pane_id_2, 1).unwrap(); + tab.horizontal_split(new_pane_id_3, 1).unwrap(); tab.move_focus_left(1); tab.move_focus_right(1); @@ -2859,7 +2862,7 @@ pub fn move_active_pane_down() { let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.horizontal_split(new_pane_id, 1); + tab.horizontal_split(new_pane_id, 1).unwrap(); tab.move_focus_up(1); tab.move_active_pane_down(1); @@ -2886,9 +2889,9 @@ pub fn move_active_pane_down_to_the_most_recently_used_position() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.horizontal_split(new_pane_id_1, 1); - tab.vertical_split(new_pane_id_2, 1); - tab.vertical_split(new_pane_id_3, 1); + tab.horizontal_split(new_pane_id_1, 1).unwrap(); + tab.vertical_split(new_pane_id_2, 1).unwrap(); + tab.vertical_split(new_pane_id_3, 1).unwrap(); tab.move_focus_up(1); tab.move_active_pane_down(1); @@ -2918,7 +2921,7 @@ pub fn move_active_pane_up() { let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.horizontal_split(new_pane_id, 1); + tab.horizontal_split(new_pane_id, 1).unwrap(); tab.move_active_pane_up(1); assert_eq!( @@ -2944,10 +2947,10 @@ pub fn move_active_pane_up_to_the_most_recently_used_position() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.horizontal_split(new_pane_id_1, 1); + tab.horizontal_split(new_pane_id_1, 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(new_pane_id_2, 1); - tab.vertical_split(new_pane_id_3, 1); + tab.vertical_split(new_pane_id_2, 1).unwrap(); + tab.vertical_split(new_pane_id_3, 1).unwrap(); tab.move_focus_down(1); tab.move_active_pane_up(1); @@ -2978,7 +2981,7 @@ pub fn move_active_pane_left() { let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.vertical_split(new_pane_id, 1); + tab.vertical_split(new_pane_id, 1).unwrap(); tab.move_active_pane_left(1); assert_eq!( @@ -3004,10 +3007,10 @@ pub fn move_active_pane_left_to_the_most_recently_used_position() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.vertical_split(new_pane_id_1, 1); + tab.vertical_split(new_pane_id_1, 1).unwrap(); tab.move_focus_left(1); - tab.horizontal_split(new_pane_id_2, 1); - tab.horizontal_split(new_pane_id_3, 1); + tab.horizontal_split(new_pane_id_2, 1).unwrap(); + tab.horizontal_split(new_pane_id_3, 1).unwrap(); tab.move_focus_right(1); tab.move_active_pane_left(1); @@ -3038,7 +3041,7 @@ pub fn move_active_pane_right() { let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.vertical_split(new_pane_id, 1); + tab.vertical_split(new_pane_id, 1).unwrap(); tab.move_focus_left(1); tab.move_active_pane_right(1); @@ -3065,9 +3068,9 @@ pub fn move_active_pane_right_to_the_most_recently_used_position() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.vertical_split(new_pane_id_1, 1); - tab.horizontal_split(new_pane_id_2, 1); - tab.horizontal_split(new_pane_id_3, 1); + tab.vertical_split(new_pane_id_1, 1).unwrap(); + tab.horizontal_split(new_pane_id_2, 1).unwrap(); + tab.horizontal_split(new_pane_id_3, 1).unwrap(); tab.move_focus_left(1); tab.move_active_pane_right(1); @@ -3105,7 +3108,7 @@ pub fn resize_down_with_pane_above() { }; let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.horizontal_split(new_pane_id, 1); + tab.horizontal_split(new_pane_id, 1).unwrap(); tab.resize_down(1); assert_eq!( @@ -3211,7 +3214,7 @@ pub fn resize_down_with_pane_below() { }; let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); - tab.horizontal_split(new_pane_id, 1); + tab.horizontal_split(new_pane_id, 1).unwrap(); tab.move_focus_up(1); tab.resize_down(1); @@ -3324,8 +3327,8 @@ pub fn resize_down_with_panes_above_and_below() { let first_pane_id = PaneId::Terminal(1); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); - tab.horizontal_split(new_pane_id_1, 1); - tab.horizontal_split(new_pane_id_2, 1); + tab.horizontal_split(new_pane_id_1, 1).unwrap(); + tab.horizontal_split(new_pane_id_2, 1).unwrap(); tab.move_focus_up(1); tab.resize_down(1); @@ -3477,9 +3480,9 @@ pub fn resize_down_with_multiple_panes_above() { let first_pane_id = PaneId::Terminal(1); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); - tab.horizontal_split(new_pane_id_1, 1); + tab.horizontal_split(new_pane_id_1, 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(new_pane_id_2, 1); + tab.vertical_split(new_pane_id_2, 1).unwrap(); tab.move_focus_down(1); tab.resize_down(1); @@ -3632,10 +3635,10 @@ pub fn resize_down_with_panes_above_aligned_left_with_current_pane() { let pane_to_the_left = PaneId::Terminal(2); let focused_pane = PaneId::Terminal(3); let pane_above = PaneId::Terminal(4); - tab.horizontal_split(pane_to_the_left, 1); - tab.vertical_split(focused_pane, 1); + tab.horizontal_split(pane_to_the_left, 1).unwrap(); + tab.vertical_split(focused_pane, 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(pane_above, 1); + tab.vertical_split(pane_above, 1).unwrap(); tab.move_focus_down(1); tab.resize_down(1); @@ -3832,10 +3835,10 @@ pub fn resize_down_with_panes_below_aligned_left_with_current_pane() { let pane_below_and_left = PaneId::Terminal(2); let pane_below = PaneId::Terminal(3); let focused_pane = PaneId::Terminal(4); - tab.horizontal_split(pane_below_and_left, 1); - tab.vertical_split(pane_below, 1); + tab.horizontal_split(pane_below_and_left, 1).unwrap(); + tab.vertical_split(pane_below, 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(focused_pane, 1); + tab.vertical_split(focused_pane, 1).unwrap(); tab.resize_down(1); assert_eq!( @@ -4031,10 +4034,10 @@ pub fn resize_down_with_panes_above_aligned_right_with_current_pane() { let focused_pane = PaneId::Terminal(2); let pane_to_the_right = PaneId::Terminal(3); let pane_above_and_right = PaneId::Terminal(4); - tab.horizontal_split(focused_pane, 1); - tab.vertical_split(pane_to_the_right, 1); + tab.horizontal_split(focused_pane, 1).unwrap(); + tab.vertical_split(pane_to_the_right, 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(pane_above_and_right, 1); + tab.vertical_split(pane_above_and_right, 1).unwrap(); tab.move_focus_down(1); tab.move_focus_left(1); tab.resize_down(1); @@ -4232,10 +4235,10 @@ pub fn resize_down_with_panes_below_aligned_right_with_current_pane() { let pane_below = PaneId::Terminal(2); let pane_below_and_right = PaneId::Terminal(3); let pane_to_the_right = PaneId::Terminal(4); - tab.horizontal_split(pane_below, 1); - tab.vertical_split(pane_below_and_right, 1); + tab.horizontal_split(pane_below, 1).unwrap(); + tab.vertical_split(pane_below_and_right, 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(pane_to_the_right, 1); + tab.vertical_split(pane_to_the_right, 1).unwrap(); tab.move_focus_left(1); tab.resize_down(1); @@ -4428,12 +4431,12 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.vertical_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(5), 1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_left(1); tab.move_focus_down(1); tab.resize_down(1); @@ -4713,12 +4716,12 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.vertical_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(5), 1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_left(1); tab.resize_down(1); @@ -4997,16 +5000,16 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_down(1); - tab.vertical_split(PaneId::Terminal(5), 1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_left(1); - tab.vertical_split(PaneId::Terminal(7), 1); - tab.vertical_split(PaneId::Terminal(8), 1); + tab.vertical_split(PaneId::Terminal(7), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(8), 1).unwrap(); tab.move_focus_left(1); tab.resize_down(1); @@ -5371,16 +5374,16 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_left(1); - tab.vertical_split(PaneId::Terminal(5), 1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_down(1); - tab.vertical_split(PaneId::Terminal(7), 1); - tab.vertical_split(PaneId::Terminal(8), 1); + tab.vertical_split(PaneId::Terminal(7), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(8), 1).unwrap(); tab.move_focus_left(1); tab.move_focus_up(1); tab.move_focus_left(1); @@ -5745,7 +5748,7 @@ pub fn cannot_resize_down_when_pane_below_is_at_minimum_height() { rows: 10, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_up(1); tab.resize_down(1); @@ -5787,7 +5790,7 @@ pub fn resize_left_with_pane_to_the_left() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.resize_left(1); assert_eq!( @@ -5890,7 +5893,7 @@ pub fn resize_left_with_pane_to_the_right() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_left(1); tab.resize_left(1); @@ -5995,8 +5998,8 @@ pub fn resize_left_with_panes_to_the_left_and_right() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); - tab.vertical_split(PaneId::Terminal(3), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_left(1); tab.resize_left(1); @@ -6143,9 +6146,9 @@ pub fn resize_left_with_multiple_panes_to_the_left() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_left(1); - tab.horizontal_split(PaneId::Terminal(3), 1); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_right(1); tab.resize_left(1); @@ -6293,10 +6296,10 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.vertical_split(PaneId::Terminal(3), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_down(1); tab.resize_left(1); @@ -6487,10 +6490,10 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.vertical_split(PaneId::Terminal(3), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_down(1); tab.move_focus_left(1); tab.resize_left(1); @@ -6682,10 +6685,10 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.vertical_split(PaneId::Terminal(3), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.resize_left(1); assert_eq!( @@ -6875,10 +6878,10 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.vertical_split(PaneId::Terminal(3), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_left(1); tab.resize_left(1); @@ -7071,13 +7074,13 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.horizontal_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(5), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_down(1); tab.resize_left(1); @@ -7356,13 +7359,13 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.horizontal_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(5), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_down(1); tab.move_focus_left(1); tab.resize_left(1); @@ -7642,17 +7645,17 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov rows: 70, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.horizontal_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(5), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); tab.move_focus_down(1); tab.resize_down(1); - tab.vertical_split(PaneId::Terminal(6), 1); - tab.horizontal_split(PaneId::Terminal(7), 1); - tab.horizontal_split(PaneId::Terminal(8), 1); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(7), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(8), 1).unwrap(); tab.move_focus_up(1); tab.resize_left(1); @@ -8017,18 +8020,18 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo rows: 70, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.horizontal_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(5), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); tab.move_focus_down(1); tab.resize_down(1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_left(1); - tab.horizontal_split(PaneId::Terminal(7), 1); - tab.horizontal_split(PaneId::Terminal(8), 1); + tab.horizontal_split(PaneId::Terminal(7), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(8), 1).unwrap(); tab.move_focus_up(1); tab.resize_left(1); @@ -8388,7 +8391,7 @@ pub fn cannot_resize_left_when_pane_to_the_left_is_at_minimum_width() { let size = Size { cols: 10, rows: 20 }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.resize_left(1); assert_eq!( @@ -8429,7 +8432,7 @@ pub fn resize_right_with_pane_to_the_left() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.resize_right(1); assert_eq!( @@ -8533,7 +8536,7 @@ pub fn resize_right_with_pane_to_the_right() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_left(1); tab.resize_right(1); @@ -8638,8 +8641,8 @@ pub fn resize_right_with_panes_to_the_left_and_right() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); - tab.vertical_split(PaneId::Terminal(3), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_left(1); tab.resize_right(1); @@ -8787,9 +8790,9 @@ pub fn resize_right_with_multiple_panes_to_the_left() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_left(1); - tab.horizontal_split(PaneId::Terminal(3), 1); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_right(1); tab.resize_right(1); @@ -8937,11 +8940,11 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_left(1); - tab.horizontal_split(PaneId::Terminal(3), 1); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_right(1); - tab.horizontal_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(4), 1).unwrap(); tab.resize_right(1); assert_eq!( @@ -9130,11 +9133,11 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_left(1); - tab.horizontal_split(PaneId::Terminal(3), 1); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_right(1); - tab.horizontal_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_left(1); tab.resize_right(1); @@ -9325,11 +9328,11 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_left(1); - tab.horizontal_split(PaneId::Terminal(3), 1); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_right(1); - tab.horizontal_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); tab.resize_right(1); @@ -9520,11 +9523,11 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_left(1); - tab.horizontal_split(PaneId::Terminal(3), 1); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_right(1); - tab.horizontal_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); tab.move_focus_left(1); tab.resize_right(1); @@ -9718,13 +9721,13 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p rows: 20, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.horizontal_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(5), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_down(1); tab.resize_right(1); @@ -10002,13 +10005,13 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ rows: 20, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.horizontal_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(5), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_down(1); tab.move_focus_left(1); tab.resize_right(1); @@ -10287,17 +10290,17 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo rows: 70, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.horizontal_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(5), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); tab.move_focus_down(1); tab.resize_up(1); - tab.vertical_split(PaneId::Terminal(6), 1); - tab.horizontal_split(PaneId::Terminal(7), 1); - tab.horizontal_split(PaneId::Terminal(8), 1); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(7), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(8), 1).unwrap(); tab.move_focus_up(1); tab.resize_right(1); @@ -10661,18 +10664,18 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab rows: 70, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.horizontal_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(5), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); tab.move_focus_down(1); tab.resize_up(1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_left(1); - tab.horizontal_split(PaneId::Terminal(7), 1); - tab.horizontal_split(PaneId::Terminal(8), 1); + tab.horizontal_split(PaneId::Terminal(7), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(8), 1).unwrap(); tab.move_focus_up(1); tab.resize_right(1); @@ -11031,7 +11034,7 @@ pub fn cannot_resize_right_when_pane_to_the_left_is_at_minimum_width() { // █ == focused pane let size = Size { cols: 10, rows: 20 }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.resize_right(1); assert_eq!( @@ -11073,7 +11076,7 @@ pub fn resize_up_with_pane_above() { rows: 20, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); tab.resize_up(1); assert_eq!( @@ -11178,7 +11181,7 @@ pub fn resize_up_with_pane_below() { rows: 20, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_up(1); tab.resize_up(1); @@ -11287,8 +11290,8 @@ pub fn resize_up_with_panes_above_and_below() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.horizontal_split(PaneId::Terminal(3), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_up(1); tab.resize_up(1); @@ -11436,9 +11439,9 @@ pub fn resize_up_with_multiple_panes_above() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(3), 1); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_down(1); tab.resize_up(1); @@ -11585,11 +11588,11 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(3), 1); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_down(1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.resize_up(1); assert_eq!( @@ -11780,11 +11783,11 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(3), 1); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_down(1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); tab.resize_up(1); @@ -11976,11 +11979,11 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(3), 1); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_down(1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_left(1); tab.resize_up(1); @@ -12172,11 +12175,11 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(3), 1); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_down(1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_left(1); tab.move_focus_up(1); tab.resize_up(1); @@ -12369,12 +12372,12 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.vertical_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(5), 1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_left(1); tab.resize_up(1); @@ -12652,12 +12655,12 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); - tab.vertical_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(5), 1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_left(1); tab.move_focus_up(1); tab.resize_up(1); @@ -12936,16 +12939,16 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_down(1); - tab.vertical_split(PaneId::Terminal(5), 1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_left(1); - tab.vertical_split(PaneId::Terminal(7), 1); - tab.vertical_split(PaneId::Terminal(8), 1); + tab.vertical_split(PaneId::Terminal(7), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(8), 1).unwrap(); tab.move_focus_left(1); tab.resize_up(1); @@ -13309,17 +13312,17 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri rows: 30, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_up(1); - tab.vertical_split(PaneId::Terminal(3), 1); - tab.vertical_split(PaneId::Terminal(4), 1); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(4), 1).unwrap(); tab.move_focus_down(1); - tab.vertical_split(PaneId::Terminal(5), 1); - tab.vertical_split(PaneId::Terminal(6), 1); + tab.vertical_split(PaneId::Terminal(5), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(6), 1).unwrap(); tab.move_focus_up(1); tab.move_focus_left(1); - tab.vertical_split(PaneId::Terminal(7), 1); - tab.vertical_split(PaneId::Terminal(8), 1); + tab.vertical_split(PaneId::Terminal(7), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(8), 1).unwrap(); tab.move_focus_left(1); tab.resize_up(1); @@ -13682,7 +13685,7 @@ pub fn cannot_resize_up_when_pane_above_is_at_minimum_height() { rows: 10, }; let mut tab = create_new_tab(size); - tab.horizontal_split(PaneId::Terminal(2), 1); + tab.horizontal_split(PaneId::Terminal(2), 1).unwrap(); tab.resize_down(1); assert_eq!( @@ -13739,7 +13742,7 @@ pub fn nondirectional_resize_increase_with_1_pane_to_left() { }; let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); - tab.vertical_split(new_pane_id_1, 1); + tab.vertical_split(new_pane_id_1, 1).unwrap(); tab.resize_increase(1); // should behave like `resize_left_with_pane_to_the_left` @@ -13772,9 +13775,9 @@ pub fn nondirectional_resize_increase_with_2_panes_to_left() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_left(1); - tab.horizontal_split(PaneId::Terminal(3), 1); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_right(1); tab.resize_increase(1); @@ -13830,9 +13833,9 @@ pub fn nondirectional_resize_increase_with_1_pane_to_right_1_pane_above() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); tab.move_focus_left(1); - tab.horizontal_split(PaneId::Terminal(3), 1); + tab.horizontal_split(PaneId::Terminal(3), 1).unwrap(); tab.resize_increase(1); assert_eq!( @@ -13886,8 +13889,8 @@ pub fn nondirectional_resize_increase_with_1_pane_to_right_1_pane_to_left() { rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); - tab.vertical_split(PaneId::Terminal(3), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_left(1); tab.resize_increase(1); @@ -13942,8 +13945,8 @@ pub fn nondirectional_resize_increase_with_pane_above_aligned_right_with_current rows: 20, }; let mut tab = create_new_tab(size); - tab.vertical_split(PaneId::Terminal(2), 1); - tab.vertical_split(PaneId::Terminal(3), 1); + tab.vertical_split(PaneId::Terminal(2), 1).unwrap(); + tab.vertical_split(PaneId::Terminal(3), 1).unwrap(); tab.move_focus_left(1); tab.resize_increase(1); diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index 16b962f1..9a08be2a 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -746,7 +746,7 @@ fn switch_to_tab_with_fullscreen() { new_tab(&mut screen, 1); { let active_tab = screen.get_active_tab_mut(1).unwrap(); - active_tab.new_pane(PaneId::Terminal(2), Some(1)); + active_tab.new_pane(PaneId::Terminal(2), Some(1)).unwrap(); active_tab.toggle_active_pane_fullscreen(1); } new_tab(&mut screen, 2); @@ -859,7 +859,7 @@ fn attach_after_first_tab_closed() { new_tab(&mut screen, 1); { let active_tab = screen.get_active_tab_mut(1).unwrap(); - active_tab.new_pane(PaneId::Terminal(2), Some(1)); + active_tab.new_pane(PaneId::Terminal(2), Some(1)).unwrap(); active_tab.toggle_active_pane_fullscreen(1); } new_tab(&mut screen, 2); diff --git a/zellij-utils/Cargo.toml b/zellij-utils/Cargo.toml index 02fad102..0c2ad1e9 100644 --- a/zellij-utils/Cargo.toml +++ b/zellij-utils/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow = "1.0.45" +anyhow = { version = "1.0.45", features = ["backtrace"] } backtrace = "0.3.55" rmp-serde = "1.1.0" clap = { version = "3.2.2", features = ["derive", "env"] } diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs index ec9d4de3..f729c036 100644 --- a/zellij-utils/src/errors.rs +++ b/zellij-utils/src/errors.rs @@ -22,6 +22,8 @@ use thiserror::Error as ThisError; pub mod prelude { pub use super::FatalError; pub use super::LoggableError; + #[cfg(not(target_family = "wasm"))] + pub use super::ToAnyhow; pub use anyhow::anyhow; pub use anyhow::bail; pub use anyhow::Context; @@ -38,10 +40,18 @@ pub trait ErrorInstruction { struct Panic(String); impl Panic { + // We already capture a backtrace with `anyhow` using the `backtrace` crate in the background. + // The advantage is that this is the backtrace of the real errors source (i.e. where we first + // encountered the error and turned it into an `anyhow::Error`), whereas the backtrace recorded + // here is the backtrace leading to the call to any `panic`ing function. Since now we propagate + // errors up before `unwrap`ing them (e.g. in `zellij_server::screen::screen_thread_main`), the + // former is what we really want to diagnose. + // We still keep the second one around just in case the first backtrace isn't meaningful or + // non-existent in the first place (Which really shouldn't happen, but you never know). fn show_backtrace(&self) -> String { if let Ok(var) = std::env::var("RUST_BACKTRACE") { if !var.is_empty() && var != "0" { - return format!("\n{:?}", backtrace::Backtrace::new()); + return format!("\n\nPanic backtrace:\n{:?}", backtrace::Backtrace::new()); } } "".into() @@ -513,4 +523,34 @@ mod not_wasm { Ok(()) } } + + /// Helper trait to convert error types that don't satisfy `anyhow`s trait requirements to + /// anyhow errors. + pub trait ToAnyhow { + fn to_anyhow(self) -> crate::anyhow::Result; + } + + /// `SendError` doesn't satisfy `anyhow`s trait requirements due to `T` possibly being a + /// `PluginInstruction` type, which wraps an `mpsc::Send` and isn't `Sync`. Due to this, in turn, + /// the whole error type isn't `Sync` and doesn't work with `anyhow` (or pretty much any other + /// error handling crate). + /// + /// Takes the `SendError` and creates an `anyhow` error type with the message that was sent + /// (formatted as string), attaching the [`ErrorContext`] as anyhow context to it. + impl ToAnyhow + for Result> + { + fn to_anyhow(self) -> crate::anyhow::Result { + match self { + Ok(val) => crate::anyhow::Ok(val), + Err(e) => { + let (msg, context) = e.into_inner(); + Err( + crate::anyhow::anyhow!("failed to send message to client: {:#?}", msg) + .context(context.to_string()), + ) + }, + } + } + } }