aboutsummaryrefslogtreecommitdiff
path: root/src/client/shell/overlays.rs
diff options
context:
space:
mode:
authorMark Jaquith <mark@jaquith.me>2026-09-14 15:47:53 -0400
committerGitHub <noreply@github.com>2026-09-14 21:47:53 +0200
commitb0f21ed2cb85613050b794bf6c78a7c367a94e0d (patch)
tree25c14e09338f5300bedbc8131aa23fab3d37add9 /src/client/shell/overlays.rs
parentd8b36691d10c6055293ad45324b22af8b8f570e5 (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.rs76
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()
})
}