2007-07-09 17:47:15 -04:00
|
|
|
import re
|
2007-10-21 20:50:11 -04:00
|
|
|
from point import Point
|
2008-05-03 16:22:12 -04:00
|
|
|
from render import HighlightRegion
|
2007-07-06 14:34:14 -04:00
|
|
|
|
2008-05-03 20:21:17 -04:00
|
|
|
BG = 'black'
|
|
|
|
SELECTED = 'magenta'
|
|
|
|
UNSELECTED = 'yellow'
|
2007-07-06 14:34:14 -04:00
|
|
|
|
2007-07-09 17:47:15 -04:00
|
|
|
class IllegalPatternError(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def escape_literal(s):
|
2007-08-11 10:16:41 -04:00
|
|
|
return re.escape(s)
|
2007-07-09 17:47:15 -04:00
|
|
|
|
2007-07-09 18:31:59 -04:00
|
|
|
def find_ranges(r, w, start=None, end=None):
|
2007-07-06 15:53:47 -04:00
|
|
|
if not w.buffer.lines:
|
|
|
|
return []
|
|
|
|
|
|
|
|
if start is None:
|
|
|
|
(x, y) = (0, 0)
|
|
|
|
else:
|
|
|
|
(x, y) = start.xy()
|
|
|
|
if end is None:
|
2007-07-11 04:55:54 -04:00
|
|
|
(x2, y2) = (len(w.buffer.lines[-1]), len(w.buffer.lines) - 1)
|
2007-07-06 15:53:47 -04:00
|
|
|
else:
|
|
|
|
(x2, y2) = end.xy()
|
2007-07-09 17:47:15 -04:00
|
|
|
|
2007-07-06 14:34:14 -04:00
|
|
|
ranges = []
|
2007-07-06 15:53:47 -04:00
|
|
|
while y <= y2:
|
|
|
|
if y == y2:
|
|
|
|
limit = x2
|
|
|
|
else:
|
2007-07-11 04:55:54 -04:00
|
|
|
limit = len(w.buffer.lines[y])
|
2007-07-09 17:47:15 -04:00
|
|
|
for m in r.finditer(w.buffer.lines[y], x, limit):
|
|
|
|
if len(m.group(0)) == 0:
|
2008-05-16 19:02:22 -04:00
|
|
|
raise IllegalPatternError("zero-width match found")
|
2008-05-03 20:21:17 -04:00
|
|
|
p1, p2 = Point(m.start(), y), Point(m.end(), y)
|
|
|
|
hr = HighlightRegion(w, p1, p2, BG, UNSELECTED, match=m, name='search')
|
|
|
|
ranges.append(hr)
|
2007-07-06 14:34:14 -04:00
|
|
|
x = 0
|
|
|
|
y += 1
|
|
|
|
return ranges
|
|
|
|
|
2007-07-09 18:31:59 -04:00
|
|
|
def find(r, w, move=False, direction='next', start=None, end=None):
|
2007-07-06 14:34:14 -04:00
|
|
|
app = w.application
|
|
|
|
c = w.logical_cursor()
|
|
|
|
newc = None
|
2007-07-09 18:31:59 -04:00
|
|
|
ranges = find_ranges(r, w, start, end)
|
2020-08-31 20:58:27 -04:00
|
|
|
indices = list(range(0, len(ranges)))
|
2007-07-06 14:34:14 -04:00
|
|
|
(x, y) = c.xy()
|
2007-07-06 15:53:47 -04:00
|
|
|
if move:
|
|
|
|
offset = 1
|
|
|
|
else:
|
|
|
|
offset = 0
|
2007-07-06 14:34:14 -04:00
|
|
|
if direction == 'next':
|
2007-07-06 15:53:47 -04:00
|
|
|
limit = Point(x - 1 + offset, y)
|
2007-07-18 12:15:43 -04:00
|
|
|
elif direction == 'previous':
|
2007-07-09 18:31:59 -04:00
|
|
|
limit = Point(x + 1 - offset, y)
|
2008-05-03 16:22:12 -04:00
|
|
|
for hr in app.highlighted_ranges:
|
|
|
|
(wz, p1, p2, fg, bg) = hr
|
2007-07-18 12:15:43 -04:00
|
|
|
if p1 == c:
|
|
|
|
limit = Point(x + 1 + p2.x - p1.x - 2*offset + 1, y)
|
2007-07-09 18:31:59 -04:00
|
|
|
break
|
2007-07-06 14:34:14 -04:00
|
|
|
indices.reverse()
|
2007-07-18 12:15:43 -04:00
|
|
|
else:
|
2020-08-31 20:58:27 -04:00
|
|
|
raise Exception('blech')
|
2007-07-06 14:34:14 -04:00
|
|
|
for i in indices:
|
2008-05-03 20:21:17 -04:00
|
|
|
if (direction == 'next' and ranges[i].p1 > limit or
|
|
|
|
direction == 'previous' and ranges[i].p2 < limit):
|
|
|
|
ranges[i].bg = SELECTED
|
|
|
|
newc = (ranges[i].p1, ranges[i].p2, ranges[i].match)
|
2007-07-18 12:15:43 -04:00
|
|
|
break
|
2007-07-06 14:34:14 -04:00
|
|
|
if newc:
|
|
|
|
w.goto(newc[0])
|
2008-05-03 22:41:58 -04:00
|
|
|
elif ranges:
|
2008-05-03 20:21:17 -04:00
|
|
|
i = 0
|
|
|
|
if direction == 'next':
|
|
|
|
i = -1
|
|
|
|
ranges[i].bg = SELECTED
|
|
|
|
newc = (ranges[i].p1, ranges[i].p2, ranges[i].match)
|
|
|
|
|
|
|
|
app.clear_highlighted_ranges('search')
|
|
|
|
for hr in ranges:
|
|
|
|
if hr.p1 < w.first:
|
2007-07-06 14:34:14 -04:00
|
|
|
continue
|
2008-05-03 20:21:17 -04:00
|
|
|
elif hr.p2 > w.last:
|
2007-07-06 14:34:14 -04:00
|
|
|
break
|
2008-05-03 17:05:24 -04:00
|
|
|
app.add_highlighted_range(hr)
|
2007-07-06 14:34:14 -04:00
|
|
|
return newc
|
|
|
|
|
2007-07-09 18:31:59 -04:00
|
|
|
def find_previous(r, w, move=False, start=None, end=None):
|
|
|
|
return find(r, w, move, 'previous', start, end)
|
|
|
|
def find_next(r, w, move=False, start=None, end=None):
|
|
|
|
return find(r, w, move, 'next', start, end)
|