46 lines
1.1 KiB
Go
46 lines
1.1 KiB
Go
package tokenize2
|
|
|
|
import (
|
|
"fmt"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// Cursor represents the position of a cursor in various ways.
|
|
type Cursor struct {
|
|
Byte int // The cursor offset in bytes
|
|
Rune int // The cursor offset in UTF8 runes
|
|
Column int // The column at which the cursor is (0-indexed)
|
|
Line int // The line at which the cursor is (0-indexed)
|
|
}
|
|
|
|
// String produces a string representation of the cursor position.
|
|
func (c Cursor) String() string {
|
|
if c.Line == 0 && c.Column == 0 {
|
|
return fmt.Sprintf("start of file")
|
|
}
|
|
return fmt.Sprintf("line %d, column %d", c.Line+1, c.Column+1)
|
|
}
|
|
|
|
// move updates the position of the cursor, based on the provided input string.
|
|
// The input string represents the runes that the cursor must be moved over.
|
|
// This method will take newlines into account to keep track of line numbers and
|
|
// column positions automatically.
|
|
func (c *Cursor) move(input string) *Cursor {
|
|
for _, r := range input {
|
|
c.moveByRune(r)
|
|
}
|
|
return c
|
|
}
|
|
|
|
func (c *Cursor) moveByRune(r rune) *Cursor {
|
|
c.Byte += utf8.RuneLen(r)
|
|
c.Rune++
|
|
if r == '\n' {
|
|
c.Column = 0
|
|
c.Line++
|
|
} else {
|
|
c.Column++
|
|
}
|
|
return c
|
|
}
|