diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-28 23:12:50 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-28 23:12:50 +0300 |
| commit | 7626a9adc84d6757042670f9816a583dcd717823 (patch) | |
| tree | 56095c659834727ca73b03627a1f6eddc86ac666 /src/ui | |
| parent | 28222b20890a1f6cd36fd477de8e9bc6e5537ff5 (diff) | |
feat: add pane copy mode
refs #231
Diffstat (limited to 'src/ui')
| -rw-r--r-- | src/ui/keybind_help.rs | 1 | ||||
| -rw-r--r-- | src/ui/menus.rs | 33 | ||||
| -rw-r--r-- | src/ui/panes.rs | 26 |
3 files changed, 60 insertions, 0 deletions
diff --git a/src/ui/keybind_help.rs b/src/ui/keybind_help.rs index c3664dec..4fb559c6 100644 --- a/src/ui/keybind_help.rs +++ b/src/ui/keybind_help.rs @@ -126,6 +126,7 @@ pub(super) fn keybind_help_groups( (keybind_label(&kb.close_pane), "close pane"), (keybind_label(&kb.rename_pane), "rename pane"), (keybind_label(&kb.edit_scrollback), "edit scrollback"), + (keybind_label(&kb.copy_mode), "copy mode"), (keybind_label(&kb.zoom), "zoom pane"), (keybind_label(&kb.resize_mode), "resize mode"), (keybind_label(&kb.toggle_sidebar), "toggle sidebar"), diff --git a/src/ui/menus.rs b/src/ui/menus.rs index b711358e..e974d524 100644 --- a/src/ui/menus.rs +++ b/src/ui/menus.rs @@ -60,6 +60,39 @@ pub(super) fn render_prefix_overlay(app: &AppState, frame: &mut Frame, area: Rec render_bottom_bar(frame, overlay_area, line, app.palette.panel_bg); } +pub(super) fn render_copy_mode_overlay(app: &AppState, frame: &mut Frame, area: Rect) { + let key = Style::default() + .fg(app.palette.accent) + .add_modifier(Modifier::BOLD); + let dim = Style::default().fg(app.palette.overlay0); + let mode_style = Style::default() + .fg(panel_contrast_fg(&app.palette)) + .bg(app.palette.accent) + .add_modifier(Modifier::BOLD); + + let select = if app.copy_mode.is_some_and(|copy_mode| copy_mode.selecting) { + "selecting" + } else { + "select" + }; + let line = Line::from(vec![ + Span::styled(" COPY ", mode_style), + Span::raw(" "), + Span::styled("h/j/k/l w/b/e { }", key), + Span::styled(" move ", dim), + Span::styled("v/space", key), + Span::styled(format!(" {select} "), dim), + Span::styled("y/enter", key), + Span::styled(" copy ", dim), + Span::styled("q/esc", key), + Span::styled(" exit", dim), + ]); + + let overlay_y = area.y + area.height.saturating_sub(1); + let overlay_area = Rect::new(area.x, overlay_y, area.width, 1); + render_bottom_bar(frame, overlay_area, line, app.palette.panel_bg); +} + pub(super) fn render_navigate_overlay(app: &AppState, frame: &mut Frame, area: Rect) { let key = Style::default() .fg(app.palette.accent) diff --git a/src/ui/panes.rs b/src/ui/panes.rs index c211ec9d..8c7d1f02 100644 --- a/src/ui/panes.rs +++ b/src/ui/panes.rs @@ -313,10 +313,36 @@ pub(super) fn render_panes( rt.scroll_metrics(), &app.palette, ); + render_copy_mode_cursor(app, frame, info); } } } +fn render_copy_mode_cursor(app: &AppState, frame: &mut Frame, info: &PaneInfo) { + if app.mode != Mode::Copy { + return; + } + let Some(copy_mode) = app.copy_mode else { + return; + }; + if copy_mode.pane_id != info.id + || copy_mode.cursor_row >= info.inner_rect.height + || copy_mode.cursor_col >= info.inner_rect.width + { + return; + } + + let x = info.inner_rect.x + copy_mode.cursor_col; + let y = info.inner_rect.y + copy_mode.cursor_row; + let cell = &mut frame.buffer_mut()[(x, y)]; + cell.set_style( + Style::default() + .fg(panel_contrast_fg(&app.palette)) + .bg(app.palette.accent) + .add_modifier(Modifier::BOLD), + ); +} + fn render_selection_highlight( selection: &Option<crate::selection::Selection>, frame: &mut Frame, |
