Capture more than one field

Step 4: Capture more than one field

A snapshot should capture everything that defines the editor's state, not just the text. Now the Editor also tracks a cursor position (an integer).

The Memento class does not change at all. Its power is that it stores state opaquely: the caretaker never knows or cares whether that state is one string or a bundle of several values.

Extend save and restore so a snapshot round-trips both fields:

  • save() stores content and cursor together, for example as a tuple, inside a single Memento.
  • restore(memento) unpacks that snapshot back into content and cursor.

Because backup, undo, and redo all go through save and restore, once you widen the snapshot every history feature automatically preserves the cursor too, with no other changes needed.

Hints
Starter code
class Memento:
    def __init__(self, state):
        self._state = state

    def get_state(self):
        return self._state


class Editor:
    def __init__(self):
        self.content = ""
        self.cursor = 0
        self._history = []
        self._redo = []

    def save(self):
        """Capture BOTH content and cursor opaquely in a Memento."""
        # TODO: store (self.content, self.cursor) in the Memento instead
        return Memento(self.content)

    def restore(self, memento):
        """Restore BOTH content and cursor from the memento."""
        # TODO: unpack the memento's state into self.content and self.cursor
        self.content = memento.get_state()

    def backup(self):
        self._history.append(self.save())
        self._redo = []

    def undo(self):
        if not self._history:
            return
        self._redo.append(self.save())
        memento = self._history.pop()
        self.restore(memento)

    def redo(self):
        if not self._redo:
            return
        memento = self._redo.pop()
        self.restore(memento)
Write it on a laptop

The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.