From 4f482f3b6332f8789fc67fc9679343a9536fd3f7 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 | 106 +++++++++++++++++++------ 2 files changed, 105 insertions(+), 44 deletions(-) diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index ca5224df..ef5a4d5a 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -152,7 +152,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>, @@ -173,8 +173,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, } @@ -198,7 +198,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(); @@ -224,7 +224,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; } @@ -244,7 +245,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; } @@ -259,7 +261,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(); @@ -270,11 +273,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 @@ -286,7 +285,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 @@ -294,6 +292,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; @@ -301,7 +300,6 @@ impl Screen { } self.update_tabs(); } - self.previous_active_tab_index = future_previous; } pub fn resize_to_screen(&mut self, new_screen_size: PositionAndSize) { @@ -341,8 +339,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, } @@ -380,7 +383,7 @@ impl Screen { self.session_state.clone(), ); tab.apply_layout(layout, new_pids, tab_index); - 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(); @@ -438,12 +441,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 83d8887b..0d325b1c 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 + + 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, + 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_active_tab().unwrap().position, + 2, + "Active tab toggler to previous 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, + 3, + "Active tab toggler to previous tab" + ); + + screen.switch_tab_prev(); + assert_eq!( + screen.tab_history, + vec![None, Some(0), Some(1), Some(3)], + "Tab history is invalid" + ); + assert_eq!( + screen.get_active_tab().unwrap().position, + 2, + "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" ); - assert_eq!( - screen.get_previous_tab().unwrap().position, - 2, - "Previous active tab invalid" - ); 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, - 0, - "Active tab toggler to previous tab" - ); - assert_eq!( - screen.get_previous_tab().unwrap().position, 1, - "Previous active tab invalid" - ); - assert_eq!( - screen.get_previous_tab().unwrap().index, - 2, - "Previous active tab invalid" + "Active tab toggler to previous tab" ); screen.toggle_tab(); assert_eq!( screen.get_active_tab().unwrap().position, - 1, + 2, "Active tab toggler to previous tab" ); assert_eq!( - screen.get_previous_tab().unwrap().position, - 0, - "Previous active tab invalid" + screen.tab_history, + vec![None, Some(0), Some(2)], + "Tab history is invalid" ); }