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 stackundo(): pop the most recent command and undo it; do nothing if the stack is emptyclass 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
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
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 stackundo(): pop the most recent command and undo it; do nothing if the stack is emptyPress Run Tests or ββ© to check your solution.