Implemented anchors for rope buffer

This commit is contained in:
Luke Wilson 2021-04-13 11:05:01 -05:00
parent 8d775804cb
commit 3bf5e6dfd7
2 changed files with 33 additions and 2 deletions

View File

@ -115,6 +115,7 @@ 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) {
b.rope.Insert(b.LineColToPos(line, col), value) b.rope.Insert(b.LineColToPos(line, col), value)
b.shiftAnchors(line, col, utf8.RuneCount(value))
} }
// Remove deletes any characters between startLine, startCol, and endLine, // Remove deletes any characters between startLine, startCol, and endLine,
@ -126,11 +127,15 @@ func (b *RopeBuffer) Remove(startLine, startCol, endLine, endCol int) {
if len := b.rope.Len(); end >= len { if len := b.rope.Len(); end >= len {
end = len end = len
if start > end { if start > end {
start = end return
} }
} }
b.rope.Remove(start, end) b.rope.Remove(start, end)
// Shift anchors within the range
b.shiftAnchorsRemovedRange(start, startLine, startCol, endLine, endCol)
// Shift anchors after the range
b.shiftAnchors(endLine, endCol+1, start-end-1)
} }
// 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
@ -328,6 +333,31 @@ func (b *RopeBuffer) WriteTo(w io.Writer) (int64, error) {
return b.rope.WriteTo(w) return b.rope.WriteTo(w)
} }
// Currently meant for the Remove function: imagine if the removed region passes through a Cursor position.
// We want to shift the cursor to the start of the region, based upon where the cursor position is.
func (b *RopeBuffer) shiftAnchorsRemovedRange(startPos, startLine, startCol, endLine, endCol int) {
for _, v := range b.anchors {
cursorLine, cursorCol := v.GetLineCol()
if cursorLine >= startLine && cursorLine <= endLine {
// If the anchor is not within the start or end columns
if (cursorLine == startLine && cursorCol < startCol) || (cursorLine == endLine && cursorCol > endCol) {
continue
}
cursorPos := b.LineColToPos(cursorLine, cursorCol)
v.line, v.col = b.PosToLineCol(cursorPos + (startPos - cursorPos))
}
}
}
func (b *RopeBuffer) shiftAnchors(insertLine, insertCol, runeCount int) {
for _, v := range b.anchors {
cursorLine, cursorCol := v.GetLineCol()
if insertLine < cursorLine || (insertLine == cursorLine && insertCol <= cursorCol) {
v.line, v.col = b.PosToLineCol(b.LineColToPos(cursorLine, cursorCol) + runeCount)
}
}
}
// RegisterCursor adds the Cursor to a slice which the Buffer uses to update // RegisterCursor adds the Cursor to a slice which the Buffer uses to update
// each Cursor based on changes that occur in the Buffer. Various functions are // each Cursor based on changes that occur in the Buffer. Various functions are
// called on the Cursor depending upon where the edits occurred and how it should // called on the Cursor depending upon where the edits occurred and how it should

View File

@ -77,6 +77,7 @@ loop:
t.Buffer = buffer.NewRopeBuffer(contents) t.Buffer = buffer.NewRopeBuffer(contents)
t.cursor = buffer.NewCursor(&t.Buffer) t.cursor = buffer.NewCursor(&t.Buffer)
t.Buffer.RegisterCursor(&t.cursor)
t.selection = buffer.NewRegion(&t.Buffer) t.selection = buffer.NewRegion(&t.Buffer)
// TODO: replace with automatic determination of language via filetype // TODO: replace with automatic determination of language via filetype
@ -173,6 +174,7 @@ func (t *TextEdit) Delete(forwards bool) {
// If the cursor is not at the first column of the first line... // If the cursor is not at the first column of the first line...
if cursLine > 0 || cursCol > 0 { if cursLine > 0 || cursCol > 0 {
t.cursor = t.cursor.Left() // Back up to that character t.cursor = t.cursor.Left() // Back up to that character
cursLine, cursCol = t.cursor.GetLineCol()
bytes := t.Buffer.Slice(cursLine, cursCol, cursLine, cursCol) // Get the char at cursor bytes := t.Buffer.Slice(cursLine, cursCol, cursLine, cursCol) // Get the char at cursor
deletedLine = bytes[0] == '\n' deletedLine = bytes[0] == '\n'
@ -233,7 +235,6 @@ func (t *TextEdit) Insert(contents string) {
default: default:
// Insert character into line // Insert character into line
t.Buffer.Insert(cursLine, cursCol, []byte(string(ch))) t.Buffer.Insert(cursLine, cursCol, []byte(string(ch)))
// t.SetLineCol(t.cury, t.curx+1) // Advance the cursor
} }
} }