Redo needs a second stack. When you undo a command, push it onto a redo stack; redo pops it back and re-executes it. The catch every editor gets right: doing a new action clears the redo history, because you have branched away from that future.
do and undo already maintain the redo stack. Implement redo.
redo(): pop the most recently undone command, re-execute it, and push it back onto the undo stack; no-op if there is nothing to redoclass 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 = []
self._redo_stack = []
def do(self, command):
command.execute(self.doc)
self._undo_stack.append(command)
self._redo_stack.clear() # a new action invalidates the redo future
def undo(self):
if self._undo_stack:
command = self._undo_stack.pop()
command.undo(self.doc)
self._redo_stack.append(command)
def redo(self):
"""Re-apply the most recently undone command."""
# TODO: mirror undo in the other direction. Take the most recently undone
# command off the top of self._redo_stack, run it forward against
# self.doc, and move it back onto self._undo_stack so it can be undone
# again. With an empty redo stack this does nothing at all.
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.
Redo needs a second stack. When you undo a command, push it onto a redo stack; redo pops it back and re-executes it. The catch every editor gets right: doing a new action clears the redo history, because you have branched away from that future.
do and undo already maintain the redo stack. Implement redo.
redo(): pop the most recently undone command, re-execute it, and push it back onto the undo stack; no-op if there is nothing to redoPress Run Tests or ββ© to check your solution.