From 5799ea4e5d9456061455244d30da98b899f20b0d Mon Sep 17 00:00:00 2001 From: Sagittarius-a Date: Wed, 21 Jul 2021 23:43:20 +0200 Subject: [PATCH 1/7] feat(tab): add keybind to go to last tab visited Fixes #398. Tab key is used as default for the `GoToLastTab` action. --- zellij-client/src/input_handler.rs | 1 + zellij-server/src/route.rs | 6 +++++ zellij-server/src/screen.rs | 27 +++++++++++++++++++++ zellij-server/src/unit/screen_tests.rs | 31 +++++++++++++++++++++++++ zellij-utils/assets/config/default.yaml | 2 ++ zellij-utils/src/errors.rs | 1 + zellij-utils/src/input/actions.rs | 1 + zellij-utils/src/input/mod.rs | 1 + 8 files changed, 70 insertions(+) diff --git a/zellij-client/src/input_handler.rs b/zellij-client/src/input_handler.rs index f02b5ad8..7f578766 100644 --- a/zellij-client/src/input_handler.rs +++ b/zellij-client/src/input_handler.rs @@ -188,6 +188,7 @@ impl InputHandler { | Action::GoToPreviousTab | Action::CloseTab | Action::GoToTab(_) + | Action::GoToLastTab | Action::MoveFocusOrTab(_) => { self.command_is_executing.blocking_input_thread(); self.os_input diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs index 29a864aa..94c4cb2c 100644 --- a/zellij-server/src/route.rs +++ b/zellij-server/src/route.rs @@ -24,6 +24,12 @@ fn route_action( ) -> bool { let mut should_break = false; match action { + Action::GoToLastTab => { + session + .senders + .send_to_screen(ScreenInstruction::GoToLastTab) + .unwrap(); + } Action::Write(val) => { session .senders diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index b348540f..02abfc1b 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -68,6 +68,7 @@ pub(crate) enum ScreenInstruction { ToggleActiveSyncTab, CloseTab, GoToTab(u32), + GoToLastTab, UpdateTabName(Vec), TerminalResize(PositionAndSize), ChangeMode(ModeInfo), @@ -133,6 +134,7 @@ impl From<&ScreenInstruction> for ScreenContext { ScreenInstruction::MouseRelease(_) => ScreenContext::MouseRelease, ScreenInstruction::MouseHold(_) => ScreenContext::MouseHold, ScreenInstruction::Copy => ScreenContext::Copy, + ScreenInstruction::GoToLastTab => ScreenContext::GoToLastTab, } } } @@ -150,6 +152,7 @@ pub(crate) struct Screen { position_and_size: PositionAndSize, /// The index of this [`Screen`]'s active [`Tab`]. active_tab_index: Option, + last_active_tab_index: Option, mode_info: ModeInfo, colors: Palette, session_state: Arc>, @@ -170,6 +173,7 @@ impl Screen { position_and_size: client_attributes.position_and_size, colors: client_attributes.palette, active_tab_index: None, + last_active_tab_index: None, tabs: BTreeMap::new(), mode_info, session_state, @@ -194,6 +198,7 @@ impl Screen { self.colors, self.session_state.clone(), ); + self.last_active_tab_index = self.active_tab_index; self.active_tab_index = Some(tab_index); self.tabs.insert(tab_index, tab); self.update_tabs(); @@ -219,6 +224,7 @@ impl Screen { for tab in self.tabs.values_mut() { if tab.position == new_tab_pos { tab.set_force_render(); + self.last_active_tab_index = self.active_tab_index; self.active_tab_index = Some(tab.index); break; } @@ -238,6 +244,7 @@ impl Screen { for tab in self.tabs.values_mut() { if tab.position == new_tab_pos { tab.set_force_render(); + self.last_active_tab_index = self.active_tab_index; self.active_tab_index = Some(tab.index); break; } @@ -252,6 +259,7 @@ 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.last_active_tab_index = self.active_tab_index; self.active_tab_index = Some(t.index); self.update_tabs(); self.render(); @@ -277,6 +285,7 @@ impl Screen { .unwrap(); if self.tabs.is_empty() { self.active_tab_index = None; + self.last_active_tab_index = None; if *self.session_state.read().unwrap() == SessionState::Attached { self.bus .senders @@ -361,6 +370,7 @@ impl Screen { self.session_state.clone(), ); tab.apply_layout(layout, new_pids, tab_index); + self.last_active_tab_index = self.active_tab_index; self.active_tab_index = Some(tab_index); self.tabs.insert(tab_index, tab); self.update_tabs(); @@ -417,6 +427,15 @@ impl Screen { self.switch_tab_next(); } } + pub fn go_to_last_tab(&mut self) { + let active_tab_index = self.active_tab_index.unwrap(); + if let Some(i) = self.last_active_tab_index { + self.go_to_tab(i + 1); + } + self.last_active_tab_index = Some(active_tab_index); + self.update_tabs(); + self.render(); + } } // The box is here in order to make the @@ -751,6 +770,14 @@ pub(crate) fn screen_thread_main( ScreenInstruction::Exit => { break; } + ScreenInstruction::GoToLastTab => { + screen.go_to_last_tab(); + screen + .bus + .senders + .send_to_server(ServerInstruction::UnblockInputThread) + .unwrap(); + } } } } diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index df159dde..0ddbdf0b 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -247,3 +247,34 @@ fn move_focus_right_at_right_screen_edge_changes_tab() { "Active tab switched to next" ); } + +#[test] +pub fn switch_to_last_tab() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut screen = create_new_screen(position_and_size); + + screen.new_tab(1); + screen.new_tab(2); + screen.go_to_tab(1); + screen.go_to_tab(2); + + screen.go_to_last_tab(); + assert_eq!( + screen.get_active_tab().unwrap().position, + 0, + "Active tab switched to last tab" + ); + + screen.go_to_last_tab(); + assert_eq!( + screen.get_active_tab().unwrap().position, + 1, + "Active tab switched to last tab" + ); +} diff --git a/zellij-utils/assets/config/default.yaml b/zellij-utils/assets/config/default.yaml index 24ee95f5..2be0911d 100644 --- a/zellij-utils/assets/config/default.yaml +++ b/zellij-utils/assets/config/default.yaml @@ -166,6 +166,8 @@ keybinds: key: [ Char: '8',] - action: [GoToTab: 9,] key: [ Char: '9',] + - action: [GoToLastTab] + key: [ Char: "\t" ] scroll: - action: [SwitchToMode: Normal,] key: [Ctrl: 'r', Ctrl: 's', Char: ' ', diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs index 6a053038..e215a500 100644 --- a/zellij-utils/src/errors.rs +++ b/zellij-utils/src/errors.rs @@ -227,6 +227,7 @@ pub enum ScreenContext { MouseRelease, MouseHold, Copy, + GoToLastTab, } /// Stack call representations corresponding to the different types of [`PtyInstruction`]s. diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index 431a09bf..977c1a48 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -74,6 +74,7 @@ pub enum Action { /// Close the current tab. CloseTab, GoToTab(u32), + GoToLastTab, TabNameInput(Vec), /// Run speficied command in new pane. Run(RunCommandAction), diff --git a/zellij-utils/src/input/mod.rs b/zellij-utils/src/input/mod.rs index 746d5861..8601a63e 100644 --- a/zellij-utils/src/input/mod.rs +++ b/zellij-utils/src/input/mod.rs @@ -37,6 +37,7 @@ pub fn get_mode_info( ("x".to_string(), "Close".to_string()), ("r".to_string(), "Rename".to_string()), ("s".to_string(), "Sync".to_string()), + ("Tab".to_string(), "Last".to_string()), ], InputMode::Scroll => vec![ ("↓↑".to_string(), "Scroll".to_string()), From 734636637dc7446bc8d453b1ba989139dd70b5fa Mon Sep 17 00:00:00 2001 From: Sagittarius-a Date: Fri, 23 Jul 2021 01:32:32 +0200 Subject: [PATCH 2/7] fix: rename variable as stated in pull request --- zellij-server/src/route.rs | 2 +- zellij-server/src/screen.rs | 26 +++++++++++++------------- zellij-utils/src/errors.rs | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs index 94c4cb2c..7092f3e9 100644 --- a/zellij-server/src/route.rs +++ b/zellij-server/src/route.rs @@ -27,7 +27,7 @@ fn route_action( Action::GoToLastTab => { session .senders - .send_to_screen(ScreenInstruction::GoToLastTab) + .send_to_screen(ScreenInstruction::ToggleTab) .unwrap(); } Action::Write(val) => { diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 02abfc1b..bbba69d9 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -68,7 +68,7 @@ pub(crate) enum ScreenInstruction { ToggleActiveSyncTab, CloseTab, GoToTab(u32), - GoToLastTab, + ToggleTab, UpdateTabName(Vec), TerminalResize(PositionAndSize), ChangeMode(ModeInfo), @@ -134,7 +134,7 @@ impl From<&ScreenInstruction> for ScreenContext { ScreenInstruction::MouseRelease(_) => ScreenContext::MouseRelease, ScreenInstruction::MouseHold(_) => ScreenContext::MouseHold, ScreenInstruction::Copy => ScreenContext::Copy, - ScreenInstruction::GoToLastTab => ScreenContext::GoToLastTab, + ScreenInstruction::ToggleTab => ScreenContext::ToggleTab, } } } @@ -152,7 +152,7 @@ pub(crate) struct Screen { position_and_size: PositionAndSize, /// The index of this [`Screen`]'s active [`Tab`]. active_tab_index: Option, - last_active_tab_index: Option, + previous_active_tab_index: Option, mode_info: ModeInfo, colors: Palette, session_state: Arc>, @@ -173,7 +173,7 @@ impl Screen { position_and_size: client_attributes.position_and_size, colors: client_attributes.palette, active_tab_index: None, - last_active_tab_index: None, + previous_active_tab_index: None, tabs: BTreeMap::new(), mode_info, session_state, @@ -198,7 +198,7 @@ impl Screen { self.colors, self.session_state.clone(), ); - self.last_active_tab_index = self.active_tab_index; + self.previous_active_tab_index = self.active_tab_index; self.active_tab_index = Some(tab_index); self.tabs.insert(tab_index, tab); self.update_tabs(); @@ -224,7 +224,7 @@ impl Screen { for tab in self.tabs.values_mut() { if tab.position == new_tab_pos { tab.set_force_render(); - self.last_active_tab_index = self.active_tab_index; + self.previous_active_tab_index = self.active_tab_index; self.active_tab_index = Some(tab.index); break; } @@ -244,7 +244,7 @@ impl Screen { for tab in self.tabs.values_mut() { if tab.position == new_tab_pos { tab.set_force_render(); - self.last_active_tab_index = self.active_tab_index; + self.previous_active_tab_index = self.active_tab_index; self.active_tab_index = Some(tab.index); break; } @@ -259,7 +259,7 @@ 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.last_active_tab_index = self.active_tab_index; + self.previous_active_tab_index = self.active_tab_index; self.active_tab_index = Some(t.index); self.update_tabs(); self.render(); @@ -285,7 +285,7 @@ impl Screen { .unwrap(); if self.tabs.is_empty() { self.active_tab_index = None; - self.last_active_tab_index = None; + self.previous_active_tab_index = None; if *self.session_state.read().unwrap() == SessionState::Attached { self.bus .senders @@ -370,7 +370,7 @@ impl Screen { self.session_state.clone(), ); tab.apply_layout(layout, new_pids, tab_index); - self.last_active_tab_index = self.active_tab_index; + self.previous_active_tab_index = self.active_tab_index; self.active_tab_index = Some(tab_index); self.tabs.insert(tab_index, tab); self.update_tabs(); @@ -429,10 +429,10 @@ impl Screen { } pub fn go_to_last_tab(&mut self) { let active_tab_index = self.active_tab_index.unwrap(); - if let Some(i) = self.last_active_tab_index { + if let Some(i) = self.previous_active_tab_index { self.go_to_tab(i + 1); } - self.last_active_tab_index = Some(active_tab_index); + self.previous_active_tab_index = Some(active_tab_index); self.update_tabs(); self.render(); } @@ -770,7 +770,7 @@ pub(crate) fn screen_thread_main( ScreenInstruction::Exit => { break; } - ScreenInstruction::GoToLastTab => { + ScreenInstruction::ToggleTab => { screen.go_to_last_tab(); screen .bus diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs index e215a500..e94e43c5 100644 --- a/zellij-utils/src/errors.rs +++ b/zellij-utils/src/errors.rs @@ -227,7 +227,7 @@ pub enum ScreenContext { MouseRelease, MouseHold, Copy, - GoToLastTab, + ToggleTab, } /// Stack call representations corresponding to the different types of [`PtyInstruction`]s. From 404faf0498630eaa6ab17141b1ca1f9e5c53b9c3 Mon Sep 17 00:00:00 2001 From: Sagittarius-a Date: Fri, 23 Jul 2021 22:38:02 +0200 Subject: [PATCH 3/7] fix: fix toggle to previous tab when deleting tabs --- zellij-server/src/screen.rs | 19 ++++- zellij-server/src/unit/screen_tests.rs | 104 +++++++++++++++++++++++-- zellij-utils/src/input/mod.rs | 2 +- 3 files changed, 115 insertions(+), 10 deletions(-) diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index bbba69d9..95b4b01f 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -270,6 +270,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(); @@ -300,6 +301,7 @@ impl Screen { } self.update_tabs(); } + self.previous_active_tab_index = future_previous; } pub fn resize_to_screen(&mut self, new_screen_size: PositionAndSize) { @@ -338,6 +340,14 @@ 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 { + Some(tab) => self.tabs.get(&tab), + None => None, + } + } + /// Returns a mutable reference to this [`Screen`]'s active [`Tab`]. pub fn get_active_tab_mut(&mut self) -> Option<&mut Tab> { match self.active_tab_index { @@ -427,10 +437,11 @@ impl Screen { self.switch_tab_next(); } } - pub fn go_to_last_tab(&mut self) { + pub fn toggle_tab(&mut self) { let active_tab_index = self.active_tab_index.unwrap(); - if let Some(i) = self.previous_active_tab_index { - self.go_to_tab(i + 1); + if let Some(_) = self.previous_active_tab_index { + let position = self.get_previous_tab().unwrap().position; + self.go_to_tab(position + 1); } self.previous_active_tab_index = Some(active_tab_index); self.update_tabs(); @@ -771,7 +782,7 @@ pub(crate) fn screen_thread_main( break; } ScreenInstruction::ToggleTab => { - screen.go_to_last_tab(); + screen.toggle_tab(); screen .bus .senders diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index 0ddbdf0b..83d8887b 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -249,7 +249,7 @@ fn move_focus_right_at_right_screen_edge_changes_tab() { } #[test] -pub fn switch_to_last_tab() { +pub fn toggle_to_previous_tab_simple() { let position_and_size = PositionAndSize { cols: 121, rows: 20, @@ -264,17 +264,111 @@ pub fn switch_to_last_tab() { screen.go_to_tab(1); screen.go_to_tab(2); - screen.go_to_last_tab(); + screen.toggle_tab(); assert_eq!( screen.get_active_tab().unwrap().position, 0, - "Active tab switched to last tab" + "Active tab toggler to previous tab" ); - screen.go_to_last_tab(); + screen.toggle_tab(); assert_eq!( screen.get_active_tab().unwrap().position, 1, - "Active tab switched to last tab" + "Active tab toggler to previous tab" + ); +} + +#[test] +pub fn toggle_to_previous_tab_create_tabs_only() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut screen = create_new_screen(position_and_size); + + screen.new_tab(1); + screen.new_tab(2); + screen.new_tab(3); + + screen.toggle_tab(); + assert_eq!( + screen.get_active_tab().unwrap().position, + 1, + "Active tab toggler to previous tab" + ); + + screen.toggle_tab(); + assert_eq!( + screen.get_active_tab().unwrap().position, + 2, + "Active tab toggler to previous tab" + ); + + screen.toggle_tab(); + assert_eq!( + screen.get_active_tab().unwrap().position, + 1, + "Active tab toggler to previous tab" + ); +} + +#[test] +pub fn toggle_to_previous_tab_delete() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut screen = create_new_screen(position_and_size); + + screen.new_tab(1); + screen.new_tab(2); + screen.new_tab(3); + + screen.toggle_tab(); + 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.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" + ); + + screen.toggle_tab(); + assert_eq!( + screen.get_active_tab().unwrap().position, + 1, + "Active tab toggler to previous tab" + ); + assert_eq!( + screen.get_previous_tab().unwrap().position, + 0, + "Previous active tab invalid" ); } diff --git a/zellij-utils/src/input/mod.rs b/zellij-utils/src/input/mod.rs index 8601a63e..ad728747 100644 --- a/zellij-utils/src/input/mod.rs +++ b/zellij-utils/src/input/mod.rs @@ -37,7 +37,7 @@ pub fn get_mode_info( ("x".to_string(), "Close".to_string()), ("r".to_string(), "Rename".to_string()), ("s".to_string(), "Sync".to_string()), - ("Tab".to_string(), "Last".to_string()), + ("Tab".to_string(), "Toggle".to_string()), ], InputMode::Scroll => vec![ ("↓↑".to_string(), "Scroll".to_string()), From 081c55458d95f310ad3b60547c054a5fc2dd6bda Mon Sep 17 00:00:00 2001 From: Sagittarius-a Date: Fri, 23 Jul 2021 22:51:22 +0200 Subject: [PATCH 4/7] fix: rename action to ToggleTab --- zellij-client/src/input_handler.rs | 2 +- zellij-server/src/route.rs | 2 +- zellij-utils/assets/config/default.yaml | 2 +- zellij-utils/src/input/actions.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zellij-client/src/input_handler.rs b/zellij-client/src/input_handler.rs index 7f578766..d262bfa9 100644 --- a/zellij-client/src/input_handler.rs +++ b/zellij-client/src/input_handler.rs @@ -188,7 +188,7 @@ impl InputHandler { | Action::GoToPreviousTab | Action::CloseTab | Action::GoToTab(_) - | Action::GoToLastTab + | Action::ToggleTab | Action::MoveFocusOrTab(_) => { self.command_is_executing.blocking_input_thread(); self.os_input diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs index 7092f3e9..92a89966 100644 --- a/zellij-server/src/route.rs +++ b/zellij-server/src/route.rs @@ -24,7 +24,7 @@ fn route_action( ) -> bool { let mut should_break = false; match action { - Action::GoToLastTab => { + Action::ToggleTab => { session .senders .send_to_screen(ScreenInstruction::ToggleTab) diff --git a/zellij-utils/assets/config/default.yaml b/zellij-utils/assets/config/default.yaml index 2be0911d..0b102d70 100644 --- a/zellij-utils/assets/config/default.yaml +++ b/zellij-utils/assets/config/default.yaml @@ -166,7 +166,7 @@ keybinds: key: [ Char: '8',] - action: [GoToTab: 9,] key: [ Char: '9',] - - action: [GoToLastTab] + - action: [ToggleTab] key: [ Char: "\t" ] scroll: - action: [SwitchToMode: Normal,] diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index 977c1a48..589b3935 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -74,7 +74,7 @@ pub enum Action { /// Close the current tab. CloseTab, GoToTab(u32), - GoToLastTab, + ToggleTab, TabNameInput(Vec), /// Run speficied command in new pane. Run(RunCommandAction), From aff99736168dcfcfc70ad40cb23dbd207faa17c5 Mon Sep 17 00:00:00 2001 From: Sagittarius-a Date: Fri, 23 Jul 2021 23:04:58 +0200 Subject: [PATCH 5/7] fix: fix clippy warning --- zellij-server/src/screen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 95b4b01f..ca5224df 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -439,7 +439,7 @@ impl Screen { } pub fn toggle_tab(&mut self) { let active_tab_index = self.active_tab_index.unwrap(); - if let Some(_) = self.previous_active_tab_index { + if self.previous_active_tab_index.is_some() { let position = self.get_previous_tab().unwrap().position; self.go_to_tab(position + 1); } From 4f482f3b6332f8789fc67fc9679343a9536fd3f7 Mon Sep 17 00:00:00 2001 From: Sagittarius-a Date: Tue, 3 Aug 2021 00:17:17 +0200 Subject: [PATCH 6/7] 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" ); } From 24ef96b96510d3efba78a965364bab992a8a92fb Mon Sep 17 00:00:00 2001 From: Sagittarius-a Date: Tue, 3 Aug 2021 22:16:40 +0200 Subject: [PATCH 7/7] fix cargo clippy lint --- zellij-server/src/screen.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index ef5a4d5a..c6c0f3a8 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -342,9 +342,7 @@ impl Screen { /// 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; - } + last?; match last.unwrap() { Some(tab) => self.tabs.get(&tab), None => None,