A lot of changes that I wasn't able to properly commit months ago
This commit is contained in:
10
pkg/buffer/buffer.go
Executable file → Normal file
10
pkg/buffer/buffer.go
Executable file → Normal file
@@ -23,6 +23,16 @@ type Buffer interface {
|
||||
// so do not write to it.
|
||||
Slice(startLine, startCol, endLine, endCol int) []byte
|
||||
|
||||
// RuneAtPos returns the UTF-8 rune at the byte position `pos` of the buffer. The
|
||||
// position must be a correct position, otherwise zero is returned.
|
||||
RuneAtPos(pos int) rune
|
||||
|
||||
// EachRuneAtPos executes the function `f` at each rune after byte position `pos`.
|
||||
// This function should be used as opposed to performing a "per character" operation
|
||||
// manually, as it enables caching buffer operations and safety checks. The function
|
||||
// returns when the end of the buffer is met or `f` returns true.
|
||||
EachRuneAtPos(pos int, f func(pos int, r rune) bool)
|
||||
|
||||
// Bytes returns all of the bytes in the buffer. This function is very likely
|
||||
// to copy all of the data in the buffer. Use sparingly. Try using other methods,
|
||||
// where possible.
|
||||
|
58
pkg/buffer/cursor.go
Executable file → Normal file
58
pkg/buffer/cursor.go
Executable file → Normal file
@@ -1,6 +1,9 @@
|
||||
package buffer
|
||||
|
||||
import "math"
|
||||
import (
|
||||
"math"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// So why is the code for moving the cursor in the buffer package, and not in the
|
||||
// TextEdit component? Well, it used to be, but it sucked that way. The cursor
|
||||
@@ -86,6 +89,41 @@ func (c Cursor) Down() Cursor {
|
||||
return c
|
||||
}
|
||||
|
||||
// NextWordBoundaryEnd proceeds to the position after the last character of the
|
||||
// next word boundary to the right of the Cursor. A word boundary is the
|
||||
// beginning or end of any sequence of similar or same-classed characters.
|
||||
// Whitespace is skipped.
|
||||
func (c Cursor) NextWordBoundaryEnd() Cursor {
|
||||
// Get position of cursor in buffer as pos
|
||||
// get classification of character at pos or assume none if whitespace
|
||||
// for each pos until end of buffer: pos + 1 (at end)
|
||||
// if pos char is not of previous pos char class:
|
||||
// set cursor position as pos
|
||||
//
|
||||
|
||||
// only skip contiguous characters for word characters
|
||||
// jump to position *after* any symbols
|
||||
|
||||
pos := (*c.buffer).LineColToPos(c.line, c.col)
|
||||
startClass := getRuneCharclass((*c.buffer).RuneAtPos(pos))
|
||||
pos++
|
||||
(*c.buffer).EachRuneAtPos(pos, func(rpos int, r rune) bool {
|
||||
class := getRuneCharclass(r)
|
||||
if class != startClass && class != charwhitespace {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
c.line, c.col = (*c.buffer).PosToLineCol(pos)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c Cursor) PrevWordBoundaryStart() Cursor {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c Cursor) GetLineCol() (line, col int) {
|
||||
return c.line, c.col
|
||||
}
|
||||
@@ -101,3 +139,21 @@ func (c Cursor) SetLineCol(line, col int) Cursor {
|
||||
func (c Cursor) Eq(other Cursor) bool {
|
||||
return c.buffer == other.buffer && c.line == other.line && c.col == other.col
|
||||
}
|
||||
|
||||
type charclass uint8
|
||||
|
||||
const (
|
||||
charwhitespace charclass = iota
|
||||
charword
|
||||
charsymbol
|
||||
)
|
||||
|
||||
func getRuneCharclass(r rune) charclass {
|
||||
if unicode.IsSpace(r) {
|
||||
return charwhitespace
|
||||
} else if r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) {
|
||||
return charword
|
||||
} else {
|
||||
return charsymbol
|
||||
}
|
||||
}
|
||||
|
0
pkg/buffer/highlighter.go
Executable file → Normal file
0
pkg/buffer/highlighter.go
Executable file → Normal file
0
pkg/buffer/language.go
Executable file → Normal file
0
pkg/buffer/language.go
Executable file → Normal file
34
pkg/buffer/rope.go
Executable file → Normal file
34
pkg/buffer/rope.go
Executable file → Normal file
@@ -96,6 +96,40 @@ func (b *RopeBuffer) Slice(startLine, startCol, endLine, endCol int) []byte {
|
||||
return b.rope.Slice(b.LineColToPos(startLine, startCol), endPos+1)
|
||||
}
|
||||
|
||||
// RuneAtPos returns the UTF-8 rune at the byte position `pos` of the buffer. The
|
||||
// position must be a correct position, otherwise zero is returned.
|
||||
func (b *RopeBuffer) RuneAtPos(pos int) (val rune) {
|
||||
_, r := b.rope.SplitAt(pos)
|
||||
l, _ := r.SplitAt(b.rope.Len() - pos)
|
||||
|
||||
l.EachLeaf(func(n *ropes.Node) bool {
|
||||
data := n.Value() // Reference; not a copy.
|
||||
val, _ = utf8.DecodeRune(data[0:])
|
||||
return true
|
||||
})
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// EachRuneAtPos executes the function `f` at each rune after byte position `pos`.
|
||||
// This function should be used as opposed to performing a "per character" operation
|
||||
// manually, as it enables caching buffer operations and safety checks. The function
|
||||
// returns when the end of the buffer is met or `f` returns true.
|
||||
func (b *RopeBuffer) EachRuneAtPos(pos int, f func(pos int, r rune) bool) {
|
||||
_, r := b.rope.SplitAt(pos)
|
||||
l, _ := r.SplitAt(b.rope.Len() - pos)
|
||||
|
||||
l.EachLeaf(func(n *ropes.Node) bool {
|
||||
data := n.Value() // Reference; not a copy.
|
||||
for i, r := range string(data) {
|
||||
if f(pos+i, r) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
// Bytes returns all of the bytes in the buffer. This function is very likely
|
||||
// to copy all of the data in the buffer. Use sparingly. Try using other methods,
|
||||
// where possible.
|
||||
|
Reference in New Issue
Block a user