diff options
-rw-r--r-- | zellij-server/src/route.rs | 6 | ||||
-rw-r--r-- | zellij-server/src/screen.rs | 12 | ||||
-rw-r--r-- | zellij-server/src/tab/mod.rs | 10 | ||||
-rw-r--r-- | zellij-server/src/unit/screen_tests.rs | 47 | ||||
-rw-r--r-- | zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action-2.snap | 16 | ||||
-rw-r--r-- | zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action-3.snap | 6 | ||||
-rw-r--r-- | zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action.snap | 16 | ||||
-rw-r--r-- | zellij-utils/src/cli.rs | 2 | ||||
-rw-r--r-- | zellij-utils/src/errors.rs | 1 | ||||
-rw-r--r-- | zellij-utils/src/input/actions.rs | 3 | ||||
-rw-r--r-- | zellij-utils/src/kdl/mod.rs | 4 |
11 files changed, 123 insertions, 0 deletions
diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs index 5b5e437ee..2ca58cc44 100644 --- a/zellij-server/src/route.rs +++ b/zellij-server/src/route.rs @@ -207,6 +207,12 @@ pub(crate) fn route_action( .send_to_screen(ScreenInstruction::ScrollToBottom(client_id)) .with_context(err_context)?; }, + Action::ScrollToTop => { + session + .senders + .send_to_screen(ScreenInstruction::ScrollToTop(client_id)) + .with_context(err_context)?; + }, Action::PageScrollUp => { session .senders diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index b2fdf4f80..fdca620d9 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -161,6 +161,7 @@ pub enum ScreenInstruction { ScrollDown(ClientId), ScrollDownAt(Position, ClientId), ScrollToBottom(ClientId), + ScrollToTop(ClientId), PageScrollUp(ClientId), PageScrollDown(ClientId), HalfPageScrollUp(ClientId), @@ -294,6 +295,7 @@ impl From<&ScreenInstruction> for ScreenContext { ScreenInstruction::ScrollUp(..) => ScreenContext::ScrollUp, ScreenInstruction::ScrollDown(..) => ScreenContext::ScrollDown, ScreenInstruction::ScrollToBottom(..) => ScreenContext::ScrollToBottom, + ScreenInstruction::ScrollToTop(..) => ScreenContext::ScrollToTop, ScreenInstruction::PageScrollUp(..) => ScreenContext::PageScrollUp, ScreenInstruction::PageScrollDown(..) => ScreenContext::PageScrollDown, ScreenInstruction::HalfPageScrollUp(..) => ScreenContext::HalfPageScrollUp, @@ -1744,6 +1746,16 @@ pub(crate) fn screen_thread_main( screen.render()?; screen.unblock_input()?; }, + ScreenInstruction::ScrollToTop(client_id) => { + active_tab_and_connected_client_id!( + screen, + client_id, + |tab: &mut Tab, client_id: ClientId| tab + .scroll_active_terminal_to_top(client_id), ? + ); + screen.render()?; + screen.unblock_input()?; + }, ScreenInstruction::PageScrollUp(client_id) => { active_tab_and_connected_client_id!( screen, diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index 093237eae..0dcd7ba58 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -2046,6 +2046,16 @@ impl Tab { Ok(()) } + pub fn scroll_active_terminal_to_top(&mut self, client_id: ClientId) -> Result<()> { + if let Some(active_pane) = self.get_active_pane_or_floating_pane_mut(client_id) { + active_pane.clear_scroll(); + if let Some(size) = active_pane.get_line_number() { + active_pane.scroll_up(size, client_id); + } + } + Ok(()) + } + pub fn clear_active_terminal_scroll(&mut self, client_id: ClientId) -> Result<()> { // TODO: is this a thing? let err_context = diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index dd212c322..e9b399618 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -1521,6 +1521,53 @@ pub fn send_cli_scroll_to_bottom_action() { } #[test] +pub fn send_cli_scroll_to_top_action() { + let size = Size { cols: 80, rows: 10 }; + let client_id = 10; // fake client id should not appear in the screen's state + let mut initial_layout = PaneLayout::default(); + initial_layout.children_split_direction = SplitDirection::Vertical; + initial_layout.children = vec![PaneLayout::default(), PaneLayout::default()]; + let mut mock_screen = MockScreen::new(size); + let session_metadata = mock_screen.clone_session_metadata(); + let screen_thread = mock_screen.run(Some(initial_layout)); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_instruction = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + let scroll_to_top_action = CliAction::ScrollToTop; + let mut pane_contents = String::new(); + for i in 0..20 { + pane_contents.push_str(&format!("fill pane up with something {}\n\r", i)); + } + let _ = mock_screen.to_screen.send(ScreenInstruction::PtyBytes( + 0, + pane_contents.as_bytes().to_vec(), + )); + std::thread::sleep(std::time::Duration::from_millis(100)); + // scroll to top + send_cli_action_to_server( + &session_metadata, + scroll_to_top_action.clone(), + &mut mock_screen, + client_id, + ); + std::thread::sleep(std::time::Duration::from_millis(100)); + mock_screen.teardown(vec![server_instruction, screen_thread]); + let snapshots = take_snapshots_and_cursor_coordinates_from_render_events( + received_server_instructions.lock().unwrap().iter(), + size, + ); + let snapshot_count = snapshots.len(); + for (_cursor_coordinates, snapshot) in snapshots { + assert_snapshot!(format!("{}", snapshot)); + } + assert_snapshot!(format!("{}", snapshot_count)); +} + +#[test] pub fn send_cli_page_scroll_up_action() { let size = Size { cols: 80, rows: 10 }; let client_id = 10; // fake client id should not appear in the screen's state diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action-2.snap new file mode 100644 index 000000000..e0a5a3fd9 --- /dev/null +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action-2.snap @@ -0,0 +1,16 @@ +--- +source: zellij-server/src/./unit/screen_tests.rs +assertion_line: 1565 +expression: "format!(\"{}\", snapshot)" +--- +00 (C): ┌ Pane #1 ───────────── SCROLL: 13/13 ┐┌ Pane #2 ─────────────────────────────┐ +01 (C): │fill pane up with something 0 ││ │ +02 (C): │fill pane up with something 1 ││ │ +03 (C): │fill pane up with something 2 ││ │ +04 (C): │fill pane up with something 3 ││ │ +05 (C): │fill pane up with something 4 ││ │ +06 (C): │fill pane up with something 5 ││ │ +07 (C): │fill pane up with something 6 ││ │ +08 (C): │fill pane up with something 7 ││ │ +09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ + diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action-3.snap new file mode 100644 index 000000000..526a865ca --- /dev/null +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action-3.snap @@ -0,0 +1,6 @@ +--- +source: zellij-server/src/./unit/screen_tests.rs +assertion_line: 1567 +expression: "format!(\"{}\", snapshot_count)" +--- +2 diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action.snap new file mode 100644 index 000000000..0555f99f3 --- /dev/null +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action.snap @@ -0,0 +1,16 @@ +--- +source: zellij-server/src/./unit/screen_tests.rs +assertion_line: 1565 +expression: "format!(\"{}\", snapshot)" +--- +00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ +01 (C): │ ││ │ +02 (C): │ ││ │ +03 (C): │ ││ │ +04 (C): │ ││ │ +05 (C): │ ││ │ +06 (C): │ ││ │ +07 (C): │ ││ │ +08 (C): │ ││ │ +09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ + diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs index 1d62e7d07..82c34eecd 100644 --- a/zellij-utils/src/cli.rs +++ b/zellij-utils/src/cli.rs @@ -216,6 +216,8 @@ pub enum CliAction { ScrollDown, /// Scroll down to bottom in focus pane. ScrollToBottom, + /// Scroll up to top in focus pane. + ScrollToTop, /// Scroll up one page in focus pane. PageScrollUp, /// Scroll down one page in focus pane. diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs index b56bd79a1..50c8f9b28 100644 --- a/zellij-utils/src/errors.rs +++ b/zellij-utils/src/errors.rs @@ -261,6 +261,7 @@ pub enum ScreenContext { ScrollDown, ScrollDownAt, ScrollToBottom, + ScrollToTop, PageScrollUp, PageScrollDown, HalfPageScrollUp, diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index 7bb13540c..1207023aa 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -128,6 +128,8 @@ pub enum Action { ScrollDownAt(Position), /// Scroll down to bottom in focus pane. ScrollToBottom, + /// Scroll up to top in focus pane. + ScrollToTop, /// Scroll up one page in focus pane. PageScrollUp, /// Scroll down one page in focus pane. @@ -226,6 +228,7 @@ impl Action { CliAction::ScrollUp => Ok(vec![Action::ScrollUp]), CliAction::ScrollDown => Ok(vec![Action::ScrollDown]), CliAction::ScrollToBottom => Ok(vec![Action::ScrollToBottom]), + CliAction::ScrollToTop => Ok(vec![Action::ScrollToTop]), CliAction::PageScrollUp => Ok(vec![Action::PageScrollUp]), CliAction::PageScrollDown => Ok(vec![Action::PageScrollDown]), CliAction::HalfPageScrollUp => Ok(vec![Action::HalfPageScrollUp]), diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs index db001fb5f..2a81300ca 100644 --- a/zellij-utils/src/kdl/mod.rs +++ b/zellij-utils/src/kdl/mod.rs @@ -43,6 +43,7 @@ macro_rules! parse_kdl_action_arguments { "ScrollUp" => Ok(Action::ScrollUp), "ScrollDown" => Ok(Action::ScrollDown), "ScrollToBottom" => Ok(Action::ScrollToBottom), + "ScrollToTop" => Ok(Action::ScrollToTop), "PageScrollUp" => Ok(Action::PageScrollUp), "PageScrollDown" => Ok(Action::PageScrollDown), "HalfPageScrollUp" => Ok(Action::HalfPageScrollUp), @@ -636,6 +637,9 @@ impl TryFrom<&KdlNode> for Action { "ScrollToBottom" => { parse_kdl_action_arguments!(action_name, action_arguments, kdl_action) }, + "ScrollToTop" => { + parse_kdl_action_arguments!(action_name, action_arguments, kdl_action) + }, "PageScrollUp" => { parse_kdl_action_arguments!(action_name, action_arguments, kdl_action) }, |