is theSoundsSounds like Cursor
represents a position in a Document
. The Document
class should ultimately be responsible for all primitive operations like inserting, deleting, gabbinggrabbing text and moving around. Most of these operations require a position as input and some may also return a position as output. A Cursor
holds a Document
and a position. Cursor
could just be a concrete data class which just holds the position and the Document
, basically a pair. The other approach is to make Cursor
a first class abstraction. In that case its API will just mirror that of Document
, and each method will be just a thin wrapper around the corresponding method on Document
, but the methods on Cursor
will omit the position parameter since they will fill that with the position from the Cursor
.
The basic pattern is something like
cursor.someMethod(arg1, ...) = cursor.doc.someMethod(cursor.pos, arg1, ...)
except if the Document
method returns a position then the Cursor
method should package that together with the document and to return a cursor like
cursor.cursorMethodotherMethod(arg1, ...) = new Cursor(cursor.doc,
cursor.doc.cursorMethodotherMethod(cursor.pos, arg1, ...))
The drawback of this approach is the boiler plate on the implementation side, but it makes the library much nicer to use on the client side. Since the required boilerplate is simple and systematic you may be able to avoid writing it manually by either generating it, or doing the delegation through reflective calls if you are using a language with decent reflection capacities or a reasonably powerful preprocessor.
You still need to decide what a position is. It can be just a number representing the character position in the whole document (eg Emacs), a pair representing the line and position on the line, or a in C/C++ a pointer directly into the underlying container. I would recommend making position a member type on Document
if your language supports that. That way each Document
implementation can supply its own position type definition. Cursor
treats positions as completely abstract, it just hold them and passes them to Document
methods. only Document
cares how they are implemented.