Editing needs a place - a cursor. Today you introduce the editor, which owns a buffer and a cursor position, and translate that row-and-column position into a byte offset in the buffer.
Create an editor over a buffer with a cursor at row 0, column 0, and map any cursor position to a buffer offset.
The buffer knows text; it does not know where you are in it. That is the
cursor’s job, and the cursor needs an owner that also holds the buffer, so this
lesson introduces the editor: a buffer plus a Row and Col. Wiring the two
together in one type now is deliberate - every editing and movement operation from
here needs both the text and the position, and giving them a shared home is the
design decision that lets those operations be simple methods.
The one piece of real logic is the bridge between the two coordinate systems. The
cursor thinks in (row, col); the buffer thinks in a single flat offset. They
relate by exactly one formula: the offset is the line’s start plus the column.
Offset() is small, but it is the hinge the whole editor turns on - inserting,
deleting, and searching all happen at the cursor, and they all reach the buffer
through this translation.
// the editor pairs a buffer with a cursor positiontype Editor struct { Buf *Buffer; Row, Col int }func NewEditor(b *Buffer) *Editor { return &Editor{Buf: b} }// a (row, col) cursor is one offset into the flat buffer:func (e *Editor) Offset() int { return e.Buf.LineStart(e.Row) + e.Col }