diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane.snap index fdea92b7a..664e881b4 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane.snap @@ -26,4 +26,4 @@ expression: last_snapshot │ ││line19 00000000000000000000000000000000000000000000000000█│ └──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ Ctrl + LOCK 

PANE  TAB  RESIZE  MOVE  SCROLL  SESSION  QUIT  - <↓↑> Scroll / Scroll Page / Select pane + <↓↑> Scroll / Scroll Page / Scroll Half Page / Select pane diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs index 444be5a08..457354916 100644 --- a/zellij-server/src/route.rs +++ b/zellij-server/src/route.rs @@ -183,6 +183,18 @@ fn route_action( .send_to_screen(ScreenInstruction::PageScrollDown(client_id)) .unwrap(); } + Action::HalfPageScrollUp => { + session + .senders + .send_to_screen(ScreenInstruction::HalfPageScrollUp(client_id)) + .unwrap(); + } + Action::HalfPageScrollDown => { + session + .senders + .send_to_screen(ScreenInstruction::HalfPageScrollDown(client_id)) + .unwrap(); + } Action::ToggleFocusFullscreen => { session .senders diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 2a8c54c6a..fb225f78a 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -59,6 +59,8 @@ pub(crate) enum ScreenInstruction { ScrollToBottom(ClientId), PageScrollUp(ClientId), PageScrollDown(ClientId), + HalfPageScrollUp(ClientId), + HalfPageScrollDown(ClientId), ClearScroll(ClientId), CloseFocusedPane(ClientId), ToggleActiveTerminalFullscreen(ClientId), @@ -123,6 +125,8 @@ impl From<&ScreenInstruction> for ScreenContext { ScreenInstruction::ScrollToBottom(..) => ScreenContext::ScrollToBottom, ScreenInstruction::PageScrollUp(..) => ScreenContext::PageScrollUp, ScreenInstruction::PageScrollDown(..) => ScreenContext::PageScrollDown, + ScreenInstruction::HalfPageScrollUp(..) => ScreenContext::HalfPageScrollUp, + ScreenInstruction::HalfPageScrollDown(..) => ScreenContext::HalfPageScrollDown, ScreenInstruction::ClearScroll(..) => ScreenContext::ClearScroll, ScreenInstruction::CloseFocusedPane(..) => ScreenContext::CloseFocusedPane, ScreenInstruction::ToggleActiveTerminalFullscreen(..) => { @@ -848,6 +852,22 @@ pub(crate) fn screen_thread_main( screen.render(); } + ScreenInstruction::HalfPageScrollUp(client_id) => { + screen + .get_active_tab_mut(client_id) + .unwrap() + .scroll_active_terminal_up_half_page(); + + screen.render(); + } + ScreenInstruction::HalfPageScrollDown(client_id) => { + screen + .get_active_tab_mut(client_id) + .unwrap() + .scroll_active_terminal_down_half_page(); + + screen.render(); + } ScreenInstruction::ClearScroll(client_id) => { screen .get_active_tab_mut(client_id) diff --git a/zellij-server/src/tab.rs b/zellij-server/src/tab.rs index ffdf7e647..083984178 100644 --- a/zellij-server/src/tab.rs +++ b/zellij-server/src/tab.rs @@ -2899,8 +2899,8 @@ impl Tab { .get_mut(&PaneId::Terminal(active_terminal_id)) .unwrap(); // prevent overflow when row == 0 - let scroll_columns = active_terminal.rows().max(1) - 1; - active_terminal.scroll_up(scroll_columns); + let scroll_rows = active_terminal.rows().max(1) - 1; + active_terminal.scroll_up(scroll_rows); } } pub fn scroll_active_terminal_down_page(&mut self) { @@ -2910,8 +2910,33 @@ impl Tab { .get_mut(&PaneId::Terminal(active_terminal_id)) .unwrap(); // prevent overflow when row == 0 - let scroll_columns = active_terminal.rows().max(1) - 1; - active_terminal.scroll_down(scroll_columns); + let scroll_rows = active_terminal.rows().max(1) - 1; + active_terminal.scroll_down(scroll_rows); + if !active_terminal.is_scrolled() { + self.process_pending_vte_events(active_terminal_id); + } + } + } + pub fn scroll_active_terminal_up_half_page(&mut self) { + if let Some(active_terminal_id) = self.get_active_terminal_id() { + let active_terminal = self + .panes + .get_mut(&PaneId::Terminal(active_terminal_id)) + .unwrap(); + // prevent overflow when row == 0 + let scroll_rows = (active_terminal.rows().max(1) - 1) / 2; + active_terminal.scroll_up(scroll_rows); + } + } + pub fn scroll_active_terminal_down_half_page(&mut self) { + if let Some(active_terminal_id) = self.get_active_terminal_id() { + let active_terminal = self + .panes + .get_mut(&PaneId::Terminal(active_terminal_id)) + .unwrap(); + // prevent overflow when row == 0 + let scroll_rows = (active_terminal.rows().max(1) - 1) / 2; + active_terminal.scroll_down(scroll_rows); if !active_terminal.is_scrolled() { self.process_pending_vte_events(active_terminal_id); } diff --git a/zellij-utils/assets/config/default.yaml b/zellij-utils/assets/config/default.yaml index b1a1ad2e3..35dc2311d 100644 --- a/zellij-utils/assets/config/default.yaml +++ b/zellij-utils/assets/config/default.yaml @@ -265,6 +265,10 @@ keybinds: key: [Ctrl: 'f', PageDown, Right, Char: 'l',] - action: [PageScrollUp,] key: [Ctrl: 'b', PageUp, Left, Char: 'h',] + - action: [HalfPageScrollDown,] + key: [Char: 'd',] + - action: [HalfPageScrollUp,] + key: [Char: 'u',] - action: [NewPane: ,] key: [ Alt: 'n',] - action: [MoveFocus: Left,] diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs index 6dae0d1ac..7088c30ce 100644 --- a/zellij-utils/src/errors.rs +++ b/zellij-utils/src/errors.rs @@ -239,6 +239,8 @@ pub enum ScreenContext { ScrollToBottom, PageScrollUp, PageScrollDown, + HalfPageScrollUp, + HalfPageScrollDown, ClearScroll, CloseFocusedPane, ToggleActiveSyncTab, diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index 13d3566de..bd43206cf 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -68,6 +68,10 @@ pub enum Action { PageScrollUp, /// Scroll down one page in focus pane. PageScrollDown, + /// Scroll up half page in focus pane. + HalfPageScrollUp, + /// Scroll down half page in focus pane. + HalfPageScrollDown, /// Toggle between fullscreen focus pane and normal layout. ToggleFocusFullscreen, /// Toggle frames around panes in the UI diff --git a/zellij-utils/src/input/mod.rs b/zellij-utils/src/input/mod.rs index c0a0f1aee..613b8d172 100644 --- a/zellij-utils/src/input/mod.rs +++ b/zellij-utils/src/input/mod.rs @@ -51,6 +51,7 @@ pub fn get_mode_info( InputMode::Scroll => vec![ ("↓↑".to_string(), "Scroll".to_string()), ("PgUp/PgDn".to_string(), "Scroll Page".to_string()), + ("u/d".to_string(), "Scroll Half Page".to_string()), ], InputMode::RenameTab => vec![("Enter".to_string(), "when done".to_string())], InputMode::Session => vec![("d".to_string(), "Detach".to_string())],