Increased performance in CodeContext extension Patch 936169 Noam Raphael

This commit is contained in:
Kurt B. Kaiser 2005-10-02 23:36:46 +00:00
parent 40d3781416
commit 74910225df
2 changed files with 49 additions and 31 deletions

View file

@ -14,10 +14,10 @@ import Tkinter
from configHandler import idleConf from configHandler import idleConf
from sets import Set from sets import Set
import re import re
from sys import maxint as INFINITY
BLOCKOPENERS = Set(["class", "def", "elif", "else", "except", "finally", "for", BLOCKOPENERS = Set(["class", "def", "elif", "else", "except", "finally", "for",
"if", "try", "while"]) "if", "try", "while"])
INFINITY = 1 << 30
UPDATEINTERVAL = 100 # millisec UPDATEINTERVAL = 100 # millisec
FONTUPDATEINTERVAL = 1000 # millisec FONTUPDATEINTERVAL = 1000 # millisec
@ -37,8 +37,12 @@ class CodeContext:
self.text = editwin.text self.text = editwin.text
self.textfont = self.text["font"] self.textfont = self.text["font"]
self.label = None self.label = None
# Dummy line, which starts the "block" of the whole document: # self.info holds information about the context lines of line number
self.info = list(self.interesting_lines(1)) # self.lastfirstline. The information is a tuple of the line's
# indentation, the line's text and the keyword at the beginning of the
# line, as returned by get_line_info. At the beginning of the list
# there's a dummy line, which starts the "block" of the whole document.
self.info = [(0, -1, "", False)]
self.lastfirstline = 1 self.lastfirstline = 1
visible = idleConf.GetOption("extensions", "CodeContext", visible = idleConf.GetOption("extensions", "CodeContext",
"visible", type="bool", default=False) "visible", type="bool", default=False)
@ -73,14 +77,7 @@ class CodeContext:
If the line does not start a block, the keyword value is False. If the line does not start a block, the keyword value is False.
The indentation of empty lines (or comment lines) is INFINITY. The indentation of empty lines (or comment lines) is INFINITY.
There is a dummy block start, with indentation -1 and text "".
Return the indent level, text (including leading whitespace),
and the block opening keyword.
""" """
if linenum == 0:
return -1, "", True
text = self.text.get("%d.0" % linenum, "%d.end" % linenum) text = self.text.get("%d.0" % linenum, "%d.end" % linenum)
spaces, firstword = getspacesfirstword(text) spaces, firstword = getspacesfirstword(text)
opener = firstword in BLOCKOPENERS and firstword opener = firstword in BLOCKOPENERS and firstword
@ -90,40 +87,59 @@ class CodeContext:
indent = len(spaces) indent = len(spaces)
return indent, text, opener return indent, text, opener
def interesting_lines(self, firstline): def interesting_lines(self, firstline, stopline=1, stopindent=0):
"""Generator which yields context lines, starting at firstline.""" """
Find the context lines, starting at firstline.
Will not return lines whose index is smaller than stopline or whose
indentation is smaller than stopindent.
stopline should always be >= 1, so the dummy block start will never
be returned (This function doesn't know what to do about it.)
Returns a list with the context lines, starting from the first (top),
and a number which all context lines above the inspected region should
have a smaller indentation than it.
"""
lines = []
# The indentation level we are currently in: # The indentation level we are currently in:
lastindent = INFINITY lastindent = INFINITY
# For a line to be interesting, it must begin with a block opening # For a line to be interesting, it must begin with a block opening
# keyword, and have less indentation than lastindent. # keyword, and have less indentation than lastindent.
for line_index in xrange(firstline, -1, -1): for line_index in xrange(firstline, stopline-1, -1):
indent, text, opener = self.get_line_info(line_index) indent, text, opener = self.get_line_info(line_index)
if indent < lastindent: if indent < lastindent:
lastindent = indent lastindent = indent
if opener in ("else", "elif"): if opener in ("else", "elif"):
# We also show the if statement # We also show the if statement
lastindent += 1 lastindent += 1
if opener and line_index < firstline: if opener and line_index < firstline and indent >= stopindent:
yield line_index, text lines.append((line_index, indent, text, opener))
if lastindent <= stopindent:
break
lines.reverse()
return lines, lastindent
def update_label(self): def update_label(self):
"""Update the CodeContext label, if needed.
"""
firstline = int(self.text.index("@0,0").split('.')[0]) firstline = int(self.text.index("@0,0").split('.')[0])
if self.lastfirstline == firstline: if self.lastfirstline == firstline:
return return
self.lastfirstline = firstline if self.lastfirstline < firstline:
tmpstack = [] lines, lastindent = self.interesting_lines(firstline,
for line_index, text in self.interesting_lines(firstline): self.lastfirstline)
# Remove irrelevant self.info items, and when we reach a relevant while self.info[-1][1] >= lastindent:
# item (which must happen because of the dummy element), break.
while self.info[-1][0] > line_index:
del self.info[-1] del self.info[-1]
if self.info[-1][0] == line_index: self.info.extend(lines)
break else:
tmpstack.append((line_index, text)) stopindent = self.info[-1][1] + 1
while tmpstack: while self.info[-1][0] >= firstline:
self.info.append(tmpstack.pop()) stopindent = self.info[-1][1]
del self.info[-1]
lines, lastindent = self.interesting_lines(
firstline, self.info[-1][0]+1, stopindent)
self.info.extend(lines)
self.lastfirstline = firstline
lines = [""] * max(0, self.numlines - len(self.info)) + \ lines = [""] * max(0, self.numlines - len(self.info)) + \
[x[1] for x in self.info[-self.numlines:]] [x[2] for x in self.info[-self.numlines:]]
self.label["text"] = '\n'.join(lines) self.label["text"] = '\n'.join(lines)
def timer_event(self): def timer_event(self):

View file

@ -3,6 +3,8 @@ What's New in IDLE 1.2a0?
*Release date: XX-XXX-2005* *Release date: XX-XXX-2005*
- Increased performance in CodeContext extension Patch 936169 Noam Raphael
- Mac line endings were incorrect when pasting code from some browsers - Mac line endings were incorrect when pasting code from some browsers
when using X11 and the Fink distribution. Python Bug 1263656. when using X11 and the Fink distribution. Python Bug 1263656.
@ -148,12 +150,12 @@ What's New in IDLE 1.1a1?
- If nulls somehow got into the strings in recent-files.lst - If nulls somehow got into the strings in recent-files.lst
EditorWindow.update_recent_files_list() was failing. Python Bug 931336. EditorWindow.update_recent_files_list() was failing. Python Bug 931336.
- If the normal background is changed via Configure/Highlighting, it will update - If the normal background is changed via Configure/Highlighting, it will
immediately, thanks to the previously mentioned patch by Nigel Rowe. update immediately, thanks to the previously mentioned patch by Nigel Rowe.
- Add a highlight theme for builtin keywords. Python Patch 805830 Nigel Rowe - Add a highlight theme for builtin keywords. Python Patch 805830 Nigel Rowe
This also fixed IDLEfork bug [ 693418 ] Normal text background color not refreshed This also fixed IDLEfork bug [ 693418 ] Normal text background color not
and Python bug [897872 ] Unknown color name on HP-UX refreshed and Python bug [897872 ] Unknown color name on HP-UX
- rpc.py:SocketIO - Large modules were generating large pickles when downloaded - rpc.py:SocketIO - Large modules were generating large pickles when downloaded
to the execution server. The return of the OK response from the subprocess to the execution server. The return of the OK response from the subprocess