Skip to content

Commit

Permalink
Replace manual utf8.DecodeRune with range string loops
Browse files Browse the repository at this point in the history
  • Loading branch information
lukewilson2002 committed Apr 13, 2021
1 parent 06d12b0 commit b9a8b00
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 57 deletions.
51 changes: 12 additions & 39 deletions ui/buffer/rope.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,12 @@ func (b *RopeBuffer) LineColToPos(line, col int) int {

l.EachLeaf(func(n *ropes.Node) bool {
data := n.Value() // Reference; not a copy.
var i int
for i < len(data) {
if col == 0 || data[i] == '\n' {
for _, r := range string(data) {
if col == 0 || r == '\n' {
return true // Found the position of the column
}
pos++
col--

// Respect Utf-8 codepoint boundaries
_, size := utf8.DecodeRune(data[i:])
i += size
}
return false // Have not gotten to the appropriate position, yet
})
Expand All @@ -68,11 +63,11 @@ func (b *RopeBuffer) Line(line int) []byte {
var isCRLF bool // true if the last byte was '\r'
l.EachLeaf(func(n *ropes.Node) bool {
data := n.Value() // Reference; not a copy.
var i int
for i < len(data) {
if data[i] == '\r' {
for i, r := range string(data) {
if r == '\r' {
isCRLF = true
} else if data[i] == '\n' {
} else if r == '\n' {
bytes += i // Add bytes before i
if isCRLF {
bytes += 2 // Add the CRLF bytes
} else {
Expand All @@ -82,12 +77,8 @@ func (b *RopeBuffer) Line(line int) []byte {
} else {
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
})

Expand Down Expand Up @@ -198,26 +189,13 @@ func (b *RopeBuffer) RunesInLineWithDelim(line int) int {
_, r := b.rope.SplitAt(linePos)
l, _ := r.SplitAt(ropeLen - linePos)

var isCRLF bool
l.EachLeaf(func(n *ropes.Node) bool {
data := n.Value() // Reference; not a copy.
var i int
for i < len(data) {
for _, r := range string(data) {
count++ // Before: we count the line delimiter
if data[i] == '\r' {
isCRLF = true
} else if data[i] == '\n' {
if r == '\n' {
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
})
Expand All @@ -244,11 +222,10 @@ func (b *RopeBuffer) RunesInLine(line int) int {
var isCRLF bool
l.EachLeaf(func(n *ropes.Node) bool {
data := n.Value() // Reference; not a copy.
var i int
for i < len(data) {
if data[i] == '\r' {
for _, r := range string(data) {
if r == '\r' {
isCRLF = true
} else if data[i] == '\n' {
} else if r == '\n' {
return true // Read (past-tense) the whole line
} else {
if isCRLF {
Expand All @@ -257,10 +234,6 @@ func (b *RopeBuffer) RunesInLine(line int) int {
}
}
count++

// Respect Utf-8 codepoint boundaries
_, size := utf8.DecodeRune(data[i:])
i += size
}
return false // Have not read the whole line, yet
})
Expand Down
28 changes: 11 additions & 17 deletions ui/drawfunctions.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package ui

import (
"unicode/utf8"

"github.com/gdamore/tcell/v2"
"github.com/mattn/go-runewidth"
)

// DrawRect renders a filled box at `x` and `y`, of size `width` and `height`.
Expand All @@ -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`.
func DrawStr(s tcell.Screen, x, y int, str string, style tcell.Style) {
// DrawStr will render each character of a string at `x` and `y`. Returned is
// 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
bytes := []byte(str)
var i int
for i < len(bytes) {
r, size := utf8.DecodeRune(bytes[i:])
for _, r := range str {
if r == '\n' {
col = 0
y++
} else {
s.SetContent(x+col, y, r, nil, style)
}
i += size
col++
col += runewidth.RuneWidth(r)
}
return col
}

// DrawQuickCharStr renders a string very similar to how DrawStr works, but stylizes the
Expand All @@ -41,20 +38,17 @@ func DrawQuickCharStr(s tcell.Screen, x, y int, str string, quickCharIdx int, st
var col int
var runeIdx int

bytes := []byte(str)
for i := 0; i < len(bytes); runeIdx++ { // i is a byte index
r, size := utf8.DecodeRune(bytes[i:])

for _, r := range str {
sty := style
if runeIdx == quickCharIdx {
sty = style.Underline(true)
}
s.SetContent(x+col, y, r, nil, sty)

i += size
col++
runeIdx++
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`
Expand Down
1 change: 0 additions & 1 deletion ui/textedit.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,6 @@ func (t *TextEdit) Draw(s tcell.Screen) {

col += runewidth.RuneWidth(r)

// Understanding the tab simulation is unnecessary; just know that it works.
byteIdx += size
runeIdx++
}
Expand Down

0 comments on commit b9a8b00

Please sign in to comment.