import re import regex from point import Point from render import HighlightRegion bg_color = 'black' selected_color = 'magenta' unselected_color = '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" ranges.append([Point(m.start(), y), Point(m.end(), y), bg_color, unselected_color, m]) 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][0] > limit: ranges[i][3] = selected_color newc = (ranges[i][0], ranges[i][1], ranges[i][4]) break elif direction == 'previous' and ranges[i][1] < limit: ranges[i][3] = selected_color newc = (ranges[i][0], ranges[i][1], ranges[i][4]) break if ranges and not newc: return None app.clear_highlighted_ranges('search') if newc: w.goto(newc[0]) for (p1, p2, fg, bg, m) in ranges: if p1 < w.first: continue elif p2 > w.last: break hr = HighlightRegion(w, p1, p2, fg, bg, match=m, name='search') 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)