From aa6094fdb1f2fa6d78d3c47504279e04e76a88ab Mon Sep 17 00:00:00 2001 From: Simonas Kareiva Date: Thu, 21 May 2026 21:24:00 +0300 Subject: [PATCH] Cursor fix --- src/tui.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/tui.rs b/src/tui.rs index 44f3ed8..5412096 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -1001,7 +1001,12 @@ fn render_editor(frame: &mut Frame, area: Rect, editor: &Editor, focused: bool) /// Build the cursor-bearing line as three spans: text before, the /// highlighted character at the cursor, text after. If the cursor sits -/// past the end of the line, the highlight falls on a trailing space. +/// past the end of the line (or on a whitespace cell), the highlight +/// falls on a visible block glyph — some terminals / ratatui's wrap +/// layer skip painting bg on styled space cells, which would leave the +/// cursor invisible. +const CURSOR_PLACEHOLDER: char = '▏'; + fn editor_cursor_line(line: &str, col: usize, cursor_style: Style) -> Line<'static> { let col = col.min(line.len()); let before = line[..col].to_string(); @@ -1011,15 +1016,17 @@ fn editor_cursor_line(line: &str, col: usize, cursor_style: Style) -> Line<'stat let mut chars = after.char_indices(); let (_, c) = chars.next().expect("non-empty: col < line.len()"); let next_boundary = chars.next().map(|(i, _)| i).unwrap_or(after.len()); + let glyph = if c.is_whitespace() { CURSOR_PLACEHOLDER } else { c }; Line::from(vec![ Span::raw(before), - Span::styled(c.to_string(), cursor_style), + Span::styled(glyph.to_string(), cursor_style), Span::raw(after[next_boundary..].to_string()), ]) } else { + // Cursor past end of line — show the placeholder glyph. Line::from(vec![ Span::raw(before), - Span::styled(" ".to_string(), cursor_style), + Span::styled(CURSOR_PLACEHOLDER.to_string(), cursor_style), ]) } }