Skip to content

Commit 99e9c36

Browse files
bpo-35689: IDLE: Add docstrings and unittests for colorizer.py (GH-11472)
(cherry picked from commit ee0f927) Co-authored-by: Cheryl Sabella <[email protected]>
1 parent 3129432 commit 99e9c36

File tree

4 files changed

+408
-16
lines changed

4 files changed

+408
-16
lines changed

Lib/idlelib/NEWS.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ Released on 2019-??-??
33
======================================
44

55

6+
bpo-35689: Add docstrings and tests for colorizer.
7+
68
bpo-35833: Revise IDLE doc for control codes sent to Shell.
79
Add a code example block.
810

Lib/idlelib/colorizer.py

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,21 @@ def color_config(text):
5353

5454

5555
class ColorDelegator(Delegator):
56+
"""Delegator for syntax highlighting (text coloring).
57+
58+
Class variables:
59+
after_id: Identifier for scheduled after event.
60+
allow_colorizing: Boolean toggle for applying colorizing.
61+
colorizing: Boolean flag when colorizing is in process.
62+
stop_colorizing: Boolean flag to end an active colorizing
63+
process.
64+
close_when_done: Widget to destroy after colorizing process
65+
completes (doesn't seem to be used by IDLE).
66+
67+
Instance variables:
68+
delegate: Delegator below this one in the stack, meaning the
69+
one this one delegates to.
70+
"""
5671

5772
def __init__(self):
5873
Delegator.__init__(self)
@@ -61,6 +76,16 @@ def __init__(self):
6176
self.LoadTagDefs()
6277

6378
def setdelegate(self, delegate):
79+
"""Set the delegate for this instance.
80+
81+
A delegate is an instance of a Delegator class and each
82+
delegate points to the next delegator in the stack. This
83+
allows multiple delegators to be chained together for a
84+
widget. The bottom delegate for a colorizer is a Text
85+
widget.
86+
87+
If there is a delegate, also start the colorizing process.
88+
"""
6489
if self.delegate is not None:
6590
self.unbind("<<toggle-auto-coloring>>")
6691
Delegator.setdelegate(self, delegate)
@@ -69,17 +94,18 @@ def setdelegate(self, delegate):
6994
self.bind("<<toggle-auto-coloring>>", self.toggle_colorize_event)
7095
self.notify_range("1.0", "end")
7196
else:
72-
# No delegate - stop any colorizing
97+
# No delegate - stop any colorizing.
7398
self.stop_colorizing = True
7499
self.allow_colorizing = False
75100

76101
def config_colors(self):
102+
"Configure text widget tags with colors from tagdefs."
77103
for tag, cnf in self.tagdefs.items():
78-
if cnf:
79-
self.tag_configure(tag, **cnf)
104+
self.tag_configure(tag, **cnf)
80105
self.tag_raise('sel')
81106

82107
def LoadTagDefs(self):
108+
"Create dictionary of tag names to text colors."
83109
theme = idleConf.CurrentTheme()
84110
self.tagdefs = {
85111
"COMMENT": idleConf.GetHighlight(theme, "comment"),
@@ -97,20 +123,24 @@ def LoadTagDefs(self):
97123
if DEBUG: print('tagdefs',self.tagdefs)
98124

99125
def insert(self, index, chars, tags=None):
126+
"Insert chars into widget at index and mark for colorizing."
100127
index = self.index(index)
101128
self.delegate.insert(index, chars, tags)
102129
self.notify_range(index, index + "+%dc" % len(chars))
103130

104131
def delete(self, index1, index2=None):
132+
"Delete chars between indexes and mark for colorizing."
105133
index1 = self.index(index1)
106134
self.delegate.delete(index1, index2)
107135
self.notify_range(index1)
108136

109137
after_id = None
110138
allow_colorizing = True
139+
stop_colorizing = False
111140
colorizing = False
112141

113142
def notify_range(self, index1, index2=None):
143+
"Mark text changes for processing and restart colorizing, if active."
114144
self.tag_add("TODO", index1, index2)
115145
if self.after_id:
116146
if DEBUG: print("colorizing already scheduled")
@@ -121,8 +151,9 @@ def notify_range(self, index1, index2=None):
121151
if self.allow_colorizing:
122152
if DEBUG: print("schedule colorizing")
123153
self.after_id = self.after(1, self.recolorize)
154+
return
124155

125-
close_when_done = None # Window to be closed when done colorizing
156+
close_when_done = None # Window to be closed when done colorizing.
126157

127158
def close(self, close_when_done=None):
128159
if self.after_id:
@@ -138,7 +169,14 @@ def close(self, close_when_done=None):
138169
else:
139170
self.close_when_done = close_when_done
140171

141-
def toggle_colorize_event(self, event):
172+
def toggle_colorize_event(self, event=None):
173+
"""Toggle colorizing on and off.
174+
175+
When toggling off, if colorizing is scheduled or is in
176+
process, it will be cancelled and/or stopped.
177+
178+
When toggling on, colorizing will be scheduled.
179+
"""
142180
if self.after_id:
143181
after_id = self.after_id
144182
self.after_id = None
@@ -156,6 +194,17 @@ def toggle_colorize_event(self, event):
156194
return "break"
157195

158196
def recolorize(self):
197+
"""Timer event (every 1ms) to colorize text.
198+
199+
Colorizing is only attempted when the text widget exists,
200+
when colorizing is toggled on, and when the colorizing
201+
process is not already running.
202+
203+
After colorizing is complete, some cleanup is done to
204+
make sure that all the text has been colorized and to close
205+
the window if the close event had been called while the
206+
process was running.
207+
"""
159208
self.after_id = None
160209
if not self.delegate:
161210
if DEBUG: print("no delegate")
@@ -185,6 +234,7 @@ def recolorize(self):
185234
top.destroy()
186235

187236
def recolorize_main(self):
237+
"Evaluate text and apply colorizing tags."
188238
next = "1.0"
189239
while True:
190240
item = self.tag_nextrange("TODO", next)
@@ -250,6 +300,7 @@ def recolorize_main(self):
250300
return
251301

252302
def removecolors(self):
303+
"Remove all colorizing tags."
253304
for tag in self.tagdefs:
254305
self.tag_remove(tag, "1.0", "end")
255306

@@ -273,7 +324,7 @@ def _color_delegator(parent): # htest #
273324
"'x', '''x''', \"x\", \"\"\"x\"\"\"\n"
274325
"r'x', u'x', R'x', U'x', f'x', F'x'\n"
275326
"fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x'\n"
276-
"b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x'.rB'x',Rb'x',RB'x'\n"
327+
"b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x', rB'x',Rb'x',RB'x'\n"
277328
"# Invalid combinations of legal characters should be half colored.\n"
278329
"ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'\n"
279330
)

0 commit comments

Comments
 (0)