import re import regex from point import Point from render import HighlightRegion BG = 'black' SELECTED = 'magenta' UNSELECTED = 'yellow' class IllegalPatternError(Exception): pass def escape_literal(s): return re.escape(s) def find_ranges(r, w, start=None, end=None): if not w.buffer.lines: return [] if start is None: (x, y) = (0, 0) else: (x, y) = start.xy() if end is None: (x2, y2) = (len(w.buffer.lines[-1]), len(w.buffer.lines) - 1) else: (x2, y2) = end.xy() ranges = [] while y <= y2: if y == y2: limit = x2 else: limit = len(w.buffer.lines[y]) for m in r.finditer(w.buffer.lines[y], x, limit): if len(m.group(0)) == 0: raise IllegalPatternError, "zero-width match found" p1, p2 = Point(m.start(), y), Point(m.end(), y) hr = HighlightRegion(w, p1, p2, BG, UNSELECTED, match=m, name='search') ranges.append(hr) x = 0 y += 1 return ranges def find(r, w, move=False, direction='next', start=None, end=None): app = w.application c = w.logical_cursor() newc = None ranges = find_ranges(r, w, start, end) indices = range(0, len(ranges)) (x, y) = c.xy() if move: offset = 1 else: offset = 0 if direction == 'next': limit = Point(x - 1 + offset, y) elif direction == 'previous': limit = Point(x + 1 - offset, y) for hr in app.highlighted_ranges: (wz, p1, p2, fg, bg) = hr if p1 == c: limit = Point(x + 1 + p2.x - p1.x - 2*offset + 1, y) break indices.reverse() else: raise Exception, 'blech' for i in indices: 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) break if newc: w.goto(newc[0]) else: 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: continue elif hr.p2 > w.last: break app.add_highlighted_range(hr) return newc 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)