diff options
| author | Mark Jaquith <mark@jaquith.me> | 2026-09-14 15:47:53 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-14 21:47:53 +0200 |
| commit | b0f21ed2cb85613050b794bf6c78a7c367a94e0d (patch) | |
| tree | 25c14e09338f5300bedbc8131aa23fab3d37add9 /src/client/shell/overlays.rs | |
| parent | d8b36691d10c6055293ad45324b22af8b8f570e5 (diff) | |
feat: add cursor-based editing to text inputs (#3698)
* feat: add cursor-based editing to text inputs
refs #1803
* fix: preserve dialog actions with associated text
refs #1803
* refactor: simplify text editor outcomes and tests
refs #1803
---------
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
Diffstat (limited to 'src/client/shell/overlays.rs')
| -rw-r--r-- | src/client/shell/overlays.rs | 76 |
1 files changed, 43 insertions, 33 deletions
diff --git a/src/client/shell/overlays.rs b/src/client/shell/overlays.rs index bc3772b1..07417bd0 100644 --- a/src/client/shell/overlays.rs +++ b/src/client/shell/overlays.rs @@ -645,12 +645,10 @@ fn render_rename_overlay( ); let input = Rect::new(i.x, i.y + 2, i.width, 1); b.set_style(input, Style::default().fg(p.text).bg(p.surface0)); - put_text( + let cursor = text_editor::render( b, - input.x, - input.y, - input.width.saturating_sub(1), - &format!(" {}", v.input), + Rect::new(input.x + 1, input.y, input.width.saturating_sub(1), 1), + &v.input, Style::default().fg(p.text).bg(p.surface0), ); let rs = row(i, &[8, 10, 12], 2, 3); @@ -682,12 +680,7 @@ fn render_rename_overlay( navigator_rows: Vec::new(), worktree_search: Rect::default(), worktree_rows: Vec::new(), - cursor: Some(crate::protocol::CursorState { - x: (input.x + 1 + display_width(&v.input)).min(input.right() - 1), - y: input.y, - visible: true, - shape: 0, - }), + cursor, ..OverlayRender::default() }) } @@ -725,11 +718,12 @@ fn render_navigator_overlay( a.y + my, a.width.saturating_sub(mx * 2).max(4), a.height.saturating_sub(my * 2).max(4), - ); + ) + .intersection(a); let i = panel(b, q, p.accent, p.panel_bg)?; let rows = super::aggregate_navigation::navigator_rows(endpoints, active_endpoint_id, n); let search = if n.search_focused { - format!(" / {}", n.query) + " / ".to_owned() } else if let Some(f) = n.filter { format!( " / {}", @@ -755,16 +749,32 @@ fn render_navigator_overlay( .fg(if n.search_focused { p.text } else { p.overlay0 }) .bg(p.panel_bg), ); + let count = format!( + "{} panes", + rows.iter() + .filter(|row| matches!(row.target, ClientNavigatorTarget::Pane { .. })) + .count() + ); + let cursor = if n.search_focused { + text_editor::render( + b, + Rect::new( + i.x + 3, + i.y, + i.width.saturating_sub(4 + display_width(&count)), + 1, + ), + &n.query, + Style::default().fg(p.text).bg(p.panel_bg), + ) + } else { + None + }; put_right_text( b, i, i.y, - &format!( - "{} panes", - rows.iter() - .filter(|row| matches!(row.target, ClientNavigatorTarget::Pane { .. })) - .count() - ), + &count, Style::default().fg(p.overlay0).bg(p.panel_bg), ); put_text( @@ -940,12 +950,7 @@ fn render_navigator_overlay( navigator_rows: row_hits, worktree_search: Rect::default(), worktree_rows: Vec::new(), - cursor: n.search_focused.then(|| crate::protocol::CursorState { - x: i.x + 3 + display_width(&n.query), - y: i.y, - visible: true, - shape: 0, - }), + cursor, ..OverlayRender::default() }) } @@ -1059,7 +1064,7 @@ fn render_help_overlay( sy, i.width, &if h.search_focused { - format!(" / {}", h.query) + " / ".to_owned() } else { " / press / to filter by command or shortcut".to_owned() }, @@ -1067,6 +1072,16 @@ fn render_help_overlay( .fg(if h.search_focused { p.text } else { p.overlay0 }) .bg(p.panel_bg), ); + let cursor = if h.search_focused { + text_editor::render( + b, + Rect::new(i.x + 3, sy, i.width.saturating_sub(3), 1), + &h.query, + Style::default().fg(p.text).bg(p.panel_bg), + ) + } else { + None + }; let body = Rect::new(i.x, i.y + 3, i.width, i.height.saturating_sub(5)); let lines = help_lines(k, &h.query, p); @@ -1126,7 +1141,7 @@ fn render_help_overlay( i.bottom() - 1, i.width, if h.search_focused { - " filter type/backspace · clear ctrl+u · scroll ↑↓/pgup/pgdn · back esc" + " edit ←→/home/end · kill ^u/^k · yank ^y · scroll ↑↓ · back esc" } else { " search / · scroll j/k/↑↓/pgup/pgdn · close esc/enter" }, @@ -1139,12 +1154,7 @@ fn render_help_overlay( help_scrollbar: scrollbar.unwrap_or_default(), help_scroll_metrics: Some(metrics), help_max_scroll: max_scroll, - cursor: h.search_focused.then(|| crate::protocol::CursorState { - x: (i.x + 3 + display_width(&h.query)).min(i.right() - 1), - y: sy, - visible: true, - shape: 0, - }), + cursor, ..OverlayRender::default() }) } |
