Text Editor with Undo & Redo — 75-Minute Interview Guide
Quick Start
5-Minute Overview
A collaborative text editor supporting unlimited undo/redo, text operations (insert, delete, replace), selection management, and command-based architecture. Core flow: Type → Command → Execute → Add to UndoStack → Redo available.
Key Entities
| Entity | Purpose |
|---|---|
| TextBuffer | Core document content |
| Command | Text operation (insert, delete, replace) |
| Memento | Document snapshot for undo |
| Editor | Orchestrator managing buffer, stacks |
4 Design Patterns
- Command: Execute, undo, redo operations
- Memento: Save/restore document states
- Singleton: Central editor instance
- Observer: Notify UI of changes
Critical Points
✅ Unlimited undo/redo → Command + stack pattern
✅ Efficient storage → Memento snapshots
✅ Text operations → Insert O(1), Delete O(n), Replace O(n)
✅ Memory optimization → Store deltas not full copies
System Overview
Problem
Users need unlimited undo/redo for text editors. Naive approach (full document copy per action) = memory overhead.
Solution
Command pattern for operations + Memento for snapshots + incremental storage.
Requirements
✅ Insert text at position
✅ Delete text range
✅ Replace text
✅ Undo (infinite depth)
✅ Redo (while not executing new command)
✅ Save position (selection)
✅ Efficient memory usage
Architecture & Patterns
1. Command Pattern
class Command(ABC):
@abstractmethod
def execute(self):
pass
@abstractmethod
def undo(self):
pass
class InsertCommand(Command):
def __init__(self, buffer, position, text):
self.buffer = buffer
self.position = position
self.text = text
def execute(self):
self.buffer.insert(self.position, self.text)
def undo(self):
self.buffer.delete(self.position, len(self.text))
2. Memento Pattern
class EditorMemento:
def __init__(self, content, position):
self.content = content
self.position = position
class TextBuffer:
def save_memento(self):
return EditorMemento(self.content, self.cursor)
def restore_memento(self, memento):
self.content = memento.content
self.cursor = memento.position
3. Singleton Editor
class Editor:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance.buffer = TextBuffer()
cls._instance.undo_stack = []
cls._instance.redo_stack = []
return cls._instance
Interview Q&A
Q1: Undo stack implementation?
A: Stack of Command objects. On undo: pop, call command.undo(). On redo: pop from redo stack, execute.
Q2: Memory optimization?
A: Store deltas (operation details) not full document copies. Rebuild state from operation history.
Q3: Concurrent edits?
A: Operational Transformation (OT) for concurrent text editing. Each operation includes position adjustment.
Q4: Large document performance?
A: Lazy undo - only compute full state when needed. Use rope data structure for efficient insert/delete.
Q5: Selection persistence?
A: Store (start, end) positions in Memento. Restore selection on undo/redo.
Scaling Q&A
Q1: Collaborative editing (multiple users)?
A: Operational Transformation (OT) or CRDTs (Conflict-free Replicated Data Types) to merge edits.
Q2: Undo depth limit?
A: Cap at 1000 commands max. Delete oldest when exceeded. Or compress old commands into snapshots.
Q3: Network sync?
A: Publish each operation to Kafka. Other clients subscribe and apply operations locally.
Demo
editor = Editor()
editor.insert(0, "Hello")
editor.insert(5, " World")
print(editor.content) # "Hello World"
editor.undo() # "Hello"
editor.undo() # ""
editor.redo() # "Hello"
editor.redo() # "Hello World"
Ready for editing! ✏️