From 7d3e0a1f31d64ffa9e80cdbd68ad5405a16893b7 Mon Sep 17 00:00:00 2001 From: Sagittarius-a Date: Tue, 3 Aug 2021 00:17:17 +0200 Subject: [PATCH] store tab history in a stack-like data structure --- zellij-server/src/screen.rs | 43 ++++++------ zellij-server/src/unit/screen_tests.rs | 96 +++++++++++++++++++++----- 2 files changed, 100 insertions(+), 39 deletions(-) diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index a4d4df4a1a..5db0447610 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -150,7 +150,7 @@ pub(crate) struct Screen { position_and_size: PositionAndSize, /// The index of this [`Screen`]'s active [`Tab`]. active_tab_index: Option, - previous_active_tab_index: Option, + tab_history: Vec>, mode_info: ModeInfo, colors: Palette, session_state: Arc>, @@ -171,8 +171,8 @@ impl Screen { position_and_size: client_attributes.position_and_size, colors: client_attributes.palette, active_tab_index: None, - previous_active_tab_index: None, tabs: BTreeMap::new(), + tab_history: Vec::with_capacity(32), mode_info, session_state, } @@ -196,7 +196,7 @@ impl Screen { self.colors, self.session_state.clone(), ); - self.previous_active_tab_index = self.active_tab_index; + self.tab_history.push(self.active_tab_index); self.active_tab_index = Some(tab_index); self.tabs.insert(tab_index, tab); self.update_tabs(); @@ -222,7 +222,8 @@ impl Screen { for tab in self.tabs.values_mut() { if tab.position == new_tab_pos { tab.set_force_render(); - self.previous_active_tab_index = self.active_tab_index; + self.tab_history.retain(|&e| e != Some(tab.index)); + self.tab_history.push(self.active_tab_index); self.active_tab_index = Some(tab.index); break; } @@ -242,7 +243,8 @@ impl Screen { for tab in self.tabs.values_mut() { if tab.position == new_tab_pos { tab.set_force_render(); - self.previous_active_tab_index = self.active_tab_index; + self.tab_history.retain(|&e| e != Some(tab.index)); + self.tab_history.push(self.active_tab_index); self.active_tab_index = Some(tab.index); break; } @@ -257,7 +259,8 @@ impl Screen { if let Some(t) = self.tabs.values_mut().find(|t| t.position == tab_index) { if t.index != active_tab_index { t.set_force_render(); - self.previous_active_tab_index = self.active_tab_index; + self.tab_history.retain(|&e| e != Some(t.index)); + self.tab_history.push(self.active_tab_index); self.active_tab_index = Some(t.index); self.update_tabs(); self.render(); @@ -268,11 +271,7 @@ impl Screen { /// Closes this [`Screen`]'s active [`Tab`], exiting the application if it happens /// to be the last tab. pub fn close_tab(&mut self) { - let future_previous = self.previous_active_tab_index; let active_tab_index = self.active_tab_index.unwrap(); - if self.tabs.len() > 1 { - self.switch_tab_prev(); - } let active_tab = self.tabs.remove(&active_tab_index).unwrap(); let pane_ids = active_tab.get_pane_ids(); // below we don't check the result of sending the CloseTab instruction to the pty thread @@ -284,7 +283,6 @@ impl Screen { .unwrap(); if self.tabs.is_empty() { self.active_tab_index = None; - self.previous_active_tab_index = None; if *self.session_state.read().unwrap() == SessionState::Attached { self.bus .senders @@ -292,6 +290,7 @@ impl Screen { .unwrap(); } } else { + self.active_tab_index = self.tab_history.pop().unwrap(); for t in self.tabs.values_mut() { if t.position > active_tab.position { t.position -= 1; @@ -299,7 +298,6 @@ impl Screen { } self.update_tabs(); } - self.previous_active_tab_index = future_previous; } pub fn resize_to_screen(&mut self, new_screen_size: PositionAndSize) { @@ -339,8 +337,13 @@ impl Screen { } /// Returns an immutable reference to this [`Screen`]'s previous active [`Tab`]. - pub fn get_previous_tab(&self) -> Option<&Tab> { - match self.previous_active_tab_index { + /// Consumes the last entry in tab history. + pub fn get_previous_tab(&mut self) -> Option<&Tab> { + let last = self.tab_history.pop(); + if last.is_none() { + return None; + } + match last.unwrap() { Some(tab) => self.tabs.get(&tab), None => None, } @@ -373,7 +376,7 @@ impl Screen { self.session_state.clone(), ); tab.apply_layout(layout, new_pids); - self.previous_active_tab_index = self.active_tab_index; + self.tab_history.push(self.active_tab_index); self.active_tab_index = Some(tab_index); self.tabs.insert(tab_index, tab); self.update_tabs(); @@ -431,12 +434,12 @@ impl Screen { } } pub fn toggle_tab(&mut self) { - let active_tab_index = self.active_tab_index.unwrap(); - if self.previous_active_tab_index.is_some() { - let position = self.get_previous_tab().unwrap().position; + let tab = self.get_previous_tab(); + if let Some(t) = tab { + let position = t.position; self.go_to_tab(position + 1); - } - self.previous_active_tab_index = Some(active_tab_index); + }; + self.update_tabs(); self.render(); } diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index 83d8887b00..0d325b1c12 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -195,7 +195,7 @@ pub fn close_the_middle_tab() { assert_eq!(screen.tabs.len(), 2, "Two tabs left"); assert_eq!( screen.get_active_tab().unwrap().position, - 0, + 1, "Active tab switched to previous tab" ); } @@ -294,12 +294,23 @@ pub fn toggle_to_previous_tab_create_tabs_only() { screen.new_tab(2); screen.new_tab(3); + assert_eq!( + screen.tab_history, + vec![None, Some(0), Some(1)], + "Tab history is invalid" + ); + screen.toggle_tab(); assert_eq!( screen.get_active_tab().unwrap().position, 1, "Active tab toggler to previous tab" ); + assert_eq!( + screen.tab_history, + vec![None, Some(0), Some(2)], + "Tab history is invalid" + ); screen.toggle_tab(); assert_eq!( @@ -307,6 +318,11 @@ pub fn toggle_to_previous_tab_create_tabs_only() { 2, "Active tab toggler to previous tab" ); + assert_eq!( + screen.tab_history, + vec![None, Some(0), Some(1)], + "Tab history is invalid" + ); screen.toggle_tab(); assert_eq!( @@ -327,48 +343,90 @@ pub fn toggle_to_previous_tab_delete() { }; let mut screen = create_new_screen(position_and_size); - screen.new_tab(1); - screen.new_tab(2); - screen.new_tab(3); + screen.new_tab(1); // 0 + screen.new_tab(2); // 1 + screen.new_tab(3); // 2 + screen.new_tab(4); // 3 - screen.toggle_tab(); + assert_eq!( + screen.tab_history, + vec![None, Some(0), Some(1), Some(2)], + "Tab history is invalid" + ); assert_eq!( screen.get_active_tab().unwrap().position, - 1, + 3, "Active tab toggler to previous tab" ); + + screen.toggle_tab(); + assert_eq!( + screen.tab_history, + vec![None, Some(0), Some(1), Some(3)], + "Tab history is invalid" + ); assert_eq!( - screen.get_previous_tab().unwrap().position, + screen.get_active_tab().unwrap().position, 2, - "Previous active tab invalid" + "Active tab toggler to previous tab" ); - screen.close_tab(); + screen.toggle_tab(); + assert_eq!( + screen.tab_history, + vec![None, Some(0), Some(1), Some(2)], + "Tab history is invalid" + ); assert_eq!( screen.get_active_tab().unwrap().position, - 0, + 3, "Active tab toggler to previous tab" ); + + screen.switch_tab_prev(); assert_eq!( - screen.get_previous_tab().unwrap().position, - 1, - "Previous active tab invalid" + screen.tab_history, + vec![None, Some(0), Some(1), Some(3)], + "Tab history is invalid" ); assert_eq!( - screen.get_previous_tab().unwrap().index, + screen.get_active_tab().unwrap().position, 2, - "Previous active tab invalid" + "Active tab toggler to previous tab" + ); + screen.switch_tab_prev(); + assert_eq!( + screen.tab_history, + vec![None, Some(0), Some(3), Some(2)], + "Tab history is invalid" + ); + assert_eq!( + screen.get_active_tab().unwrap().position, + 1, + "Active tab toggler to previous tab" ); - screen.toggle_tab(); + screen.close_tab(); + assert_eq!( + screen.tab_history, + vec![None, Some(0), Some(3)], + "Tab history is invalid" + ); assert_eq!( screen.get_active_tab().unwrap().position, 1, "Active tab toggler to previous tab" ); + + screen.toggle_tab(); assert_eq!( - screen.get_previous_tab().unwrap().position, - 0, - "Previous active tab invalid" + screen.get_active_tab().unwrap().position, + 2, + "Active tab toggler to previous tab" + ); + assert_eq!( + screen.tab_history, + vec![None, Some(0), Some(2)], + "Tab history is invalid" ); }