fix(ui): resize input area for wrapped text

This commit is contained in:
2026-06-22 12:39:48 -05:00
parent e2b9d27e20
commit 2ae4eda0a1
+49 -6
View File
@@ -105,7 +105,7 @@ fn main_layout(area: Rect, input: &str, menu_height: u16) -> std::rc::Rc<[Rect]>
.constraints([
Constraint::Min(3),
Constraint::Length(menu_height),
Constraint::Length(input_height(input)),
Constraint::Length(input_height(input, area.width)),
Constraint::Length(1),
])
.split(area)
@@ -439,12 +439,31 @@ fn truncate_middle(s: &str, max: usize) -> String {
format!("{start}…{end}")
}
fn input_height(input: &str) -> u16 {
let mut lines = input.lines().count().max(1) as u16;
if input.ends_with('\n') {
lines = lines.saturating_add(1);
fn input_height(input: &str, available_width: u16) -> u16 {
// The first line has a 2-char prefix ("› " or "… ") and continuation
// lines have a 2-char indent (" "), so the content width is always
// available_width - 2. Count word-wrapped rows so that a single long
// line grows the input area instead of overflowing horizontally.
let prefix_width = 2usize;
let content_width = available_width
.saturating_sub(prefix_width as u16) as usize;
let content_width = content_width.max(1);
let mut rows = 0u16;
let lines: Vec<&str> = if input.is_empty() {
vec![""]
} else {
input.lines().collect()
};
for line in &lines {
rows = rows.saturating_add(
ratatui_wrapped_row_count(line, content_width) as u16,
);
}
lines.clamp(1, 6)
if input.ends_with('\n') {
rows = rows.saturating_add(1);
}
rows.max(1).clamp(1, 6)
}
#[cfg(test)]
@@ -475,6 +494,30 @@ mod tests {
assert_eq!(max_transcript_scroll(&transcript, false, false, area), 0);
}
#[test]
fn input_height_wraps_long_line() {
// A single long line with no newlines should occupy more than 1 row
// when the terminal is narrow.
let long = "word ".repeat(40);
assert!(input_height(&long, 20) > 1);
}
#[test]
fn input_height_short_line_is_one_row() {
assert_eq!(input_height("hello", 80), 1);
}
#[test]
fn input_height_counts_explicit_newlines() {
assert_eq!(input_height("line1\nline2\nline3", 80), 3);
}
#[test]
fn input_height_clamps_at_six() {
let long = "word ".repeat(400);
assert_eq!(input_height(&long, 20), 6);
}
#[test]
fn max_scroll_counts_whitespace_only_render_rows() {
let content = (0..60)