Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 39 additions & 4 deletions internal/buffer/buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"sync"
"sync/atomic"
"time"
"sort"

luar "layeh.com/gopher-luar"

Expand Down Expand Up @@ -1140,7 +1141,41 @@ var BracePairs = [][2]rune{
{'[', ']'},
}

func (b *Buffer) getSortedSyntaxIndices(lineN int) []int {
keys := make([]int, 0, len(b.Match(lineN)))
for k := range b.Match(lineN) {
keys = append(keys, k)
}
sort.Ints(keys)
return keys
}

// Returns the Group (syntax highlight group ID) at the specified location and a boolean
// that indicates if a group is found or not
func (b *Buffer) GetGroupAtLoc(loc Loc) (highlight.Group, bool) {
sortedIndices := b.getSortedSyntaxIndices(loc.Y)
i := sort.SearchInts(sortedIndices, loc.X)
if i == 0 || i == len(sortedIndices) {
return 0, false
}
if sortedIndices[i] == loc.X && b.Match(loc.Y)[sortedIndices[i]] != 0 {
return b.Match(loc.Y)[sortedIndices[i]], true
}
return b.Match(loc.Y)[sortedIndices[i - 1]], true
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'm missing something but is the sorting necessary?

Suggested change
func (b *Buffer) getSortedSyntaxIndices(lineN int) []int {
keys := make([]int, 0, len(b.Match(lineN)))
for k := range b.Match(lineN) {
keys = append(keys, k)
}
sort.Ints(keys)
return keys
}
// Returns the Group (syntax highlight group ID) at the specified location and a boolean
// that indicates if a group is found or not
func (b *Buffer) GetGroupAtLoc(loc Loc) (highlight.Group, bool) {
sortedIndices := b.getSortedSyntaxIndices(loc.Y)
i := sort.SearchInts(sortedIndices, loc.X)
if i == 0 || i == len(sortedIndices) {
return 0, false
}
if sortedIndices[i] == loc.X && b.Match(loc.Y)[sortedIndices[i]] != 0 {
return b.Match(loc.Y)[sortedIndices[i]], true
}
return b.Match(loc.Y)[sortedIndices[i - 1]], true
}
func (b *Buffer) GetGroupAtLoc(loc Loc) (highlight.Group, bool) {
found := -1
for i := range b.Match(loc.Y) {
if i > found && i <= loc.X {
found = i
}
}
if found == -1 {
return 0, false
}
return b.Match(loc.Y)[found], true
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suggested change won't work when the cursor is at the end of a syntax change, which has an empty group and needs the previous group id.

The sorted indices are now being reused for the rest of the lines without iterating the whole line again, which will be useful for extreme cases where the line is very long, for example, minified js or json.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suggested change won't work when the cursor is at the end of a syntax change, which has an empty group and needs the previous group id.

Can you provide an example of this / how to test it? It should be fixable – if the only reason you need the sorted indices is to call sort.SearchInts afterwards you can always do it with a simple loop (less code and no allocations).


func (b *Buffer) isLocInStringOrComment(loc Loc) bool {
g, gFound := b.GetGroupAtLoc(loc)
if gFound && (g.String() == "constant.string" || strings.Contains(g.String(), "comment")) {
return true
}
return false
}

func (b *Buffer) findMatchingBrace(braceType [2]rune, start Loc, char rune) (Loc, bool) {
if b.isLocInStringOrComment(start) {
return start, false
}
var i int
if char == braceType[0] {
for y := start.Y; y < b.LinesNum(); y++ {
Expand All @@ -1151,9 +1186,9 @@ func (b *Buffer) findMatchingBrace(braceType [2]rune, start Loc, char rune) (Loc
}
for x := xInit; x < len(l); x++ {
r := l[x]
if r == braceType[0] {
if r == braceType[0] && !b.isLocInStringOrComment(Loc{x, y}) {
i++
} else if r == braceType[1] {
} else if r == braceType[1] && !b.isLocInStringOrComment(Loc{x, y}) {
i--
if i == 0 {
return Loc{x, y}, true
Expand All @@ -1170,9 +1205,9 @@ func (b *Buffer) findMatchingBrace(braceType [2]rune, start Loc, char rune) (Loc
}
for x := xInit; x >= 0; x-- {
r := l[x]
if r == braceType[1] {
if r == braceType[1] && !b.isLocInStringOrComment(Loc{x, y}){
i++
} else if r == braceType[0] {
} else if r == braceType[0] && !b.isLocInStringOrComment(Loc{x, y}){
i--
if i == 0 {
return Loc{x, y}, true
Expand Down