Problem
When the cursor is on a code block's title (language label), raw ANSI escape sequences flash visibly as artifacts. Observed sequences: [7m (reverse video) and [40m (black background) leaking into the rendered title and box border content. Only reproduces on certain themes.
Context
Title cursor rendering — internal/editor/render.go:417-427
renderLabelCursor() uses a bare lipgloss.NewStyle().Reverse(true) with no foreground/background color. The same bare style is used at line 279 for empty titles. This produces \x1b[7m which depends entirely on the terminal's current fg/bg state — unreliable when embedded between border color escapes and faint-styled text.
Off-by-one in scroll/truncate — internal/editor/render.go:338-345
When the cursor is on the title (line 0), cursorVisIdx stays at 0, so adjustedCursor = 0 + 1 = 1. The top border (line 0 of the code box output, which contains the cursor label) gets isCursorLine = false, meaning it goes through non-cursor truncation via ansi.Truncate. If the gutter + border exceeds terminal width, ansi.Truncate may clip through the cursor's ANSI sequences in the label.
Textarea cursor vs label cursor mismatch — The textarea's virtual cursor uses Foreground(Color("7")) + Reverse(true) (textarea.go:476), but the label cursor uses bare Reverse(true) with no color. These produce different ANSI sequences, which could explain why the content area shows [40m while the title shows [7m.
Theme dependency — Different themes set LabelAlign to "left", "center", or "right", which changes where the label sits in the top border and how much padding surrounds it. Themes with "center" or "right" alignment shift the label position, potentially pushing the cursor ANSI closer to truncation boundaries.
Tasks
Problem
When the cursor is on a code block's title (language label), raw ANSI escape sequences flash visibly as artifacts. Observed sequences:
[7m(reverse video) and[40m(black background) leaking into the rendered title and box border content. Only reproduces on certain themes.Context
Title cursor rendering —
internal/editor/render.go:417-427renderLabelCursor()uses a barelipgloss.NewStyle().Reverse(true)with no foreground/background color. The same bare style is used at line 279 for empty titles. This produces\x1b[7mwhich depends entirely on the terminal's current fg/bg state — unreliable when embedded between border color escapes and faint-styled text.Off-by-one in scroll/truncate —
internal/editor/render.go:338-345When the cursor is on the title (line 0),
cursorVisIdxstays at 0, soadjustedCursor = 0 + 1 = 1. The top border (line 0 of the code box output, which contains the cursor label) getsisCursorLine = false, meaning it goes through non-cursor truncation viaansi.Truncate. If the gutter + border exceeds terminal width,ansi.Truncatemay clip through the cursor's ANSI sequences in the label.Textarea cursor vs label cursor mismatch — The textarea's virtual cursor uses
Foreground(Color("7")) + Reverse(true)(textarea.go:476), but the label cursor uses bareReverse(true)with no color. These produce different ANSI sequences, which could explain why the content area shows[40mwhile the title shows[7m.Theme dependency — Different themes set
LabelAlignto"left","center", or"right", which changes where the label sits in the top border and how much padding surrounds it. Themes with"center"or"right"alignment shift the label position, potentially pushing the cursor ANSI closer to truncation boundaries.Tasks
renderLabelCursor's cursor style an explicit foreground + background color (derived from theme) instead of bareReverse(true)adjustedCursoroff-by-one: when cursor is on the title, the top border line should be treated as the cursor line for scroll/truncateleft,center,right) and multiple themes