Skip to content

[3.7] bpo-35689: IDLE: Add docstrings and unittests for colorizer.py (GH-11472) #11925

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Lib/idlelib/NEWS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ Released on 2019-??-??
======================================


bpo-35689: Add docstrings and tests for colorizer.

bpo-35833: Revise IDLE doc for control codes sent to Shell.
Add a code example block.

Expand Down
63 changes: 57 additions & 6 deletions Lib/idlelib/colorizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,21 @@ def color_config(text):


class ColorDelegator(Delegator):
"""Delegator for syntax highlighting (text coloring).

Class variables:
after_id: Identifier for scheduled after event.
allow_colorizing: Boolean toggle for applying colorizing.
colorizing: Boolean flag when colorizing is in process.
stop_colorizing: Boolean flag to end an active colorizing
process.
close_when_done: Widget to destroy after colorizing process
completes (doesn't seem to be used by IDLE).

Instance variables:
delegate: Delegator below this one in the stack, meaning the
one this one delegates to.
"""

def __init__(self):
Delegator.__init__(self)
Expand All @@ -61,6 +76,16 @@ def __init__(self):
self.LoadTagDefs()

def setdelegate(self, delegate):
"""Set the delegate for this instance.

A delegate is an instance of a Delegator class and each
delegate points to the next delegator in the stack. This
allows multiple delegators to be chained together for a
widget. The bottom delegate for a colorizer is a Text
widget.

If there is a delegate, also start the colorizing process.
"""
if self.delegate is not None:
self.unbind("<<toggle-auto-coloring>>")
Delegator.setdelegate(self, delegate)
Expand All @@ -69,17 +94,18 @@ def setdelegate(self, delegate):
self.bind("<<toggle-auto-coloring>>", self.toggle_colorize_event)
self.notify_range("1.0", "end")
else:
# No delegate - stop any colorizing
# No delegate - stop any colorizing.
self.stop_colorizing = True
self.allow_colorizing = False

def config_colors(self):
"Configure text widget tags with colors from tagdefs."
for tag, cnf in self.tagdefs.items():
if cnf:
self.tag_configure(tag, **cnf)
self.tag_configure(tag, **cnf)
self.tag_raise('sel')

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

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

def delete(self, index1, index2=None):
"Delete chars between indexes and mark for colorizing."
index1 = self.index(index1)
self.delegate.delete(index1, index2)
self.notify_range(index1)

after_id = None
allow_colorizing = True
stop_colorizing = False
colorizing = False

def notify_range(self, index1, index2=None):
"Mark text changes for processing and restart colorizing, if active."
self.tag_add("TODO", index1, index2)
if self.after_id:
if DEBUG: print("colorizing already scheduled")
Expand All @@ -121,8 +151,9 @@ def notify_range(self, index1, index2=None):
if self.allow_colorizing:
if DEBUG: print("schedule colorizing")
self.after_id = self.after(1, self.recolorize)
return

close_when_done = None # Window to be closed when done colorizing
close_when_done = None # Window to be closed when done colorizing.

def close(self, close_when_done=None):
if self.after_id:
Expand All @@ -138,7 +169,14 @@ def close(self, close_when_done=None):
else:
self.close_when_done = close_when_done

def toggle_colorize_event(self, event):
def toggle_colorize_event(self, event=None):
"""Toggle colorizing on and off.

When toggling off, if colorizing is scheduled or is in
process, it will be cancelled and/or stopped.

When toggling on, colorizing will be scheduled.
"""
if self.after_id:
after_id = self.after_id
self.after_id = None
Expand All @@ -156,6 +194,17 @@ def toggle_colorize_event(self, event):
return "break"

def recolorize(self):
"""Timer event (every 1ms) to colorize text.

Colorizing is only attempted when the text widget exists,
when colorizing is toggled on, and when the colorizing
process is not already running.

After colorizing is complete, some cleanup is done to
make sure that all the text has been colorized and to close
the window if the close event had been called while the
process was running.
"""
self.after_id = None
if not self.delegate:
if DEBUG: print("no delegate")
Expand Down Expand Up @@ -185,6 +234,7 @@ def recolorize(self):
top.destroy()

def recolorize_main(self):
"Evaluate text and apply colorizing tags."
next = "1.0"
while True:
item = self.tag_nextrange("TODO", next)
Expand Down Expand Up @@ -250,6 +300,7 @@ def recolorize_main(self):
return

def removecolors(self):
"Remove all colorizing tags."
for tag in self.tagdefs:
self.tag_remove(tag, "1.0", "end")

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