Replace manual utf8.DecodeRune with range string loops
This commit is contained in:
parent
06d12b0415
commit
b9a8b0040a
@ -36,17 +36,12 @@ func (b *RopeBuffer) LineColToPos(line, col int) int {
|
|||||||
|
|
||||||
l.EachLeaf(func(n *ropes.Node) bool {
|
l.EachLeaf(func(n *ropes.Node) bool {
|
||||||
data := n.Value() // Reference; not a copy.
|
data := n.Value() // Reference; not a copy.
|
||||||
var i int
|
for _, r := range string(data) {
|
||||||
for i < len(data) {
|
if col == 0 || r == '\n' {
|
||||||
if col == 0 || data[i] == '\n' {
|
|
||||||
return true // Found the position of the column
|
return true // Found the position of the column
|
||||||
}
|
}
|
||||||
pos++
|
pos++
|
||||||
col--
|
col--
|
||||||
|
|
||||||
// Respect Utf-8 codepoint boundaries
|
|
||||||
_, size := utf8.DecodeRune(data[i:])
|
|
||||||
i += size
|
|
||||||
}
|
}
|
||||||
return false // Have not gotten to the appropriate position, yet
|
return false // Have not gotten to the appropriate position, yet
|
||||||
})
|
})
|
||||||
@ -68,11 +63,11 @@ func (b *RopeBuffer) Line(line int) []byte {
|
|||||||
var isCRLF bool // true if the last byte was '\r'
|
var isCRLF bool // true if the last byte was '\r'
|
||||||
l.EachLeaf(func(n *ropes.Node) bool {
|
l.EachLeaf(func(n *ropes.Node) bool {
|
||||||
data := n.Value() // Reference; not a copy.
|
data := n.Value() // Reference; not a copy.
|
||||||
var i int
|
for i, r := range string(data) {
|
||||||
for i < len(data) {
|
if r == '\r' {
|
||||||
if data[i] == '\r' {
|
|
||||||
isCRLF = true
|
isCRLF = true
|
||||||
} else if data[i] == '\n' {
|
} else if r == '\n' {
|
||||||
|
bytes += i // Add bytes before i
|
||||||
if isCRLF {
|
if isCRLF {
|
||||||
bytes += 2 // Add the CRLF bytes
|
bytes += 2 // Add the CRLF bytes
|
||||||
} else {
|
} else {
|
||||||
@ -82,12 +77,8 @@ func (b *RopeBuffer) Line(line int) []byte {
|
|||||||
} else {
|
} else {
|
||||||
isCRLF = false
|
isCRLF = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Respect Utf-8 codepoint boundaries
|
|
||||||
_, size := utf8.DecodeRune(data[i:])
|
|
||||||
bytes += size
|
|
||||||
i += size
|
|
||||||
}
|
}
|
||||||
|
bytes += len(data)
|
||||||
return false // Have not read the whole line, yet
|
return false // Have not read the whole line, yet
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -198,26 +189,13 @@ func (b *RopeBuffer) RunesInLineWithDelim(line int) int {
|
|||||||
_, r := b.rope.SplitAt(linePos)
|
_, r := b.rope.SplitAt(linePos)
|
||||||
l, _ := r.SplitAt(ropeLen - linePos)
|
l, _ := r.SplitAt(ropeLen - linePos)
|
||||||
|
|
||||||
var isCRLF bool
|
|
||||||
l.EachLeaf(func(n *ropes.Node) bool {
|
l.EachLeaf(func(n *ropes.Node) bool {
|
||||||
data := n.Value() // Reference; not a copy.
|
data := n.Value() // Reference; not a copy.
|
||||||
var i int
|
for _, r := range string(data) {
|
||||||
for i < len(data) {
|
|
||||||
count++ // Before: we count the line delimiter
|
count++ // Before: we count the line delimiter
|
||||||
if data[i] == '\r' {
|
if r == '\n' {
|
||||||
isCRLF = true
|
|
||||||
} else if data[i] == '\n' {
|
|
||||||
return true // Read (past-tense) the whole line
|
return true // Read (past-tense) the whole line
|
||||||
} else {
|
|
||||||
if isCRLF {
|
|
||||||
isCRLF = false
|
|
||||||
count++ // Add the '\r' we previously thought was part of the delim.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Respect Utf-8 codepoint boundaries
|
|
||||||
_, size := utf8.DecodeRune(data[i:])
|
|
||||||
i += size
|
|
||||||
}
|
}
|
||||||
return false // Have not read the whole line, yet
|
return false // Have not read the whole line, yet
|
||||||
})
|
})
|
||||||
@ -244,11 +222,10 @@ func (b *RopeBuffer) RunesInLine(line int) int {
|
|||||||
var isCRLF bool
|
var isCRLF bool
|
||||||
l.EachLeaf(func(n *ropes.Node) bool {
|
l.EachLeaf(func(n *ropes.Node) bool {
|
||||||
data := n.Value() // Reference; not a copy.
|
data := n.Value() // Reference; not a copy.
|
||||||
var i int
|
for _, r := range string(data) {
|
||||||
for i < len(data) {
|
if r == '\r' {
|
||||||
if data[i] == '\r' {
|
|
||||||
isCRLF = true
|
isCRLF = true
|
||||||
} else if data[i] == '\n' {
|
} else if r == '\n' {
|
||||||
return true // Read (past-tense) the whole line
|
return true // Read (past-tense) the whole line
|
||||||
} else {
|
} else {
|
||||||
if isCRLF {
|
if isCRLF {
|
||||||
@ -257,10 +234,6 @@ func (b *RopeBuffer) RunesInLine(line int) int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
count++
|
count++
|
||||||
|
|
||||||
// Respect Utf-8 codepoint boundaries
|
|
||||||
_, size := utf8.DecodeRune(data[i:])
|
|
||||||
i += size
|
|
||||||
}
|
}
|
||||||
return false // Have not read the whole line, yet
|
return false // Have not read the whole line, yet
|
||||||
})
|
})
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
|
"github.com/mattn/go-runewidth"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DrawRect renders a filled box at `x` and `y`, of size `width` and `height`.
|
// DrawRect renders a filled box at `x` and `y`, of size `width` and `height`.
|
||||||
@ -16,22 +15,20 @@ func DrawRect(s tcell.Screen, x, y, width, height int, char rune, style tcell.St
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawStr will render each character of a string at `x` and `y`.
|
// DrawStr will render each character of a string at `x` and `y`. Returned is
|
||||||
func DrawStr(s tcell.Screen, x, y int, str string, style tcell.Style) {
|
// the number of columns that were drawn to the screen.
|
||||||
|
func DrawStr(s tcell.Screen, x, y int, str string, style tcell.Style) int {
|
||||||
var col int
|
var col int
|
||||||
bytes := []byte(str)
|
for _, r := range str {
|
||||||
var i int
|
|
||||||
for i < len(bytes) {
|
|
||||||
r, size := utf8.DecodeRune(bytes[i:])
|
|
||||||
if r == '\n' {
|
if r == '\n' {
|
||||||
col = 0
|
col = 0
|
||||||
y++
|
y++
|
||||||
} else {
|
} else {
|
||||||
s.SetContent(x+col, y, r, nil, style)
|
s.SetContent(x+col, y, r, nil, style)
|
||||||
}
|
}
|
||||||
i += size
|
col += runewidth.RuneWidth(r)
|
||||||
col++
|
|
||||||
}
|
}
|
||||||
|
return col
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawQuickCharStr renders a string very similar to how DrawStr works, but stylizes the
|
// DrawQuickCharStr renders a string very similar to how DrawStr works, but stylizes the
|
||||||
@ -41,20 +38,17 @@ func DrawQuickCharStr(s tcell.Screen, x, y int, str string, quickCharIdx int, st
|
|||||||
var col int
|
var col int
|
||||||
var runeIdx int
|
var runeIdx int
|
||||||
|
|
||||||
bytes := []byte(str)
|
for _, r := range str {
|
||||||
for i := 0; i < len(bytes); runeIdx++ { // i is a byte index
|
|
||||||
r, size := utf8.DecodeRune(bytes[i:])
|
|
||||||
|
|
||||||
sty := style
|
sty := style
|
||||||
if runeIdx == quickCharIdx {
|
if runeIdx == quickCharIdx {
|
||||||
sty = style.Underline(true)
|
sty = style.Underline(true)
|
||||||
}
|
}
|
||||||
s.SetContent(x+col, y, r, nil, sty)
|
s.SetContent(x+col, y, r, nil, sty)
|
||||||
|
|
||||||
i += size
|
runeIdx++
|
||||||
col++
|
col += runewidth.RuneWidth(r)
|
||||||
}
|
}
|
||||||
return col // TODO: use mattn/runewidth
|
return col
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawRectOutline draws only the outline of a rectangle, using `ul`, `ur`, `bl`, and `br`
|
// DrawRectOutline draws only the outline of a rectangle, using `ul`, `ur`, `bl`, and `br`
|
||||||
|
@ -476,7 +476,6 @@ func (t *TextEdit) Draw(s tcell.Screen) {
|
|||||||
|
|
||||||
col += runewidth.RuneWidth(r)
|
col += runewidth.RuneWidth(r)
|
||||||
|
|
||||||
// Understanding the tab simulation is unnecessary; just know that it works.
|
|
||||||
byteIdx += size
|
byteIdx += size
|
||||||
runeIdx++
|
runeIdx++
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user