TextEdit: naive fix to rendering selection around hard tabs
This commit is contained in:
@@ -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.
|
||||||
|
Reference in New Issue
Block a user