Hmm... Tim didn't turn "replace all" into a single undo block.
I think I like it better if it os, so here.
diff --git a/Tools/idle/ReplaceDialog.py b/Tools/idle/ReplaceDialog.py
index 813de48..e29d4d6 100644
--- a/Tools/idle/ReplaceDialog.py
+++ b/Tools/idle/ReplaceDialog.py
@@ -82,6 +82,7 @@
ok = 1
first = last = None
# XXX ought to replace circular instead of top-to-bottom when wrapping
+ text.undo_block_start()
while 1:
res = self.engine.search_forward(text, prog, line, col, 0, ok)
if not res:
@@ -103,6 +104,7 @@
text.insert(first, new)
col = i + len(new)
ok = 0
+ text.undo_block_stop()
if first and last:
self.show_hit(first, last)
self.close()