@@ -100,48 +100,47 @@ class HighlightMap:
100100
101101 BLOCK_SIZE = 50
102102
103- def __init__ (self , text_area_widget : widgets . TextArea ):
104- self .text_area_widget : widgets . TextArea = text_area_widget
105- self . uncovered_lines : dict [ int , range ] = {}
103+ def __init__ (self , text_area : TextArea ):
104+ self .text_area : TextArea = text_area
105+ """The text area associated with this highlight map."""
106106
107- # A mapping from line index to a list of Highlight instances.
108- self ._highlights : LineToHighlightsMap = defaultdict (list )
109- self .reset ()
107+ self ._highlighted_blocks : set [int ] = set ()
108+ """The set of blocks that have been highlighted. Each block covers BLOCK_SIZE
109+ lines.
110+ """
111+
112+ self ._highlights : dict [int , list [Highlight ]] = defaultdict (list )
113+ """A mapping from line index to a list of Highlight instances."""
110114
111115 def reset (self ) -> None :
112116 """Reset so that future lookups rebuild the highlight map."""
113117 self ._highlights .clear ()
114- line_count = self .document .line_count
115- uncovered_lines = self .uncovered_lines
116- uncovered_lines .clear ()
117- i = end_range = 0
118- for i in range (0 , line_count , self .BLOCK_SIZE ):
119- end_range = min (i + self .BLOCK_SIZE , line_count )
120- line_range = range (i , end_range )
121- uncovered_lines .update ({j : line_range for j in line_range })
122- if end_range < line_count :
123- line_range = range (i , line_count )
124- uncovered_lines .update ({j : line_range for j in line_range })
118+ self ._highlighted_blocks .clear ()
125119
126120 @property
127121 def document (self ) -> DocumentBase :
128122 """The text document being highlighted."""
129- return self .text_area_widget .document
123+ return self .text_area .document
124+
125+ def __getitem__ (self , index : int ) -> list [Highlight ]:
126+ block_index = index // self .BLOCK_SIZE
127+ if block_index not in self ._highlighted_blocks :
128+ self ._highlighted_blocks .add (block_index )
129+ self ._build_part_of_highlight_map (block_index * self .BLOCK_SIZE )
130+ return self ._highlights [index ]
130131
131- def __getitem__ (self , idx : int ) -> list [text_area .Highlight ]:
132- if idx in self .uncovered_lines :
133- self ._build_part_of_highlight_map (self .uncovered_lines [idx ])
134- return self ._highlights [idx ]
132+ def _build_part_of_highlight_map (self , start_index : int ) -> None :
133+ """Build part of the highlight map.
135134
136- def _build_part_of_highlight_map (self , line_range : range ) -> None :
137- """Build part of the highlight map."""
135+ Args:
136+ start_index: The start of the block of line for which to build the map.
137+ """
138138 highlights = self ._highlights
139- for line_index in line_range :
140- self .uncovered_lines .pop (line_index )
141- start_point = (line_range [0 ], 0 )
142- end_point = (line_range [- 1 ] + 1 , 0 )
139+ start_point = (start_index , 0 )
140+ end_index = min (self .document .line_count , start_index + self .BLOCK_SIZE )
141+ end_point = (end_index , 0 )
143142 captures = self .document .query_syntax_tree (
144- self .text_area_widget ._highlight_query ,
143+ self .text_area ._highlight_query ,
145144 start_point = start_point ,
146145 end_point = end_point ,
147146 )
@@ -159,8 +158,9 @@ def _build_part_of_highlight_map(self, line_range: range) -> None:
159158 )
160159
161160 # Add the middle lines - entire row of this node is highlighted
161+ middle_highlight = (0 , None , highlight_name )
162162 for node_row in range (node_start_row + 1 , node_end_row ):
163- highlights [node_row ].append (( 0 , None , highlight_name ) )
163+ highlights [node_row ].append (middle_highlight )
164164
165165 # Add the last line of the node range
166166 highlights [node_end_row ].append (
@@ -176,16 +176,16 @@ def _build_part_of_highlight_map(self, line_range: range) -> None:
176176 # to be sorted in ascending order of ``a``. When two highlights have the same
177177 # value of ``a`` then the one with the larger a--b range comes first, with ``None``
178178 # being considered larger than any number.
179- def sort_key (hl ) -> tuple [int , int , int ]:
180- a , b , _ = hl
181- max_range_ind = 1
179+ def sort_key (highlight : Highlight ) -> tuple [int , int , int ]:
180+ a , b , _ = highlight
181+ max_range_index = 1
182182 if b is None :
183- max_range_ind = 0
183+ max_range_index = 0
184184 b = a
185- return a , max_range_ind , a - b
185+ return a , max_range_index , a - b
186186
187- for line_index in line_range :
188- line_highlights = highlights .get (line_index , []).sort (key = sort_key )
187+ for line_index in range ( start_index , end_index ) :
188+ highlights .get (line_index , []).sort (key = sort_key )
189189
190190
191191@dataclass
@@ -707,7 +707,7 @@ def check_consume_key(self, key: str, character: str | None = None) -> bool:
707707 # Otherwise we capture all printable keys
708708 return character is not None and character .isprintable ()
709709
710- def _build_highlight_map (self ) -> None :
710+ def _reset_highlights (self ) -> None :
711711 """Reset the lazily evaluated highlight map."""
712712
713713 if self ._highlight_query :
@@ -1031,7 +1031,7 @@ def _set_document(self, text: str, language: str | None) -> None:
10311031 self .document = document
10321032 self .wrapped_document = WrappedDocument (document , tab_width = self .indent_width )
10331033 self .navigator = DocumentNavigator (self .wrapped_document )
1034- self ._build_highlight_map ()
1034+ self ._reset_highlights ()
10351035 self .move_cursor ((0 , 0 ))
10361036 self ._rewrap_and_refresh_virtual_size ()
10371037
@@ -1444,7 +1444,7 @@ def edit(self, edit: Edit) -> EditResult:
14441444
14451445 self ._refresh_size ()
14461446 edit .after (self )
1447- self ._build_highlight_map ()
1447+ self ._reset_highlights ()
14481448 self .post_message (self .Changed (self ))
14491449 return result
14501450
@@ -1507,7 +1507,7 @@ def _undo_batch(self, edits: Sequence[Edit]) -> None:
15071507 self ._refresh_size ()
15081508 for edit in reversed (edits ):
15091509 edit .after (self )
1510- self ._build_highlight_map ()
1510+ self ._reset_highlights ()
15111511 self .post_message (self .Changed (self ))
15121512
15131513 def _redo_batch (self , edits : Sequence [Edit ]) -> None :
@@ -1555,7 +1555,7 @@ def _redo_batch(self, edits: Sequence[Edit]) -> None:
15551555 self ._refresh_size ()
15561556 for edit in edits :
15571557 edit .after (self )
1558- self ._build_highlight_map ()
1558+ self ._reset_highlights ()
15591559 self .post_message (self .Changed (self ))
15601560
15611561 async def _on_key (self , event : events .Key ) -> None :
0 commit comments