Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ShExBy/shex_roo.../lib64/python2..../idlelib
File: CodeContext.py
"""CodeContext - Extension to display the block context above the edit window
[0] Fix | Delete
[1] Fix | Delete
Once code has scrolled off the top of a window, it can be difficult to
[2] Fix | Delete
determine which block you are in. This extension implements a pane at the top
[3] Fix | Delete
of each IDLE edit window which provides block structure hints. These hints are
[4] Fix | Delete
the lines which contain the block opening keywords, e.g. 'if', for the
[5] Fix | Delete
enclosing block. The number of hint lines is determined by the numlines
[6] Fix | Delete
variable in the CodeContext section of config-extensions.def. Lines which do
[7] Fix | Delete
not open blocks are not shown in the context hints pane.
[8] Fix | Delete
[9] Fix | Delete
"""
[10] Fix | Delete
import Tkinter
[11] Fix | Delete
from Tkconstants import TOP, LEFT, X, W, SUNKEN
[12] Fix | Delete
import re
[13] Fix | Delete
from sys import maxint as INFINITY
[14] Fix | Delete
from idlelib.configHandler import idleConf
[15] Fix | Delete
[16] Fix | Delete
BLOCKOPENERS = {"class", "def", "elif", "else", "except", "finally", "for",
[17] Fix | Delete
"if", "try", "while", "with"}
[18] Fix | Delete
UPDATEINTERVAL = 100 # millisec
[19] Fix | Delete
FONTUPDATEINTERVAL = 1000 # millisec
[20] Fix | Delete
[21] Fix | Delete
getspacesfirstword =\
[22] Fix | Delete
lambda s, c=re.compile(r"^(\s*)(\w*)"): c.match(s).groups()
[23] Fix | Delete
[24] Fix | Delete
class CodeContext:
[25] Fix | Delete
menudefs = [('options', [('!Code Conte_xt', '<<toggle-code-context>>')])]
[26] Fix | Delete
context_depth = idleConf.GetOption("extensions", "CodeContext",
[27] Fix | Delete
"numlines", type="int", default=3)
[28] Fix | Delete
bgcolor = idleConf.GetOption("extensions", "CodeContext",
[29] Fix | Delete
"bgcolor", type="str", default="LightGray")
[30] Fix | Delete
fgcolor = idleConf.GetOption("extensions", "CodeContext",
[31] Fix | Delete
"fgcolor", type="str", default="Black")
[32] Fix | Delete
def __init__(self, editwin):
[33] Fix | Delete
self.editwin = editwin
[34] Fix | Delete
self.text = editwin.text
[35] Fix | Delete
self.textfont = self.text["font"]
[36] Fix | Delete
self.label = None
[37] Fix | Delete
# self.info is a list of (line number, indent level, line text, block
[38] Fix | Delete
# keyword) tuples providing the block structure associated with
[39] Fix | Delete
# self.topvisible (the linenumber of the line displayed at the top of
[40] Fix | Delete
# the edit window). self.info[0] is initialized as a 'dummy' line which
[41] Fix | Delete
# starts the toplevel 'block' of the module.
[42] Fix | Delete
self.info = [(0, -1, "", False)]
[43] Fix | Delete
self.topvisible = 1
[44] Fix | Delete
visible = idleConf.GetOption("extensions", "CodeContext",
[45] Fix | Delete
"visible", type="bool", default=False)
[46] Fix | Delete
if visible:
[47] Fix | Delete
self.toggle_code_context_event()
[48] Fix | Delete
self.editwin.setvar('<<toggle-code-context>>', True)
[49] Fix | Delete
# Start two update cycles, one for context lines, one for font changes.
[50] Fix | Delete
self.text.after(UPDATEINTERVAL, self.timer_event)
[51] Fix | Delete
self.text.after(FONTUPDATEINTERVAL, self.font_timer_event)
[52] Fix | Delete
[53] Fix | Delete
def toggle_code_context_event(self, event=None):
[54] Fix | Delete
if not self.label:
[55] Fix | Delete
# Calculate the border width and horizontal padding required to
[56] Fix | Delete
# align the context with the text in the main Text widget.
[57] Fix | Delete
#
[58] Fix | Delete
# All values are passed through int(str(<value>)), since some
[59] Fix | Delete
# values may be pixel objects, which can't simply be added to ints.
[60] Fix | Delete
widgets = self.editwin.text, self.editwin.text_frame
[61] Fix | Delete
# Calculate the required vertical padding
[62] Fix | Delete
padx = 0
[63] Fix | Delete
for widget in widgets:
[64] Fix | Delete
padx += int(str( widget.pack_info()['padx'] ))
[65] Fix | Delete
padx += int(str( widget.cget('padx') ))
[66] Fix | Delete
# Calculate the required border width
[67] Fix | Delete
border = 0
[68] Fix | Delete
for widget in widgets:
[69] Fix | Delete
border += int(str( widget.cget('border') ))
[70] Fix | Delete
self.label = Tkinter.Label(self.editwin.top,
[71] Fix | Delete
text="\n" * (self.context_depth - 1),
[72] Fix | Delete
anchor=W, justify=LEFT,
[73] Fix | Delete
font=self.textfont,
[74] Fix | Delete
bg=self.bgcolor, fg=self.fgcolor,
[75] Fix | Delete
width=1, #don't request more than we get
[76] Fix | Delete
padx=padx, border=border,
[77] Fix | Delete
relief=SUNKEN)
[78] Fix | Delete
# Pack the label widget before and above the text_frame widget,
[79] Fix | Delete
# thus ensuring that it will appear directly above text_frame
[80] Fix | Delete
self.label.pack(side=TOP, fill=X, expand=False,
[81] Fix | Delete
before=self.editwin.text_frame)
[82] Fix | Delete
else:
[83] Fix | Delete
self.label.destroy()
[84] Fix | Delete
self.label = None
[85] Fix | Delete
idleConf.SetOption("extensions", "CodeContext", "visible",
[86] Fix | Delete
str(self.label is not None))
[87] Fix | Delete
idleConf.SaveUserCfgFiles()
[88] Fix | Delete
[89] Fix | Delete
def get_line_info(self, linenum):
[90] Fix | Delete
"""Get the line indent value, text, and any block start keyword
[91] Fix | Delete
[92] Fix | Delete
If the line does not start a block, the keyword value is False.
[93] Fix | Delete
The indentation of empty lines (or comment lines) is INFINITY.
[94] Fix | Delete
[95] Fix | Delete
"""
[96] Fix | Delete
text = self.text.get("%d.0" % linenum, "%d.end" % linenum)
[97] Fix | Delete
spaces, firstword = getspacesfirstword(text)
[98] Fix | Delete
opener = firstword in BLOCKOPENERS and firstword
[99] Fix | Delete
if len(text) == len(spaces) or text[len(spaces)] == '#':
[100] Fix | Delete
indent = INFINITY
[101] Fix | Delete
else:
[102] Fix | Delete
indent = len(spaces)
[103] Fix | Delete
return indent, text, opener
[104] Fix | Delete
[105] Fix | Delete
def get_context(self, new_topvisible, stopline=1, stopindent=0):
[106] Fix | Delete
"""Get context lines, starting at new_topvisible and working backwards.
[107] Fix | Delete
[108] Fix | Delete
Stop when stopline or stopindent is reached. Return a tuple of context
[109] Fix | Delete
data and the indent level at the top of the region inspected.
[110] Fix | Delete
[111] Fix | Delete
"""
[112] Fix | Delete
assert stopline > 0
[113] Fix | Delete
lines = []
[114] Fix | Delete
# The indentation level we are currently in:
[115] Fix | Delete
lastindent = INFINITY
[116] Fix | Delete
# For a line to be interesting, it must begin with a block opening
[117] Fix | Delete
# keyword, and have less indentation than lastindent.
[118] Fix | Delete
for linenum in xrange(new_topvisible, stopline-1, -1):
[119] Fix | Delete
indent, text, opener = self.get_line_info(linenum)
[120] Fix | Delete
if indent < lastindent:
[121] Fix | Delete
lastindent = indent
[122] Fix | Delete
if opener in ("else", "elif"):
[123] Fix | Delete
# We also show the if statement
[124] Fix | Delete
lastindent += 1
[125] Fix | Delete
if opener and linenum < new_topvisible and indent >= stopindent:
[126] Fix | Delete
lines.append((linenum, indent, text, opener))
[127] Fix | Delete
if lastindent <= stopindent:
[128] Fix | Delete
break
[129] Fix | Delete
lines.reverse()
[130] Fix | Delete
return lines, lastindent
[131] Fix | Delete
[132] Fix | Delete
def update_code_context(self):
[133] Fix | Delete
"""Update context information and lines visible in the context pane.
[134] Fix | Delete
[135] Fix | Delete
"""
[136] Fix | Delete
new_topvisible = int(self.text.index("@0,0").split('.')[0])
[137] Fix | Delete
if self.topvisible == new_topvisible: # haven't scrolled
[138] Fix | Delete
return
[139] Fix | Delete
if self.topvisible < new_topvisible: # scroll down
[140] Fix | Delete
lines, lastindent = self.get_context(new_topvisible,
[141] Fix | Delete
self.topvisible)
[142] Fix | Delete
# retain only context info applicable to the region
[143] Fix | Delete
# between topvisible and new_topvisible:
[144] Fix | Delete
while self.info[-1][1] >= lastindent:
[145] Fix | Delete
del self.info[-1]
[146] Fix | Delete
elif self.topvisible > new_topvisible: # scroll up
[147] Fix | Delete
stopindent = self.info[-1][1] + 1
[148] Fix | Delete
# retain only context info associated
[149] Fix | Delete
# with lines above new_topvisible:
[150] Fix | Delete
while self.info[-1][0] >= new_topvisible:
[151] Fix | Delete
stopindent = self.info[-1][1]
[152] Fix | Delete
del self.info[-1]
[153] Fix | Delete
lines, lastindent = self.get_context(new_topvisible,
[154] Fix | Delete
self.info[-1][0]+1,
[155] Fix | Delete
stopindent)
[156] Fix | Delete
self.info.extend(lines)
[157] Fix | Delete
self.topvisible = new_topvisible
[158] Fix | Delete
# empty lines in context pane:
[159] Fix | Delete
context_strings = [""] * max(0, self.context_depth - len(self.info))
[160] Fix | Delete
# followed by the context hint lines:
[161] Fix | Delete
context_strings += [x[2] for x in self.info[-self.context_depth:]]
[162] Fix | Delete
self.label["text"] = '\n'.join(context_strings)
[163] Fix | Delete
[164] Fix | Delete
def timer_event(self):
[165] Fix | Delete
if self.label:
[166] Fix | Delete
self.update_code_context()
[167] Fix | Delete
self.text.after(UPDATEINTERVAL, self.timer_event)
[168] Fix | Delete
[169] Fix | Delete
def font_timer_event(self):
[170] Fix | Delete
newtextfont = self.text["font"]
[171] Fix | Delete
if self.label and newtextfont != self.textfont:
[172] Fix | Delete
self.textfont = newtextfont
[173] Fix | Delete
self.label["font"] = self.textfont
[174] Fix | Delete
self.text.after(FONTUPDATEINTERVAL, self.font_timer_event)
[175] Fix | Delete
[176] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function