diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-30 02:57:48 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-30 02:58:41 +0300 |
| commit | 5e2dc40691e30f90c5fe3b1e60d5074ceb358556 (patch) | |
| tree | b5c23c4e1bbf24f8a7b948deec8d2591a12bfcc9 | |
| parent | 0fa6440d41c31f23ba2126e4b23bc5627705e317 (diff) | |
fix: add copy mode ctrl page navigation
refs #885
| -rw-r--r-- | docs/next/website/src/content/docs/keyboard.mdx | 2 | ||||
| -rw-r--r-- | src/app/input/copy_mode.rs | 36 |
2 files changed, 29 insertions, 9 deletions
diff --git a/docs/next/website/src/content/docs/keyboard.mdx b/docs/next/website/src/content/docs/keyboard.mdx index 07f11362..b8faa755 100644 --- a/docs/next/website/src/content/docs/keyboard.mdx +++ b/docs/next/website/src/content/docs/keyboard.mdx @@ -64,7 +64,7 @@ The full keymap and the binding syntax live in the [keybinding reference](/docs/ ## Copy mode -Press `prefix+[` to enter copy mode for the focused pane. Use `h/j/k/l`, `w/b/e`, and `{`/`}` to move, `v` or Space to start a selection, `y` or Enter to copy it, and `q` or Esc to leave without copying. Mouse drag-select copies without entering copy mode at all. +Press `prefix+[` to enter copy mode for the focused pane. Use `h/j/k/l`, `w/b/e`, `{`/`}`, and `ctrl+b`/`ctrl+f` to move, `v` or Space to start a selection, `y` or Enter to copy it, and `q` or Esc to leave without copying. Mouse drag-select copies without entering copy mode at all. ## Change anything diff --git a/src/app/input/copy_mode.rs b/src/app/input/copy_mode.rs index 967d8d32..b2219d9f 100644 --- a/src/app/input/copy_mode.rs +++ b/src/app/input/copy_mode.rs @@ -126,6 +126,12 @@ impl AppState { } match (key.code, key.modifiers) { + (KeyCode::Char('b'), mods) if mods.contains(KeyModifiers::CONTROL) => { + self.scroll_copy_mode_page(terminal_runtimes, -1, false) + } + (KeyCode::Char('f'), mods) if mods.contains(KeyModifiers::CONTROL) => { + self.scroll_copy_mode_page(terminal_runtimes, 1, false) + } (KeyCode::Char('u'), mods) if mods.contains(KeyModifiers::CONTROL) => { self.scroll_copy_mode_page(terminal_runtimes, -1, true) } @@ -759,19 +765,33 @@ mod tests { } #[tokio::test] - async fn copy_mode_ignores_prefix_key() { - let (mut app, _) = app_with_copy_screen(b"foo bar\n"); + async fn copy_mode_ctrl_b_uses_page_up() { + let bytes = numbered_lines_bytes(64); + let (mut app, pane_id) = app_with_copy_scrollback(&bytes); app.state.enter_copy_mode(&app.terminal_runtimes); - if let Some(copy_mode) = app.state.copy_mode.as_mut() { - copy_mode.cursor_row = 0; - copy_mode.cursor_col = 4; - } + let height = app.state.copy_mode.expect("copy mode").cursor_row + 1; + let expected_lines = copy_mode_page_lines(height, false); app.handle_copy_mode_key(TerminalKey::new(KeyCode::Char('b'), KeyModifiers::CONTROL)); - let copy_mode = app.state.copy_mode.expect("copy mode"); assert_eq!(app.state.mode, Mode::Copy); - assert_eq!(copy_mode.cursor_col, 4); + assert_eq!(copy_mode_offset_from_bottom(&app, pane_id), expected_lines); + } + + #[tokio::test] + async fn copy_mode_ctrl_f_uses_page_down() { + let bytes = numbered_lines_bytes(64); + let (mut app, pane_id) = app_with_copy_scrollback(&bytes); + app.state.enter_copy_mode(&app.terminal_runtimes); + let height = app.state.copy_mode.expect("copy mode").cursor_row + 1; + let page_lines = copy_mode_page_lines(height, false); + app.state + .set_pane_scroll_offset(&app.terminal_runtimes, pane_id, page_lines); + + app.handle_copy_mode_key(TerminalKey::new(KeyCode::Char('f'), KeyModifiers::CONTROL)); + + assert_eq!(app.state.mode, Mode::Copy); + assert_eq!(copy_mode_offset_from_bottom(&app, pane_id), 0); } #[tokio::test] |
