bpo-23216: IDLE: Add docstrings to search modules (GH-12141) · python/cpython@0bb5e75 (original) (raw)
1
1
`"""Replace dialog for IDLE. Inherits SearchDialogBase for GUI.
`
2
``
`-
Uses idlelib.SearchEngine for search capability.
`
``
2
`+
Uses idlelib.searchengine.SearchEngine for search capability.
`
3
3
`Defines various replace related functions like replace, replace all,
`
4
``
`-
replace+find.
`
``
4
`+
and replace+find.
`
5
5
`"""
`
6
6
`import re
`
7
7
``
`@@ -10,9 +10,16 @@
`
10
10
`from idlelib.searchbase import SearchDialogBase
`
11
11
`from idlelib import searchengine
`
12
12
``
``
13
+
13
14
`def replace(text):
`
14
``
`-
"""Returns a singleton ReplaceDialog instance.The single dialog
`
15
``
`-
saves user entries and preferences across instances."""
`
``
15
`+
"""Create or reuse a singleton ReplaceDialog instance.
`
``
16
+
``
17
`+
The singleton dialog saves user entries and preferences
`
``
18
`+
across instances.
`
``
19
+
``
20
`+
Args:
`
``
21
`+
text: Text widget containing the text to be searched.
`
``
22
`+
"""
`
16
23
`root = text._root()
`
17
24
`engine = searchengine.get(root)
`
18
25
`if not hasattr(engine, "_replacedialog"):
`
`@@ -22,16 +29,36 @@ def replace(text):
`
22
29
``
23
30
``
24
31
`class ReplaceDialog(SearchDialogBase):
`
``
32
`+
"Dialog for finding and replacing a pattern in text."
`
25
33
``
26
34
`title = "Replace Dialog"
`
27
35
`icon = "Replace"
`
28
36
``
29
37
`def init(self, root, engine):
`
30
``
`-
SearchDialogBase.init(self, root, engine)
`
``
38
`+
"""Create search dialog for finding and replacing text.
`
``
39
+
``
40
`+
Uses SearchDialogBase as the basis for the GUI and a
`
``
41
`+
searchengine instance to prepare the search.
`
``
42
+
``
43
`+
Attributes:
`
``
44
`+
replvar: StringVar containing 'Replace with:' value.
`
``
45
`+
replent: Entry widget for replvar. Created in
`
``
46
`+
create_entries().
`
``
47
`+
ok: Boolean used in searchengine.search_text to indicate
`
``
48
`+
whether the search includes the selection.
`
``
49
`+
"""
`
``
50
`+
super().init(root, engine)
`
31
51
`self.replvar = StringVar(root)
`
32
52
``
33
53
`def open(self, text):
`
34
``
`-
"""Display the replace dialog"""
`
``
54
`+
"""Make dialog visible on top of others and ready to use.
`
``
55
+
``
56
`+
Also, highlight the currently selected text and set the
`
``
57
`+
search to include the current selection (self.ok).
`
``
58
+
``
59
`+
Args:
`
``
60
`+
text: Text widget being searched.
`
``
61
`+
"""
`
35
62
`SearchDialogBase.open(self, text)
`
36
63
`try:
`
37
64
`first = text.index("sel.first")
`
`@@ -44,37 +71,50 @@ def open(self, text):
`
44
71
`first = first or text.index("insert")
`
45
72
`last = last or first
`
46
73
`self.show_hit(first, last)
`
47
``
`-
self.ok = 1
`
``
74
`+
self.ok = True
`
48
75
``
49
76
`def create_entries(self):
`
50
``
`-
"""Create label and text entry widgets"""
`
``
77
`+
"Create base and additional label and text entry widgets."
`
51
78
`SearchDialogBase.create_entries(self)
`
52
79
`self.replent = self.make_entry("Replace with:", self.replvar)[0]
`
53
80
``
54
81
`def create_command_buttons(self):
`
``
82
`+
"""Create base and additional command buttons.
`
``
83
+
``
84
`+
The additional buttons are for Find, Replace,
`
``
85
`+
Replace+Find, and Replace All.
`
``
86
`+
"""
`
55
87
`SearchDialogBase.create_command_buttons(self)
`
56
88
`self.make_button("Find", self.find_it)
`
57
89
`self.make_button("Replace", self.replace_it)
`
58
``
`-
self.make_button("Replace+Find", self.default_command, 1)
`
``
90
`+
self.make_button("Replace+Find", self.default_command, isdef=True)
`
59
91
`self.make_button("Replace All", self.replace_all)
`
60
92
``
61
93
`def find_it(self, event=None):
`
62
``
`-
self.do_find(0)
`
``
94
`+
"Handle the Find button."
`
``
95
`+
self.do_find(False)
`
63
96
``
64
97
`def replace_it(self, event=None):
`
``
98
`+
"""Handle the Replace button.
`
``
99
+
``
100
`+
If the find is successful, then perform replace.
`
``
101
`+
"""
`
65
102
`if self.do_find(self.ok):
`
66
103
`self.do_replace()
`
67
104
``
68
105
`def default_command(self, event=None):
`
69
``
`-
"Replace and find next."
`
``
106
`+
"""Handle the Replace+Find button as the default command.
`
``
107
+
``
108
`+
First performs a replace and then, if the replace was
`
``
109
`+
successful, a find next.
`
``
110
`+
"""
`
70
111
`if self.do_find(self.ok):
`
71
112
`if self.do_replace(): # Only find next match if replace succeeded.
`
72
113
`# A bad re can cause it to fail.
`
73
``
`-
self.do_find(0)
`
``
114
`+
self.do_find(False)
`
74
115
``
75
116
`def _replace_expand(self, m, repl):
`
76
``
`-
""" Helper function for expanding a regular expression
`
77
``
`-
in the replace field, if needed. """
`
``
117
`+
"Expand replacement text if regular expression."
`
78
118
`if self.engine.isre():
`
79
119
`try:
`
80
120
`new = m.expand(repl)
`
`@@ -87,7 +127,15 @@ def _replace_expand(self, m, repl):
`
87
127
`return new
`
88
128
``
89
129
`def replace_all(self, event=None):
`
90
``
`-
"""Replace all instances of patvar with replvar in text"""
`
``
130
`+
"""Handle the Replace All button.
`
``
131
+
``
132
`+
Search text for occurrences of the Find value and replace
`
``
133
`+
each of them. The 'wrap around' value controls the start
`
``
134
`+
point for searching. If wrap isn't set, then the searching
`
``
135
`+
starts at the first occurrence after the current selection;
`
``
136
`+
if wrap is set, the replacement starts at the first line.
`
``
137
`+
The replacement is always done top-to-bottom in the text.
`
``
138
`+
"""
`
91
139
`prog = self.engine.getprog()
`
92
140
`if not prog:
`
93
141
`return
`
`@@ -104,12 +152,13 @@ def replace_all(self, event=None):
`
104
152
`if self.engine.iswrap():
`
105
153
`line = 1
`
106
154
`col = 0
`
107
``
`-
ok = 1
`
``
155
`+
ok = True
`
108
156
`first = last = None
`
109
157
`# XXX ought to replace circular instead of top-to-bottom when wrapping
`
110
158
`text.undo_block_start()
`
111
``
`-
while 1:
`
112
``
`-
res = self.engine.search_forward(text, prog, line, col, 0, ok)
`
``
159
`+
while True:
`
``
160
`+
res = self.engine.search_forward(text, prog, line, col,
`
``
161
`+
wrap=False, ok=ok)
`
113
162
`if not res:
`
114
163
`break
`
115
164
`line, m = res
`
`@@ -130,13 +179,17 @@ def replace_all(self, event=None):
`
130
179
`if new:
`
131
180
`text.insert(first, new)
`
132
181
`col = i + len(new)
`
133
``
`-
ok = 0
`
``
182
`+
ok = False
`
134
183
`text.undo_block_stop()
`
135
184
`if first and last:
`
136
185
`self.show_hit(first, last)
`
137
186
`self.close()
`
138
187
``
139
``
`-
def do_find(self, ok=0):
`
``
188
`+
def do_find(self, ok=False):
`
``
189
`+
"""Search for and highlight next occurrence of pattern in text.
`
``
190
+
``
191
`+
No text replacement is done with this option.
`
``
192
`+
"""
`
140
193
`if not self.engine.getprog():
`
141
194
`return False
`
142
195
`text = self.text
`
`@@ -149,10 +202,11 @@ def do_find(self, ok=0):
`
149
202
`first = "%d.%d" % (line, i)
`
150
203
`last = "%d.%d" % (line, j)
`
151
204
`self.show_hit(first, last)
`
152
``
`-
self.ok = 1
`
``
205
`+
self.ok = True
`
153
206
`return True
`
154
207
``
155
208
`def do_replace(self):
`
``
209
`+
"Replace search pattern in text with replacement value."
`
156
210
`prog = self.engine.getprog()
`
157
211
`if not prog:
`
158
212
`return False
`
`@@ -180,12 +234,20 @@ def do_replace(self):
`
180
234
`text.insert(first, new)
`
181
235
`text.undo_block_stop()
`
182
236
`self.show_hit(first, text.index("insert"))
`
183
``
`-
self.ok = 0
`
``
237
`+
self.ok = False
`
184
238
`return True
`
185
239
``
186
240
`def show_hit(self, first, last):
`
187
``
`-
"""Highlight text from 'first' to 'last'.
`
188
``
`-
'first', 'last' - Text indices"""
`
``
241
`+
"""Highlight text between first and last indices.
`
``
242
+
``
243
`+
Text is highlighted via the 'hit' tag and the marked
`
``
244
`+
section is brought into view.
`
``
245
+
``
246
`+
The colors from the 'hit' tag aren't currently shown
`
``
247
`+
when the text is displayed. This is due to the 'sel'
`
``
248
`+
tag being added first, so the colors in the 'sel'
`
``
249
`+
config are seen instead of the colors for 'hit'.
`
``
250
`+
"""
`
189
251
`text = self.text
`
190
252
`text.mark_set("insert", first)
`
191
253
`text.tag_remove("sel", "1.0", "end")
`
`@@ -199,6 +261,7 @@ def show_hit(self, first, last):
`
199
261
`text.update_idletasks()
`
200
262
``
201
263
`def close(self, event=None):
`
``
264
`+
"Close the dialog and remove hit tags."
`
202
265
`SearchDialogBase.close(self, event)
`
203
266
`self.text.tag_remove("hit", "1.0", "end")
`
204
267
``