diff options
author | Aram Drevekenin <aram@poor.dev> | 2024-02-26 10:48:02 +0100 |
---|---|---|
committer | Aram Drevekenin <aram@poor.dev> | 2024-02-26 10:48:02 +0100 |
commit | 5071b54b26eb6bede1760e1dd5540c8959b108f5 (patch) | |
tree | f5a7aa488ece8f21c17350bb3ec14ceaf15f60a7 /zellij-server/src/screen.rs | |
parent | af17598f3d121fe0373d7f766b17cd437ce0ab49 (diff) | |
parent | 27bffbf1533b4b2d3c10b1305557c75ddd121374 (diff) |
Merge branch 'main' into plugin-aliasesplugin-aliases
Diffstat (limited to 'zellij-server/src/screen.rs')
-rw-r--r-- | zellij-server/src/screen.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 2e351cff4..4594fe3cb 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -7,6 +7,7 @@ use std::rc::Rc; use std::str; use std::time::Duration; +use log::{debug, warn}; use zellij_utils::data::{ Direction, PaneManifest, PluginPermission, Resize, ResizeStrategy, SessionInfo, }; @@ -238,6 +239,8 @@ pub enum ScreenInstruction { ToggleTab(ClientId), UpdateTabName(Vec<u8>, ClientId), UndoRenameTab(ClientId), + MoveTabLeft(ClientId), + MoveTabRight(ClientId), TerminalResize(Size), TerminalPixelDimensions(PixelDimensions), TerminalBackgroundColor(String), @@ -447,6 +450,8 @@ impl From<&ScreenInstruction> for ScreenContext { ScreenInstruction::GoToTabName(..) => ScreenContext::GoToTabName, ScreenInstruction::UpdateTabName(..) => ScreenContext::UpdateTabName, ScreenInstruction::UndoRenameTab(..) => ScreenContext::UndoRenameTab, + ScreenInstruction::MoveTabLeft(..) => ScreenContext::MoveTabLeft, + ScreenInstruction::MoveTabRight(..) => ScreenContext::MoveTabRight, ScreenInstruction::TerminalResize(..) => ScreenContext::TerminalResize, ScreenInstruction::TerminalPixelDimensions(..) => { ScreenContext::TerminalPixelDimensions @@ -1585,6 +1590,91 @@ impl Screen { } } + pub fn move_active_tab_to_left(&mut self, client_id: ClientId) -> Result<()> { + if self.tabs.len() < 2 { + debug!("cannot move tab to left: only one tab exists"); + return Ok(()); + } + let Some(client_id) = self.client_id(client_id) else { + return Ok(()); + }; + let Some(&active_tab_idx) = self.active_tab_indices.get(&client_id) else { + return Ok(()); + }; + + // wraps around: [tab1, tab2, tab3] => [tab1, tab2, tab3] + // ^ ^ + // active_tab_idx left_tab_idx + let left_tab_idx = (active_tab_idx + self.tabs.len() - 1) % self.tabs.len(); + + self.switch_tabs(active_tab_idx, left_tab_idx, client_id); + self.log_and_report_session_state() + .context("failed to move tab to left")?; + Ok(()) + } + + fn client_id(&mut self, client_id: ClientId) -> Option<u16> { + if self.get_active_tab(client_id).is_ok() { + Some(client_id) + } else { + self.get_first_client_id() + } + } + + fn switch_tabs(&mut self, active_tab_idx: usize, other_tab_idx: usize, client_id: u16) { + if !self.tabs.contains_key(&active_tab_idx) || !self.tabs.contains_key(&other_tab_idx) { + warn!( + "failed to switch tabs: index {} or {} not found in {:?}", + active_tab_idx, + other_tab_idx, + self.tabs.keys() + ); + return; + } + + // NOTE: Can `expect` here, because we checked that the keys exist above + let mut active_tab = self + .tabs + .remove(&active_tab_idx) + .expect("active tab not found"); + let mut other_tab = self + .tabs + .remove(&other_tab_idx) + .expect("other tab not found"); + + std::mem::swap(&mut active_tab.index, &mut other_tab.index); + std::mem::swap(&mut active_tab.position, &mut other_tab.position); + + // now, `active_tab.index` is changed, so we need to update it + self.active_tab_indices.insert(client_id, active_tab.index); + + self.tabs.insert(active_tab.index, active_tab); + self.tabs.insert(other_tab.index, other_tab); + } + + pub fn move_active_tab_to_right(&mut self, client_id: ClientId) -> Result<()> { + if self.tabs.len() < 2 { + debug!("cannot move tab to right: only one tab exists"); + return Ok(()); + } + let Some(client_id) = self.client_id(client_id) else { + return Ok(()); + }; + let Some(&active_tab_idx) = self.active_tab_indices.get(&client_id) else { + return Ok(()); + }; + + // wraps around: [tab1, tab2, tab3] => [tab1, tab2, tab3] + // ^ ^ + // active_tab_idx right_tab_idx + let right_tab_idx = (active_tab_idx + 1) % self.tabs.len(); + + self.switch_tabs(active_tab_idx, right_tab_idx, client_id); + self.log_and_report_session_state() + .context("failed to move active tab to right")?; + Ok(()) + } + pub fn change_mode(&mut self, mut mode_info: ModeInfo, client_id: ClientId) -> Result<()> { if mode_info.session_name.as_ref() != Some(&self.session_name) { mode_info.session_name = Some(self.session_name.clone()); @@ -2989,6 +3079,16 @@ pub(crate) fn screen_thread_main( screen.unblock_input()?; screen.render(None)?; }, + ScreenInstruction::MoveTabLeft(client_id) => { + screen.move_active_tab_to_left(client_id)?; + screen.unblock_input()?; + screen.render(None)?; + }, + ScreenInstruction::MoveTabRight(client_id) => { + screen.move_active_tab_to_right(client_id)?; + screen.unblock_input()?; + screen.render(None)?; + }, ScreenInstruction::TerminalResize(new_size) => { screen.resize_to_screen(new_size)?; screen.log_and_report_session_state()?; // update tabs so that the ui indication will be send to the plugins |