-
Notifications
You must be signed in to change notification settings - Fork 0
/
base.py
71 lines (63 loc) · 2.4 KB
/
base.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import re
from re import Pattern
from typing import Any, Generator, Tuple, Union
from sublime import View
from sublime_api import view_cached_substr as substr # pyright: ignore
CHUNKSIZE = 10_000
def buffer_slice(
v: View, forward: bool, default_yield_border: bool = False
) -> Generator[Union[None, Tuple[int, int]], Tuple[Any, int, Pattern], None]:
vid = v.id()
first = 0
last = v.size()
if default_yield_border:
default_yield = (last, last) if forward else (first, first)
else:
default_yield = None
*_, index, pattern = yield default_yield
unfolded = []
for fold_start, fold_end in v.folded_regions():
unfolded.append((first, fold_start))
first = fold_end
unfolded.append((first, last))
regions = []
pt = -1
for a, b in unfolded:
while pt < b:
pt = min((index if index > a else last), b, v.line(a + CHUNKSIZE).b)
regions.append((a, pt))
a = pt
buffers = {}
if forward:
while True:
while index >= last:
*_, index, new_pattern = yield default_yield
_s, _e = next((_s, _e) for _s, _e in regions if index < _e)
offset = max(index - _s, 0)
piece = buffers.setdefault(_s, substr(vid, _s, _e))
for m in re.finditer(pattern, piece[offset:]):
mstart = _s + offset + m.start()
mend = _s + offset + m.end()
*_, index, new_pattern = yield (mstart, mend)
if index != mend or new_pattern != pattern: # new region
pattern = new_pattern
break
else:
index = _e + 1
else:
regions = regions[::-1]
while True:
while index <= 0:
*_, index, new_pattern = yield default_yield
_e, _s = next((_s, _e) for _s, _e in regions if index > _s)
offset = max(_s - index, 0)
piece = buffers.setdefault(_s, substr(vid, _s, _e)[::-1])
for m in re.finditer(pattern, piece[offset:]):
mstart = _s - offset - m.start()
mend = _s - offset - m.end()
*_, index, new_pattern = yield (mstart, mend)
if index != mend or new_pattern != pattern: # new region
pattern = new_pattern
break
else:
index = _e - 1