Skip to content

Commit 59a7793

Browse files
committed
Update with suggestions by Darren Burns.
1 parent 57de067 commit 59a7793

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
@@ -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

Comments
 (0)