Skip to content

Commit 760aa63

Browse files
committed
Update with suggestions by Darren Burns.
1 parent 34ead81 commit 760aa63

File tree

1 file changed

+42
-42
lines changed

1 file changed

+42
-42
lines changed

src/textual/widgets/_text_area.py

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -101,48 +101,47 @@ class HighlightMap:
101101

102102
BLOCK_SIZE = 50
103103

104-
def __init__(self, text_area_widget: widgets.TextArea):
105-
self.text_area_widget: widgets.TextArea = text_area_widget
106-
self.uncovered_lines: dict[int, range] = {}
104+
def __init__(self, text_area: TextArea):
105+
self.text_area: TextArea = text_area
106+
"""The text area associated with this highlight map."""
107107

108-
# A mapping from line index to a list of Highlight instances.
109-
self._highlights: LineToHighlightsMap = defaultdict(list)
110-
self.reset()
108+
self._highlighted_blocks: set[int] = set()
109+
"""The set of blocks that have been highlighted. Each block covers BLOCK_SIZE
110+
lines.
111+
"""
112+
113+
self._highlights: dict[int, list[Highlight]] = defaultdict(list)
114+
"""A mapping from line index to a list of Highlight instances."""
111115

112116
def reset(self) -> None:
113117
"""Reset so that future lookups rebuild the highlight map."""
114118
self._highlights.clear()
115-
line_count = self.document.line_count
116-
uncovered_lines = self.uncovered_lines
117-
uncovered_lines.clear()
118-
i = end_range = 0
119-
for i in range(0, line_count, self.BLOCK_SIZE):
120-
end_range = min(i + self.BLOCK_SIZE, line_count)
121-
line_range = range(i, end_range)
122-
uncovered_lines.update({j: line_range for j in line_range})
123-
if end_range < line_count:
124-
line_range = range(i, line_count)
125-
uncovered_lines.update({j: line_range for j in line_range})
119+
self._highlighted_blocks.clear()
126120

127121
@property
128122
def document(self) -> DocumentBase:
129123
"""The text document being highlighted."""
130-
return self.text_area_widget.document
124+
return self.text_area.document
125+
126+
def __getitem__(self, index: int) -> list[Highlight]:
127+
block_index = index // self.BLOCK_SIZE
128+
if block_index not in self._highlighted_blocks:
129+
self._highlighted_blocks.add(block_index)
130+
self._build_part_of_highlight_map(block_index * self.BLOCK_SIZE)
131+
return self._highlights[index]
131132

132-
def __getitem__(self, idx: int) -> list[text_area.Highlight]:
133-
if idx in self.uncovered_lines:
134-
self._build_part_of_highlight_map(self.uncovered_lines[idx])
135-
return self._highlights[idx]
133+
def _build_part_of_highlight_map(self, start_index: int) -> None:
134+
"""Build part of the highlight map.
136135
137-
def _build_part_of_highlight_map(self, line_range: range) -> None:
138-
"""Build part of the highlight map."""
136+
Args:
137+
start_index: The start of the block of line for which to build the map.
138+
"""
139139
highlights = self._highlights
140-
for line_index in line_range:
141-
self.uncovered_lines.pop(line_index)
142-
start_point = (line_range[0], 0)
143-
end_point = (line_range[-1] + 1, 0)
140+
start_point = (start_index, 0)
141+
end_index = min(self.document.line_count, start_index + self.BLOCK_SIZE)
142+
end_point = (end_index, 0)
144143
captures = self.document.query_syntax_tree(
145-
self.text_area_widget._highlight_query,
144+
self.text_area._highlight_query,
146145
start_point=start_point,
147146
end_point=end_point,
148147
)
@@ -160,8 +159,9 @@ def _build_part_of_highlight_map(self, line_range: range) -> None:
160159
)
161160

162161
# Add the middle lines - entire row of this node is highlighted
162+
middle_highlight = (0, None, highlight_name)
163163
for node_row in range(node_start_row + 1, node_end_row):
164-
highlights[node_row].append((0, None, highlight_name))
164+
highlights[node_row].append(middle_highlight)
165165

166166
# Add the last line of the node range
167167
highlights[node_end_row].append(
@@ -177,16 +177,16 @@ def _build_part_of_highlight_map(self, line_range: range) -> None:
177177
# to be sorted in ascending order of ``a``. When two highlights have the same
178178
# value of ``a`` then the one with the larger a--b range comes first, with ``None``
179179
# being considered larger than any number.
180-
def sort_key(hl) -> tuple[int, int, int]:
181-
a, b, _ = hl
182-
max_range_ind = 1
180+
def sort_key(highlight: Highlight) -> tuple[int, int, int]:
181+
a, b, _ = highlight
182+
max_range_index = 1
183183
if b is None:
184-
max_range_ind = 0
184+
max_range_index = 0
185185
b = a
186-
return a, max_range_ind, a - b
186+
return a, max_range_index, a - b
187187

188-
for line_index in line_range:
189-
line_highlights = highlights.get(line_index, []).sort(key=sort_key)
188+
for line_index in range(start_index, end_index):
189+
highlights.get(line_index, []).sort(key=sort_key)
190190

191191

192192
@dataclass
@@ -708,7 +708,7 @@ def check_consume_key(self, key: str, character: str | None = None) -> bool:
708708
# Otherwise we capture all printable keys
709709
return character is not None and character.isprintable()
710710

711-
def _build_highlight_map(self) -> None:
711+
def _reset_highlights(self) -> None:
712712
"""Reset the lazily evaluated highlight map."""
713713

714714
if self._highlight_query:
@@ -1034,7 +1034,7 @@ def _set_document(self, text: str, language: str | None) -> None:
10341034
self.document = document
10351035
self.wrapped_document = WrappedDocument(document, tab_width=self.indent_width)
10361036
self.navigator = DocumentNavigator(self.wrapped_document)
1037-
self._build_highlight_map()
1037+
self._reset_highlights()
10381038
self.move_cursor((0, 0))
10391039
self._rewrap_and_refresh_virtual_size()
10401040

@@ -1447,7 +1447,7 @@ def edit(self, edit: Edit) -> EditResult:
14471447

14481448
self._refresh_size()
14491449
edit.after(self)
1450-
self._build_highlight_map()
1450+
self._reset_highlights()
14511451
self.post_message(self.Changed(self))
14521452
return result
14531453

@@ -1510,7 +1510,7 @@ def _undo_batch(self, edits: Sequence[Edit]) -> None:
15101510
self._refresh_size()
15111511
for edit in reversed(edits):
15121512
edit.after(self)
1513-
self._build_highlight_map()
1513+
self._reset_highlights()
15141514
self.post_message(self.Changed(self))
15151515

15161516
def _redo_batch(self, edits: Sequence[Edit]) -> None:
@@ -1558,7 +1558,7 @@ def _redo_batch(self, edits: Sequence[Edit]) -> None:
15581558
self._refresh_size()
15591559
for edit in edits:
15601560
edit.after(self)
1561-
self._build_highlight_map()
1561+
self._reset_highlights()
15621562
self.post_message(self.Changed(self))
15631563

15641564
async def _on_key(self, event: events.Key) -> None:

0 commit comments

Comments
 (0)