Build Undo/RedoStep 2 of 5

The Undo Stack

Step 2: The Undo Stack

Undo is last-in, first-out. You reverse actions newest-first. That is exactly a stack. The Editor is the invoker: it runs commands and remembers them on an undo stack so it can reverse them.

  • do(command): execute the command on the document and push it onto the undo stack
  • undo(): pop the most recent command and undo it; do nothing if the stack is empty
Hints
Starter code
class Document:
    def __init__(self, text=""):
        self.text = text


class Command:
    def execute(self, doc):
        raise NotImplementedError

    def undo(self, doc):
        raise NotImplementedError


class Insert(Command):
    def __init__(self, pos, text):
        self.pos = pos
        self.text = text

    def execute(self, doc):
        doc.text = doc.text[:self.pos] + self.text + doc.text[self.pos:]

    def undo(self, doc):
        doc.text = doc.text[:self.pos] + doc.text[self.pos + len(self.text):]


class Editor:
    def __init__(self, text=""):
        self.doc = Document(text)
        self._undo_stack = []

    def do(self, command):
        """Execute the command and remember it for undo."""
        # TODO: command.execute(self.doc); self._undo_stack.append(command)
        pass

    def undo(self):
        """Undo the most recent command (LIFO). No-op if nothing to undo."""
        # TODO:
        #   if self._undo_stack:
        #       command = self._undo_stack.pop()
        #       command.undo(self.doc)
        pass

    @property
    def text(self):
        return self.doc.text
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.