Rope: Added LineColToPos, and optimized Highlighter's UpdateLines()
This commit is contained in:
parent
f829b37d0c
commit
58c8de3068
@ -62,6 +62,14 @@ type Buffer interface {
|
|||||||
// the last rune before the line delimiter.
|
// the last rune before the line delimiter.
|
||||||
ClampLineCol(line, col int) (int, int)
|
ClampLineCol(line, col int) (int, int)
|
||||||
|
|
||||||
|
|
||||||
|
// LineColToPos returns the index of the byte at line, col. If line is less than
|
||||||
|
// zero, or more than the number of available lines, the function will panic. If
|
||||||
|
// col is less than zero, the function will panic. If col is greater than the
|
||||||
|
// length of the line, the position of the last byte of the line is returned,
|
||||||
|
// instead.
|
||||||
|
LineColToPos(line, col int) int
|
||||||
|
|
||||||
// PosToLineCol converts a byte offset (position) of the buffer's bytes, into
|
// PosToLineCol converts a byte offset (position) of the buffer's bytes, into
|
||||||
// a line and column. Unless you are working with the Bytes() function, this
|
// a line and column. Unless you are working with the Bytes() function, this
|
||||||
// is unlikely to be useful to you. Position will be clamped.
|
// is unlikely to be useful to you. Position will be clamped.
|
||||||
|
@ -81,21 +81,29 @@ func (h *Highlighter) UpdateLines(startLine, endLine int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the rule k does not have an End, then it can be optimized that we search from the start
|
// If the rule k does not have an End, then it can be optimized that we search from the start
|
||||||
// of view until the end of view. For any k that has an End, we search for starts from start
|
// of view until the end of view. For any k that has an End, we search for ends from start
|
||||||
// of buffer, until end of view.
|
// of view, backtracking when one is found, to fulfill a multiline highlight.
|
||||||
|
|
||||||
endLine, endCol := h.Buffer.ClampLineCol(endLine, (h.Buffer).RunesInLineWithDelim(endLine)-1)
|
endLine, endCol := h.Buffer.ClampLineCol(endLine, (h.Buffer).RunesInLineWithDelim(endLine)-1)
|
||||||
bytes := (h.Buffer).Slice(0, 0, endLine, endCol) // Allocates size of the buffer
|
startPos := h.Buffer.LineColToPos(startLine, 0)
|
||||||
|
bytes := h.Buffer.Slice(startLine, 0, endLine, endCol)
|
||||||
|
|
||||||
for k, v := range h.Language.Rules {
|
for k, v := range h.Language.Rules {
|
||||||
indexes := k.Start.FindAllIndex(bytes, -1) // Attempt to find the start match
|
var indexes [][]int // [][2]int
|
||||||
|
if k.End != nil && k.End.String() != "$" { // If this range might be a multiline range...
|
||||||
|
endIndexes := k.End.FindAllIndex(bytes, -1) // Attempt to find every ending match
|
||||||
|
startIndexes := k.Start.FindAllIndex(bytes, -1) // Attempt to find every starting match
|
||||||
|
// ...
|
||||||
|
_ = endIndexes
|
||||||
|
_ = startIndexes
|
||||||
|
} else { // A standard single-line match
|
||||||
|
indexes = k.Start.FindAllIndex(bytes, -1) // Attempt to find the start match
|
||||||
|
}
|
||||||
|
|
||||||
if indexes != nil {
|
if indexes != nil {
|
||||||
for i := range indexes {
|
for i := range indexes {
|
||||||
// if k.End != nil && k.End.String() != "$" { // If this match has a defined end...
|
startLine, startCol := h.Buffer.PosToLineCol(indexes[i][0] + startPos)
|
||||||
// }
|
endLine, endCol := h.Buffer.PosToLineCol(indexes[i][1]-1 + startPos)
|
||||||
endPos := indexes[i][1] - 1
|
|
||||||
startLine, startCol := h.Buffer.PosToLineCol(indexes[i][0])
|
|
||||||
endLine, endCol := h.Buffer.PosToLineCol(endPos)
|
|
||||||
|
|
||||||
match := Match { startCol, endLine, endCol, v }
|
match := Match { startCol, endLine, endCol, v }
|
||||||
|
|
||||||
|
@ -13,11 +13,12 @@ func NewRopeBuffer(contents []byte) *RopeBuffer {
|
|||||||
return (*RopeBuffer)(rope.New(contents))
|
return (*RopeBuffer)(rope.New(contents))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the index of the byte at line, col. If line is less than zero, or more
|
// LineColToPos returns the index of the byte at line, col. If line is less than
|
||||||
// than the number of available lines, the function will panic. If col is less than
|
// zero, or more than the number of available lines, the function will panic. If
|
||||||
// zero, the function will panic. If col is greater than the length of the line,
|
// col is less than zero, the function will panic. If col is greater than the
|
||||||
// the position of the last byte of the line is returned, instead.
|
// length of the line, the position of the last byte of the line is returned,
|
||||||
func (b *RopeBuffer) pos(line, col int) int {
|
// instead.
|
||||||
|
func (b *RopeBuffer) LineColToPos(line, col int) int {
|
||||||
var pos int
|
var pos int
|
||||||
|
|
||||||
_rope := (*rope.Node)(b)
|
_rope := (*rope.Node)(b)
|
||||||
@ -96,11 +97,11 @@ func (b *RopeBuffer) Line(line int) []byte {
|
|||||||
// inclusive bounds. The returned value may or may not be a copy of the data,
|
// inclusive bounds. The returned value may or may not be a copy of the data,
|
||||||
// so do not write to it.
|
// so do not write to it.
|
||||||
func (b *RopeBuffer) Slice(startLine, startCol, endLine, endCol int) []byte {
|
func (b *RopeBuffer) Slice(startLine, startCol, endLine, endCol int) []byte {
|
||||||
endPos := b.pos(endLine, endCol)+1
|
endPos := b.LineColToPos(endLine, endCol)+1
|
||||||
if length := (*rope.Node)(b).Len(); endPos >= length {
|
if length := (*rope.Node)(b).Len(); endPos >= length {
|
||||||
endPos = length-1
|
endPos = length-1
|
||||||
}
|
}
|
||||||
return (*rope.Node)(b).Slice(b.pos(startLine, startCol), endPos)
|
return (*rope.Node)(b).Slice(b.LineColToPos(startLine, startCol), endPos)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes returns all of the bytes in the buffer. This function is very likely
|
// Bytes returns all of the bytes in the buffer. This function is very likely
|
||||||
@ -112,14 +113,14 @@ func (b *RopeBuffer) Bytes() []byte {
|
|||||||
|
|
||||||
// Insert copies a byte slice (inserting it) into the position at line, col.
|
// Insert copies a byte slice (inserting it) into the position at line, col.
|
||||||
func (b *RopeBuffer) Insert(line, col int, value []byte) {
|
func (b *RopeBuffer) Insert(line, col int, value []byte) {
|
||||||
(*rope.Node)(b).Insert(b.pos(line, col), value)
|
(*rope.Node)(b).Insert(b.LineColToPos(line, col), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove deletes any characters between startLine, startCol, and endLine,
|
// Remove deletes any characters between startLine, startCol, and endLine,
|
||||||
// endCol, inclusive bounds.
|
// endCol, inclusive bounds.
|
||||||
func (b *RopeBuffer) Remove(startLine, startCol, endLine, endCol int) {
|
func (b *RopeBuffer) Remove(startLine, startCol, endLine, endCol int) {
|
||||||
start := b.pos(startLine, startCol)
|
start := b.LineColToPos(startLine, startCol)
|
||||||
end := b.pos(endLine, endCol) + 1
|
end := b.LineColToPos(endLine, endCol) + 1
|
||||||
|
|
||||||
if len := (*rope.Node)(b).Len(); end >= len {
|
if len := (*rope.Node)(b).Len(); end >= len {
|
||||||
end = len
|
end = len
|
||||||
@ -134,8 +135,8 @@ func (b *RopeBuffer) Remove(startLine, startCol, endLine, endCol int) {
|
|||||||
// Returns the number of occurrences of 'sequence' in the buffer, within the range
|
// Returns the number of occurrences of 'sequence' in the buffer, within the range
|
||||||
// of start line and col, to end line and col. End is exclusive.
|
// of start line and col, to end line and col. End is exclusive.
|
||||||
func (b *RopeBuffer) Count(startLine, startCol, endLine, endCol int, sequence []byte) int {
|
func (b *RopeBuffer) Count(startLine, startCol, endLine, endCol int, sequence []byte) int {
|
||||||
startPos := b.pos(startLine, startCol)
|
startPos := b.LineColToPos(startLine, startCol)
|
||||||
endPos := b.pos(endLine, endCol)
|
endPos := b.LineColToPos(endLine, endCol)
|
||||||
return (*rope.Node)(b).Count(startPos, endPos, sequence)
|
return (*rope.Node)(b).Count(startPos, endPos, sequence)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user