1
1
import re
2
2
from functools import partial , reduce
3
3
from math import gcd
4
- from operator import attrgetter , itemgetter
4
+ from operator import itemgetter
5
5
from rich .emoji import EmojiVariant
6
6
from typing import (
7
7
TYPE_CHECKING ,
@@ -1033,6 +1033,7 @@ def divide(self, offsets: Iterable[int]) -> Lines:
1033
1033
Lines: New RichText instances between offsets.
1034
1034
"""
1035
1035
_offsets = list (offsets )
1036
+
1036
1037
if not _offsets :
1037
1038
return Lines ([self .copy ()])
1038
1039
@@ -1056,33 +1057,46 @@ def divide(self, offsets: Iterable[int]) -> Lines:
1056
1057
)
1057
1058
if not self ._spans :
1058
1059
return new_lines
1059
- order = {span : span_index for span_index , span in enumerate (self ._spans )}
1060
- span_stack = sorted (self ._spans , key = attrgetter ("start" ), reverse = True )
1061
1060
1062
- pop = span_stack . pop
1063
- push = span_stack . append
1061
+ _line_appends = [ line . _spans . append for line in new_lines . _lines ]
1062
+ line_count = len ( line_ranges )
1064
1063
_Span = Span
1065
- get_order = order .__getitem__
1066
-
1067
- for line , (start , end ) in zip (new_lines , line_ranges ):
1068
- if not span_stack :
1069
- break
1070
- append_span = line ._spans .append
1071
- position = len (span_stack ) - 1
1072
- while span_stack [position ].start < end :
1073
- span = pop (position )
1074
- add_span , remaining_span = span .split (end )
1075
- if remaining_span :
1076
- push (remaining_span )
1077
- order [remaining_span ] = order [span ]
1078
- span_start , span_end , span_style = add_span
1079
- line_span = _Span (span_start - start , span_end - start , span_style )
1080
- order [line_span ] = order [span ]
1081
- append_span (line_span )
1082
- position -= 1
1083
- if position < 0 or not span_stack :
1084
- break # pragma: no cover
1085
- line ._spans .sort (key = get_order )
1064
+
1065
+ for span_start , span_end , style in self ._spans :
1066
+
1067
+ lower_bound = 0
1068
+ upper_bound = line_count
1069
+ start_line_no = (lower_bound + upper_bound ) // 2
1070
+
1071
+ while True :
1072
+ line_start , line_end = line_ranges [start_line_no ]
1073
+ if span_start < line_start :
1074
+ upper_bound = start_line_no - 1
1075
+ elif span_start > line_end :
1076
+ lower_bound = start_line_no + 1
1077
+ else :
1078
+ break
1079
+ start_line_no = (lower_bound + upper_bound ) // 2
1080
+
1081
+ end_line_no = lower_bound = start_line_no
1082
+ upper_bound = line_count
1083
+
1084
+ while True :
1085
+ line_start , line_end = line_ranges [end_line_no ]
1086
+ if span_end < line_start :
1087
+ upper_bound = end_line_no - 1
1088
+ elif span_end > line_end :
1089
+ lower_bound = end_line_no + 1
1090
+ else :
1091
+ break
1092
+ end_line_no = (lower_bound + upper_bound ) // 2
1093
+
1094
+ for line_no in range (start_line_no , end_line_no + 1 ):
1095
+ line_start , line_end = line_ranges [line_no ]
1096
+ new_start = max (0 , span_start - line_start )
1097
+ new_end = min (span_end - line_start , line_end - line_start )
1098
+ if new_end > new_start :
1099
+ _line_appends [line_no ](_Span (new_start , new_end , style ))
1086
1100
1087
1101
return new_lines
1088
1102
0 commit comments