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()),