@@ -950,26 +950,33 @@ func (m *model) applySelectionHighlight(lines []string, viewportStartLine int) [
950950}
951951
952952func (m * model ) highlightLine (line string , startCol , endCol int ) string {
953+ // Get plain text for boundary checks
953954 plainLine := ansi .Strip (line )
955+ plainWidth := runewidth .StringWidth (plainLine )
954956
955- startRuneIdx := displayWidthToRuneIndex (plainLine , startCol )
956- endRuneIdx := displayWidthToRuneIndex (plainLine , endCol )
957-
958- if startRuneIdx >= len ([]rune (plainLine )) {
957+ // Validate and normalize boundaries
958+ if startCol >= plainWidth {
959959 return line
960960 }
961- if startRuneIdx >= endRuneIdx {
961+ if startCol >= endCol {
962962 return line
963963 }
964-
965- runes := []rune (plainLine )
966- before := string (runes [:startRuneIdx ])
967- selected := styles .SelectionStyle .Render (string (runes [startRuneIdx :endRuneIdx ]))
968- after := ""
969- if endRuneIdx < len (runes ) {
970- after = string (runes [endRuneIdx :])
964+ if endCol > plainWidth {
965+ endCol = plainWidth
971966 }
972967
968+ // Extract the three parts while preserving ANSI codes
969+ // before: from start to startCol (preserves original styling)
970+ before := ansi .Cut (line , 0 , startCol )
971+
972+ // selected: from startCol to endCol (strip styling, apply selection style)
973+ selectedText := ansi .Cut (line , startCol , endCol )
974+ selectedPlain := ansi .Strip (selectedText )
975+ selected := styles .SelectionStyle .Render (selectedPlain )
976+
977+ // after: from endCol to end (preserves original styling)
978+ after := ansi .Cut (line , endCol , plainWidth )
979+
973980 return before + selected + after
974981}
975982
0 commit comments