TextEdit: naive fix to rendering selection around hard tabs

This commit is contained in:
Luke I. Wilson
2021-04-04 09:36:56 -05:00
parent 0e0f4b9339
commit ca68b8d7fa

View File

@@ -401,19 +401,25 @@ func (t *TextEdit) Draw(s tcell.Screen) {
if line < bufferLines { // Only index buffer if we are within it... if line < bufferLines { // Only index buffer if we are within it...
lineNumStr = strconv.Itoa(line + 1) // Only set for lines within the buffer (not view) lineNumStr = strconv.Itoa(line + 1) // Only set for lines within the buffer (not view)
var lineBytes []byte = t.Buffer.Line(line) // Line to be drawn var origLineBytes []byte = t.Buffer.Line(line)
var lineTabs [128]int // Rune index for each hard tab '\t' in lineBytes var lineBytes []byte = origLineBytes // Line to be drawn
var tabs int // Length of lineTabs (number of hard tabs)
// When iterating lineTabs: the value at i is
// the rune index the tab was found at.
// var lineTabs [128]int // Rune index for each hard tab '\t' in lineBytes
// var tabs int // Length of lineTabs (number of hard tabs)
if t.UseHardTabs { if t.UseHardTabs {
var i int // var ri int // rune index
for i < len(lineBytes) { // var i int
r, size := utf8.DecodeRune(lineBytes[i:]) // for i < len(lineBytes) {
if r == '\t' { // r, size := utf8.DecodeRune(lineBytes[i:])
lineTabs[tabs] = i // if r == '\t' {
tabs++ // lineTabs[tabs] = ri
} // tabs++
i += size // }
} // i += size
// ri++
// }
lineBytes = bytes.ReplaceAll(lineBytes, []byte{'\t'}, tabBytes) lineBytes = bytes.ReplaceAll(lineBytes, []byte{'\t'}, tabBytes)
} }
@@ -434,15 +440,37 @@ func (t *TextEdit) Draw(s tcell.Screen) {
tabOffsetAtRuneIdx := func(idx int) int { tabOffsetAtRuneIdx := func(idx int) int {
var count int var count int
for i := range lineTabs { var i int
if i >= tabs || lineTabs[i] >= idx { for i < len(origLineBytes) {
break r, size := utf8.DecodeRune(origLineBytes[i:])
} if r == '\t' {
count++ count++
} }
i += size
}
return count * (t.TabSize - 1) return count * (t.TabSize - 1)
} }
// origRuneIdx converts a rune index from lineBytes to a runeIndex from origLineBytes
// not affected by the hard tabs becoming 4 or 8 spaces.
origRuneIdx := func(idx int) int { // returns the idx that is not mutated by hard tabs
var ridx int // new rune idx
var i int // byte index
for idx > 0 {
r, size := utf8.DecodeRune(origLineBytes[i:])
if r == '\t' {
idx -= t.TabSize
} else {
idx--
}
if idx >= 0 { // causes ridx = 0, when idx = 3
ridx++
}
i += size
}
return ridx
}
for col < t.x + t.width { // For each column in view... for col < t.x + t.width { // For each column in view...
var r rune = ' ' // Rune to draw this iteration var r rune = ' ' // Rune to draw this iteration
var size int = 1 // Size of the rune (in bytes) var size int = 1 // Size of the rune (in bytes)
@@ -460,11 +488,12 @@ func (t *TextEdit) Draw(s tcell.Screen) {
// Determine whether we select the current rune. Also only select runes within // Determine whether we select the current rune. Also only select runes within
// the line bytes range. // the line bytes range.
if t.selectMode && line >= t.selection.StartLine && line <= t.selection.EndLine { // If we're part of a selection... if t.selectMode && line >= t.selection.StartLine && line <= t.selection.EndLine { // If we're part of a selection...
_origRuneIdx := origRuneIdx(runeIdx)
if line == t.selection.StartLine { // If selection starts at this line... if line == t.selection.StartLine { // If selection starts at this line...
if runeIdx-tabOffsetAtRuneIdx >= t.selection.StartCol { // And we're at or past the start col... if _origRuneIdx >= t.selection.StartCol { // And we're at or past the start col...
// If the start line is also the end line... // If the start line is also the end line...
if line == t.selection.EndLine { if line == t.selection.EndLine {
if runeIdx-tabOffsetAtRuneIdx <= t.selection.EndCol { // And we're before the end of that... if _origRuneIdx <= t.selection.EndCol { // And we're before the end of that...
selected = true selected = true
} }
} else { // Definitely highlight } else { // Definitely highlight
@@ -472,7 +501,7 @@ func (t *TextEdit) Draw(s tcell.Screen) {
} }
} }
} else if line == t.selection.EndLine { // If selection ends at this line... } else if line == t.selection.EndLine { // If selection ends at this line...
if runeIdx-tabOffsetAtRuneIdx <= t.selection.EndCol { // And we're at or before the end col... if _origRuneIdx <= t.selection.EndCol { // And we're at or before the end col...
selected = true selected = true
} }
} else { // We're between the start and the end lines, definitely highlight. } else { // We're between the start and the end lines, definitely highlight.