summaryrefslogtreecommitdiffstats
path: root/Lib/idlelib/replace.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/idlelib/replace.py')
-rw-r--r--Lib/idlelib/replace.py111
1 files changed, 87 insertions, 24 deletions
diff --git a/Lib/idlelib/replace.py b/Lib/idlelib/replace.py
index 4a834eb..6be034a 100644
--- a/Lib/idlelib/replace.py
+++ b/Lib/idlelib/replace.py
@@ -1,7 +1,7 @@
"""Replace dialog for IDLE. Inherits SearchDialogBase for GUI.
-Uses idlelib.SearchEngine for search capability.
+Uses idlelib.searchengine.SearchEngine for search capability.
Defines various replace related functions like replace, replace all,
-replace+find.
+and replace+find.
"""
import re
@@ -10,9 +10,16 @@ from tkinter import StringVar, TclError
from idlelib.searchbase import SearchDialogBase
from idlelib import searchengine
+
def replace(text):
- """Returns a singleton ReplaceDialog instance.The single dialog
- saves user entries and preferences across instances."""
+ """Create or reuse a singleton ReplaceDialog instance.
+
+ The singleton dialog saves user entries and preferences
+ across instances.
+
+ Args:
+ text: Text widget containing the text to be searched.
+ """
root = text._root()
engine = searchengine.get(root)
if not hasattr(engine, "_replacedialog"):
@@ -22,16 +29,36 @@ def replace(text):
class ReplaceDialog(SearchDialogBase):
+ "Dialog for finding and replacing a pattern in text."
title = "Replace Dialog"
icon = "Replace"
def __init__(self, root, engine):
- SearchDialogBase.__init__(self, root, engine)
+ """Create search dialog for finding and replacing text.
+
+ Uses SearchDialogBase as the basis for the GUI and a
+ searchengine instance to prepare the search.
+
+ Attributes:
+ replvar: StringVar containing 'Replace with:' value.
+ replent: Entry widget for replvar. Created in
+ create_entries().
+ ok: Boolean used in searchengine.search_text to indicate
+ whether the search includes the selection.
+ """
+ super().__init__(root, engine)
self.replvar = StringVar(root)
def open(self, text):
- """Display the replace dialog"""
+ """Make dialog visible on top of others and ready to use.
+
+ Also, highlight the currently selected text and set the
+ search to include the current selection (self.ok).
+
+ Args:
+ text: Text widget being searched.
+ """
SearchDialogBase.open(self, text)
try:
first = text.index("sel.first")
@@ -44,37 +71,50 @@ class ReplaceDialog(SearchDialogBase):
first = first or text.index("insert")
last = last or first
self.show_hit(first, last)
- self.ok = 1
+ self.ok = True
def create_entries(self):
- """Create label and text entry widgets"""
+ "Create base and additional label and text entry widgets."
SearchDialogBase.create_entries(self)
self.replent = self.make_entry("Replace with:", self.replvar)[0]
def create_command_buttons(self):
+ """Create base and additional command buttons.
+
+ The additional buttons are for Find, Replace,
+ Replace+Find, and Replace All.
+ """
SearchDialogBase.create_command_buttons(self)
self.make_button("Find", self.find_it)
self.make_button("Replace", self.replace_it)
- self.make_button("Replace+Find", self.default_command, 1)
+ self.make_button("Replace+Find", self.default_command, isdef=True)
self.make_button("Replace All", self.replace_all)
def find_it(self, event=None):
- self.do_find(0)
+ "Handle the Find button."
+ self.do_find(False)
def replace_it(self, event=None):
+ """Handle the Replace button.
+
+ If the find is successful, then perform replace.
+ """
if self.do_find(self.ok):
self.do_replace()
def default_command(self, event=None):
- "Replace and find next."
+ """Handle the Replace+Find button as the default command.
+
+ First performs a replace and then, if the replace was
+ successful, a find next.
+ """
if self.do_find(self.ok):
if self.do_replace(): # Only find next match if replace succeeded.
# A bad re can cause it to fail.
- self.do_find(0)
+ self.do_find(False)
def _replace_expand(self, m, repl):
- """ Helper function for expanding a regular expression
- in the replace field, if needed. """
+ "Expand replacement text if regular expression."
if self.engine.isre():
try:
new = m.expand(repl)
@@ -87,7 +127,15 @@ class ReplaceDialog(SearchDialogBase):
return new
def replace_all(self, event=None):
- """Replace all instances of patvar with replvar in text"""
+ """Handle the Replace All button.
+
+ Search text for occurrences of the Find value and replace
+ each of them. The 'wrap around' value controls the start
+ point for searching. If wrap isn't set, then the searching
+ starts at the first occurrence after the current selection;
+ if wrap is set, the replacement starts at the first line.
+ The replacement is always done top-to-bottom in the text.
+ """
prog = self.engine.getprog()
if not prog:
return
@@ -104,12 +152,13 @@ class ReplaceDialog(SearchDialogBase):
if self.engine.iswrap():
line = 1
col = 0
- ok = 1
+ ok = True
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)
+ while True:
+ res = self.engine.search_forward(text, prog, line, col,
+ wrap=False, ok=ok)
if not res:
break
line, m = res
@@ -130,13 +179,17 @@ class ReplaceDialog(SearchDialogBase):
if new:
text.insert(first, new)
col = i + len(new)
- ok = 0
+ ok = False
text.undo_block_stop()
if first and last:
self.show_hit(first, last)
self.close()
- def do_find(self, ok=0):
+ def do_find(self, ok=False):
+ """Search for and highlight next occurrence of pattern in text.
+
+ No text replacement is done with this option.
+ """
if not self.engine.getprog():
return False
text = self.text
@@ -149,10 +202,11 @@ class ReplaceDialog(SearchDialogBase):
first = "%d.%d" % (line, i)
last = "%d.%d" % (line, j)
self.show_hit(first, last)
- self.ok = 1
+ self.ok = True
return True
def do_replace(self):
+ "Replace search pattern in text with replacement value."
prog = self.engine.getprog()
if not prog:
return False
@@ -180,12 +234,20 @@ class ReplaceDialog(SearchDialogBase):
text.insert(first, new)
text.undo_block_stop()
self.show_hit(first, text.index("insert"))
- self.ok = 0
+ self.ok = False
return True
def show_hit(self, first, last):
- """Highlight text from 'first' to 'last'.
- 'first', 'last' - Text indices"""
+ """Highlight text between first and last indices.
+
+ Text is highlighted via the 'hit' tag and the marked
+ section is brought into view.
+
+ The colors from the 'hit' tag aren't currently shown
+ when the text is displayed. This is due to the 'sel'
+ tag being added first, so the colors in the 'sel'
+ config are seen instead of the colors for 'hit'.
+ """
text = self.text
text.mark_set("insert", first)
text.tag_remove("sel", "1.0", "end")
@@ -199,6 +261,7 @@ class ReplaceDialog(SearchDialogBase):
text.update_idletasks()
def close(self, event=None):
+ "Close the dialog and remove hit tags."
SearchDialogBase.close(self, event)
self.text.tag_remove("hit", "1.0", "end")