package tokenize import "fmt" // 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 { c.Byte += len(input) for _, r := range input { c.Rune++ if r == '\n' { c.Column = 0 c.Line++ } else { c.Column++ } } return c }