Kaydet (Commit) 0a135793 authored tarafından Kurt B. Kaiser's avatar Kurt B. Kaiser

Tweak CodeContext.py docstrings, comments, and names.

üst bee0d467
"""CodeContext - Display the block context of code at top of edit window """CodeContext - Extension to display the block context above the edit window
Once code has scrolled off the top of the screen, it can be difficult Once code has scrolled off the top of a window, it can be difficult to
to determine which block you are in. This extension implements a pane determine which block you are in. This extension implements a pane at the top
at the top of each IDLE edit window which provides block structure of each IDLE edit window which provides block structure hints. These hints are
hints. These hints are the lines which contain the block opening the lines which contain the block opening keywords, e.g. 'if', for the
keywords, e.g. 'if', for the enclosing block. The number of hint lines enclosing block. The number of hint lines is determined by the numlines
is determined by the numlines variable in the CodeContext section of variable in the CodeContext section of config-extensions.def. Lines which do
config-extensions.def. Lines which do not open blocks are not shown in not open blocks are not shown in the context hints pane.
the context hints pane.
""" """
import Tkinter import Tkinter
...@@ -21,13 +20,14 @@ BLOCKOPENERS = Set(["class", "def", "elif", "else", "except", "finally", "for", ...@@ -21,13 +20,14 @@ BLOCKOPENERS = Set(["class", "def", "elif", "else", "except", "finally", "for",
UPDATEINTERVAL = 100 # millisec UPDATEINTERVAL = 100 # millisec
FONTUPDATEINTERVAL = 1000 # millisec FONTUPDATEINTERVAL = 1000 # millisec
getspacesfirstword = lambda s, c=re.compile(r"^(\s*)(\w*)"): c.match(s).groups() getspacesfirstword =\
lambda s, c=re.compile(r"^(\s*)(\w*)"): c.match(s).groups()
class CodeContext: class CodeContext:
menudefs = [('options', [('!Code Conte_xt', '<<toggle-code-context>>')])] menudefs = [('options', [('!Code Conte_xt', '<<toggle-code-context>>')])]
numlines = idleConf.GetOption("extensions", "CodeContext", context_depth = idleConf.GetOption("extensions", "CodeContext",
"numlines", type="int", default=3) "numlines", type="int", default=3)
bgcolor = idleConf.GetOption("extensions", "CodeContext", bgcolor = idleConf.GetOption("extensions", "CodeContext",
"bgcolor", type="str", default="LightGray") "bgcolor", type="str", default="LightGray")
fgcolor = idleConf.GetOption("extensions", "CodeContext", fgcolor = idleConf.GetOption("extensions", "CodeContext",
...@@ -37,13 +37,13 @@ class CodeContext: ...@@ -37,13 +37,13 @@ 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
# self.info holds information about the context lines of line number # self.info is a list of (line number, indent level, line text, block
# self.lastfirstline. The information is a tuple of the line's # keyword) tuples providing the block structure associated with
# indentation, the line's text and the keyword at the beginning of the # self.topvisible (the linenumber of the line displayed at the top of
# line, as returned by get_line_info. At the beginning of the list # the edit window). self.info[0] is initialized as a 'dummy' line which
# there's a dummy line, which starts the "block" of the whole document. # starts the toplevel 'block' of the module.
self.info = [(0, -1, "", False)] self.info = [(0, -1, "", False)]
self.lastfirstline = 1 self.topvisible = 1
visible = idleConf.GetOption("extensions", "CodeContext", visible = idleConf.GetOption("extensions", "CodeContext",
"visible", type="bool", default=False) "visible", type="bool", default=False)
if visible: if visible:
...@@ -56,7 +56,7 @@ class CodeContext: ...@@ -56,7 +56,7 @@ class CodeContext:
def toggle_code_context_event(self, event=None): def toggle_code_context_event(self, event=None):
if not self.label: if not self.label:
self.label = Tkinter.Label(self.editwin.top, self.label = Tkinter.Label(self.editwin.top,
text="\n" * (self.numlines - 1), text="\n" * (self.context_depth - 1),
anchor="w", justify="left", anchor="w", justify="left",
font=self.textfont, font=self.textfont,
bg=self.bgcolor, fg=self.fgcolor, bg=self.bgcolor, fg=self.fgcolor,
...@@ -77,6 +77,7 @@ class CodeContext: ...@@ -77,6 +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.
""" """
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)
...@@ -87,64 +88,69 @@ class CodeContext: ...@@ -87,64 +88,69 @@ class CodeContext:
indent = len(spaces) indent = len(spaces)
return indent, text, opener return indent, text, opener
def interesting_lines(self, firstline, stopline=1, stopindent=0): def get_context(self, new_topvisible, stopline=1, stopindent=0):
""" """Get context lines, starting at new_topvisible and working backwards.
Find the context lines, starting at firstline.
Will not return lines whose index is smaller than stopline or whose Stop when stopline or stopindent is reached. Return a tuple of context
indentation is smaller than stopindent. data and the indent level at the top of the region inspected.
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.
""" """
assert stopline > 0
lines = [] 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, stopline-1, -1): for linenum in xrange(new_topvisible, stopline-1, -1):
indent, text, opener = self.get_line_info(line_index) indent, text, opener = self.get_line_info(linenum)
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 and indent >= stopindent: if opener and linenum < new_topvisible and indent >= stopindent:
lines.append((line_index, indent, text, opener)) lines.append((linenum, indent, text, opener))
if lastindent <= stopindent: if lastindent <= stopindent:
break break
lines.reverse() lines.reverse()
return lines, lastindent return lines, lastindent
def update_label(self): def update_code_context(self):
"""Update the CodeContext label, if needed. """Update context information and lines visible in the context pane.
""" """
firstline = int(self.text.index("@0,0").split('.')[0]) new_topvisible = int(self.text.index("@0,0").split('.')[0])
if self.lastfirstline == firstline: if self.topvisible == new_topvisible: # haven't scrolled
return return
if self.lastfirstline < firstline: if self.topvisible < new_topvisible: # scroll down
lines, lastindent = self.interesting_lines(firstline, lines, lastindent = self.get_context(new_topvisible,
self.lastfirstline) self.topvisible)
# retain only context info applicable to the region
# between topvisible and new_topvisible:
while self.info[-1][1] >= lastindent: while self.info[-1][1] >= lastindent:
del self.info[-1] del self.info[-1]
self.info.extend(lines) elif self.topvisible > new_topvisible: # scroll up
else:
stopindent = self.info[-1][1] + 1 stopindent = self.info[-1][1] + 1
while self.info[-1][0] >= firstline: # retain only context info associated
# with lines above new_topvisible:
while self.info[-1][0] >= new_topvisible:
stopindent = self.info[-1][1] stopindent = self.info[-1][1]
del self.info[-1] del self.info[-1]
lines, lastindent = self.interesting_lines( lines, lastindent = self.get_context(new_topvisible,
firstline, self.info[-1][0]+1, stopindent) self.info[-1][0]+1,
self.info.extend(lines) stopindent)
self.lastfirstline = firstline self.info.extend(lines)
lines = [""] * max(0, self.numlines - len(self.info)) + \ self.topvisible = new_topvisible
[x[2] for x in self.info[-self.numlines:]]
self.label["text"] = '\n'.join(lines) # empty lines in context pane:
context_strings = [""] * max(0, self.context_depth - len(self.info))
# followed by the context hint lines:
context_strings += [x[2] for x in self.info[-self.context_depth:]]
self.label["text"] = '\n'.join(context_strings)
def timer_event(self): def timer_event(self):
if self.label: if self.label:
self.update_label() self.update_code_context()
self.text.after(UPDATEINTERVAL, self.timer_event) self.text.after(UPDATEINTERVAL, self.timer_event)
def font_timer_event(self): def font_timer_event(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment