tui: improve input responsiveness and diff/readability

- Input thread: lower crossterm poll to 5ms and yield on idle
- Remove per-frame full-screen bg fill; rely on local clears
- Wrap stdout in BufWriter for fewer syscalls
- Bottom pane: paint bg for entire area and composer block
- ExecCell: add 2-col hanging indent for preamble; ensure bg fill
- Normalize TTY overwrite sequences (\r, \x08, ESC[K) in stdout/stderr and background events to avoid ghost chars
- Diff overlay: center sign with spaces (one after), tighten gap after line number; align wraps under code indent
- History diff cell: match sign spacing with overlay (two before, one after); adjust gutters
This commit is contained in:
James Peter
2025-08-24 10:32:50 +10:00
parent d2cfbf166e
commit 9bcf7c7e2b
2 changed files with 13 additions and 7 deletions
+10 -4
View File
@@ -15,7 +15,7 @@ use crate::history_cell::PatchEventType;
// Keep one space between the line number and the sign column for typical
// 4‑digit line numbers (e.g., "1235 + "). This value is the total target
// width for "<ln><gap>", so with 4 digits we get 1 space gap.
const SPACES_AFTER_LINE_NUMBER: usize = 5;
const SPACES_AFTER_LINE_NUMBER: usize = 6;
// Internal representation for diff line rendering
#[allow(dead_code)]
@@ -310,6 +310,10 @@ fn push_wrapped_diff_line(
let prefix_cols = indent.len() + ln_str.len() + gap_after_ln;
let mut first = true;
// Continuation hanging indent equals the leading spaces of the content
// (after the diff sign). This keeps wrapped rows aligned under the code
// indentation.
let continuation_indent: usize = text.chars().take_while(|c| *c == ' ').count();
let (sign_opt, line_style) = match kind {
DiffLineType::Insert => (Some('+'), Some(style_add())),
DiffLineType::Delete => (Some('-'), Some(style_del())),
@@ -323,8 +327,9 @@ fn push_wrapped_diff_line(
// at a UTF-8 character boundary so this row's chunk fits exactly.
// First line includes a visible sign plus a trailing space after it.
// Continuation lines include only the hanging space (no sign).
let base_prefix = if first { prefix_cols + 2 } else { prefix_cols + 1 + continuation_indent };
let available_content_cols = term_cols
.saturating_sub(if first { prefix_cols + 2 } else { prefix_cols + 1 })
.saturating_sub(base_prefix)
.max(1);
let split_at_byte_index = remaining_text
.char_indices()
@@ -369,9 +374,10 @@ fn push_wrapped_diff_line(
} else {
// Continuation lines keep a space for the sign column so content aligns
let hang_prefix = format!(
"{indent}{}{} ",
"{indent}{}{} {}",
" ".repeat(ln_str.len()),
" ".repeat(gap_after_ln)
" ".repeat(gap_after_ln),
" ".repeat(continuation_indent)
);
let content_span = match line_style {
Some(style) => RtSpan::styled(chunk.to_string(), style),
+3 -3
View File
@@ -498,9 +498,9 @@ impl HistoryCell for DiffCell {
// Center the sign in the two-column gutter by leaving one leading
// space and drawing the sign in the second column.
let marker_col_x = area.x.saturating_add(1); // draw '+'/'-' here
let content_x = area.x.saturating_add(2); // one space after the sign
let content_w = area.width.saturating_sub(2);
let marker_col_x = area.x.saturating_add(2); // two spaces then '+'/'-'
let content_x = area.x.saturating_add(4); // two spaces before sign + one after sign
let content_w = area.width.saturating_sub(4);
let mut cur_y = area.y;
// Helper to classify a line and extract marker and content