Compare commits

...

3 Commits

Author SHA1 Message Date
Neko Box Coder
0870a075dc
Extracting brace matching logic into its own public function 2024-07-07 01:19:30 +01:00
Neko Box Coder
b0baa98bc7
Compute sorted group indicies only when needed 2024-07-07 00:55:36 +01:00
Neko Box Coder
ae7723ae08
Reusing the sorted group indices computed on the same line 2024-07-07 00:14:13 +01:00

View File

@ -1141,7 +1141,8 @@ var BracePairs = [][2]rune{
{'[', ']'},
}
func (b *Buffer) getSortedSyntaxIndices(lineN int) []int {
// Returns the indices of syntax groups in ascending order
func (b *Buffer) GetSortedSyntaxGroupIndices(lineN int) []int {
keys := make([]int, 0, len(b.Match(lineN)))
for k := range b.Match(lineN) {
keys = append(keys, k)
@ -1151,9 +1152,13 @@ func (b *Buffer) getSortedSyntaxIndices(lineN int) []int {
}
// 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)
// that indicates if a group is found or not.
// This optionally accepts sorted Group indices returned from GetSortedSyntaxGroupIndices()
// which can be reused on the same line.
func (b *Buffer) GetGroupAtLoc(loc Loc, sortedIndices []int) (highlight.Group, bool) {
if sortedIndices == nil {
sortedIndices = b.GetSortedSyntaxGroupIndices(loc.Y)
}
i := sort.SearchInts(sortedIndices, loc.X)
if i == 0 || i == len(sortedIndices) {
return 0, false
@ -1164,57 +1169,108 @@ func (b *Buffer) GetGroupAtLoc(loc Loc) (highlight.Group, bool) {
return b.Match(loc.Y)[sortedIndices[i - 1]], true
}
func (b *Buffer) isLocInStringOrComment(loc Loc) bool {
g, gFound := b.GetGroupAtLoc(loc)
func (b *Buffer) isLocInStringOrComment(loc Loc, sortedIndices []int) bool {
g, gFound := b.GetGroupAtLoc(loc, sortedIndices)
if gFound && (g.String() == "constant.string" || strings.Contains(g.String(), "comment")) {
return true
}
return false
}
func (b *Buffer) FindOpeningBrace(braceType [2]rune, start Loc) (Loc, bool) {
startChar := []rune(string(b.LineBytes(start.Y)))[start.X]
var i int
if startChar == braceType[1] {
i = 0
} else {
i = 1
}
for y := start.Y; y >= 0; y-- {
var sortedGroups []int
sortedGroupsPopulated := false
l := []rune(string(b.lines[y].data))
xInit := len(l) - 1
if y == start.Y {
xInit = start.X
}
for x := xInit; x >= 0; x-- {
r := l[x]
if r == braceType[1] {
if !sortedGroupsPopulated {
sortedGroups = b.GetSortedSyntaxGroupIndices(y)
sortedGroupsPopulated = true
}
if !b.isLocInStringOrComment(Loc{x, y}, sortedGroups) {
i++
}
} else if r == braceType[0]{
if !sortedGroupsPopulated {
sortedGroups = b.GetSortedSyntaxGroupIndices(y)
sortedGroupsPopulated = true
}
if !b.isLocInStringOrComment(Loc{x, y}, sortedGroups) {
i--
}
if i == 0 {
return Loc{x, y}, true
}
}
}
}
return start, false
}
func (b *Buffer) FindClosingBrace(braceType [2]rune, start Loc) (Loc, bool) {
startChar := []rune(string(b.LineBytes(start.Y)))[start.X]
var i int
if startChar == braceType[0] {
i = 0
} else {
i = 1
}
for y := start.Y; y < b.LinesNum(); y++ {
var sortedGroups []int
sortedGroupsPopulated := false
l := []rune(string(b.LineBytes(y)))
xInit := 0
if y == start.Y {
xInit = start.X
}
for x := xInit; x < len(l); x++ {
r := l[x]
if r == braceType[0] {
if !sortedGroupsPopulated {
sortedGroups = b.GetSortedSyntaxGroupIndices(y)
sortedGroupsPopulated = true
}
if !b.isLocInStringOrComment(Loc{x, y}, sortedGroups) {
i++
}
} else if r == braceType[1] {
if !sortedGroupsPopulated {
sortedGroups = b.GetSortedSyntaxGroupIndices(y)
sortedGroupsPopulated = true
}
if !b.isLocInStringOrComment(Loc{x, y}, sortedGroups) {
i--
}
if i == 0 {
return Loc{x, y}, true
}
}
}
}
return start, false
}
func (b *Buffer) findMatchingBrace(braceType [2]rune, start Loc, char rune) (Loc, bool) {
if b.isLocInStringOrComment(start) {
if b.isLocInStringOrComment(start, nil) {
return start, false
}
var i int
if char == braceType[0] {
for y := start.Y; y < b.LinesNum(); y++ {
l := []rune(string(b.LineBytes(y)))
xInit := 0
if y == start.Y {
xInit = start.X
}
for x := xInit; x < len(l); x++ {
r := l[x]
if r == braceType[0] && !b.isLocInStringOrComment(Loc{x, y}) {
i++
} else if r == braceType[1] && !b.isLocInStringOrComment(Loc{x, y}) {
i--
if i == 0 {
return Loc{x, y}, true
}
}
}
}
return b.FindClosingBrace(braceType, start)
} else if char == braceType[1] {
for y := start.Y; y >= 0; y-- {
l := []rune(string(b.lines[y].data))
xInit := len(l) - 1
if y == start.Y {
xInit = start.X
}
for x := xInit; x >= 0; x-- {
r := l[x]
if r == braceType[1] && !b.isLocInStringOrComment(Loc{x, y}){
i++
} else if r == braceType[0] && !b.isLocInStringOrComment(Loc{x, y}){
i--
if i == 0 {
return Loc{x, y}, true
}
}
}
}
return b.FindOpeningBrace(braceType, start)
}
return start, false
}