2323FONTUPDATEINTERVAL = 1000 # millisec
2424
2525
26- def getspacesfirstword (s , c = re .compile (r"^(\s*)(\w*)" )):
27- "Extract the beginning whitespace and first word from s."
28- return c .match (s ).groups ()
26+ def get_spaces_firstword (codeline , c = re .compile (r"^(\s*)(\w*)" )):
27+ "Extract the beginning whitespace and first word from codeline."
28+ return c .match (codeline ).groups ()
29+
30+
31+ def get_line_info (codeline ):
32+ """Return tuple of (line indent value, codeline, block start keyword).
33+
34+ The indentation of empty lines (or comment lines) is INFINITY.
35+ If the line does not start a block, the keyword value is False.
36+ """
37+ spaces , firstword = get_spaces_firstword (codeline )
38+ indent = len (spaces )
39+ if len (codeline ) == indent or codeline [indent ] == '#' :
40+ indent = INFINITY
41+ opener = firstword in BLOCKOPENERS and firstword
42+ return indent , codeline , opener
2943
3044
3145class CodeContext :
@@ -42,15 +56,15 @@ def __init__(self, editwin):
4256 self.textfont is the editor window font.
4357
4458 self.label displays the code context text above the editor text.
45- Initially None it is toggled via <<toggle-code-context>>.
59+ Initially None, it is toggled via <<toggle-code-context>>.
4660 self.topvisible is the number of the top text line displayed.
4761 self.info is a list of (line number, indent level, line text,
4862 block keyword) tuples for the block structure above topvisible.
49- s self.info[0] is initialized a 'dummy' line which
50- # starts the toplevel 'block' of the module.
63+ self.info[0] is initialized with a 'dummy' line which
64+ starts the toplevel 'block' of the module.
5165
5266 self.t1 and self.t2 are two timer events on the editor text widget to
53- monitor for changes to the context text or editor font.
67+ monitor for changes to the context text or editor font.
5468 """
5569 self .editwin = editwin
5670 self .text = editwin .text
@@ -94,45 +108,28 @@ def toggle_code_context_event(self, event=None):
94108 # All values are passed through getint(), since some
95109 # values may be pixel objects, which can't simply be added to ints.
96110 widgets = self .editwin .text , self .editwin .text_frame
97- # Calculate the required vertical padding
111+ # Calculate the required horizontal padding and border width.
98112 padx = 0
113+ border = 0
99114 for widget in widgets :
100115 padx += widget .tk .getint (widget .pack_info ()['padx' ])
101116 padx += widget .tk .getint (widget .cget ('padx' ))
102- # Calculate the required border width
103- border = 0
104- for widget in widgets :
105117 border += widget .tk .getint (widget .cget ('border' ))
106118 self .label = tkinter .Label (
107119 self .editwin .top , text = "\n " * (self .context_depth - 1 ),
108120 anchor = W , justify = LEFT , font = self .textfont ,
109121 bg = self .bgcolor , fg = self .fgcolor ,
110- width = 1 , #don 't request more than we get
122+ width = 1 , # Don 't request more than we get.
111123 padx = padx , border = border , relief = SUNKEN )
112124 # Pack the label widget before and above the text_frame widget,
113- # thus ensuring that it will appear directly above text_frame
125+ # thus ensuring that it will appear directly above text_frame.
114126 self .label .pack (side = TOP , fill = X , expand = False ,
115127 before = self .editwin .text_frame )
116128 else :
117129 self .label .destroy ()
118130 self .label = None
119131 return "break"
120132
121- def get_line_info (self , linenum ):
122- """Return tuple of (line indent value, text, and block start keyword).
123-
124- If the line does not start a block, the keyword value is False.
125- The indentation of empty lines (or comment lines) is INFINITY.
126- """
127- text = self .text .get ("%d.0" % linenum , "%d.end" % linenum )
128- spaces , firstword = getspacesfirstword (text )
129- opener = firstword in BLOCKOPENERS and firstword
130- if len (text ) == len (spaces ) or text [len (spaces )] == '#' :
131- indent = INFINITY
132- else :
133- indent = len (spaces )
134- return indent , text , opener
135-
136133 def get_context (self , new_topvisible , stopline = 1 , stopindent = 0 ):
137134 """Return a list of block line tuples and the 'last' indent.
138135
@@ -144,16 +141,17 @@ def get_context(self, new_topvisible, stopline=1, stopindent=0):
144141 """
145142 assert stopline > 0
146143 lines = []
147- # The indentation level we are currently in:
144+ # The indentation level we are currently in.
148145 lastindent = INFINITY
149146 # For a line to be interesting, it must begin with a block opening
150147 # keyword, and have less indentation than lastindent.
151148 for linenum in range (new_topvisible , stopline - 1 , - 1 ):
152- indent , text , opener = self .get_line_info (linenum )
149+ codeline = self .text .get (f'{ linenum } .0' , f'{ linenum } .end' )
150+ indent , text , opener = get_line_info (codeline )
153151 if indent < lastindent :
154152 lastindent = indent
155153 if opener in ("else" , "elif" ):
156- # We also show the if statement
154+ # Also show the if statement.
157155 lastindent += 1
158156 if opener and linenum < new_topvisible and indent >= stopindent :
159157 lines .append ((linenum , indent , text , opener ))
@@ -172,19 +170,19 @@ def update_code_context(self):
172170 the context label.
173171 """
174172 new_topvisible = int (self .text .index ("@0,0" ).split ('.' )[0 ])
175- if self .topvisible == new_topvisible : # haven 't scrolled
173+ if self .topvisible == new_topvisible : # Haven 't scrolled.
176174 return
177- if self .topvisible < new_topvisible : # scroll down
175+ if self .topvisible < new_topvisible : # Scroll down.
178176 lines , lastindent = self .get_context (new_topvisible ,
179177 self .topvisible )
180- # retain only context info applicable to the region
181- # between topvisible and new_topvisible:
178+ # Retain only context info applicable to the region
179+ # between topvisible and new_topvisible.
182180 while self .info [- 1 ][1 ] >= lastindent :
183181 del self .info [- 1 ]
184- else : # self.topvisible > new_topvisible: # scroll up
182+ else : # self.topvisible > new_topvisible: # Scroll up.
185183 stopindent = self .info [- 1 ][1 ] + 1
186- # retain only context info associated
187- # with lines above new_topvisible:
184+ # Retain only context info associated
185+ # with lines above new_topvisible.
188186 while self .info [- 1 ][0 ] >= new_topvisible :
189187 stopindent = self .info [- 1 ][1 ]
190188 del self .info [- 1 ]
@@ -193,9 +191,9 @@ def update_code_context(self):
193191 stopindent )
194192 self .info .extend (lines )
195193 self .topvisible = new_topvisible
196- # empty lines in context pane:
194+ # Empty lines in context pane.
197195 context_strings = ["" ] * max (0 , self .context_depth - len (self .info ))
198- # followed by the context hint lines:
196+ # Followed by the context hint lines.
199197 context_strings += [x [2 ] for x in self .info [- self .context_depth :]]
200198 self .label ["text" ] = '\n ' .join (context_strings )
201199
0 commit comments