pmacs3/search.py

87 lines
2.3 KiB
Python

import re
import regex
from point2 import Point
bg_color = 'black'
selected_color = 'magenta'
unselected_color = 'yellow'
class IllegalPatternError(Exception):
pass
def escape_literal(s):
return regex.meta_chars.sub(r'\\\1', s)
def find_ranges(s, 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]) - 1, len(w.buffer.lines) - 1)
else:
(x2, y2) = end.xy()
#s2 = escape_literal(s)
#r = re.compile(s2, re.IGNORECASE)
r = re.compile(s, re.IGNORECASE)
ranges = []
while y <= y2:
if y == y2:
limit = x2
else:
limit = len(w.buffer.lines[y]) - 1
for m in r.finditer(w.buffer.lines[y], x, limit):
if len(m.group(0)) == 0:
raise IllegalPatternError, "zero-width match found for: %r" % s
ranges.append([Point(m.start(), y), Point(m.end(), y), bg_color, unselected_color])
x = 0
y += 1
return ranges
def find(s, w, move=False, direction='next', start=None, end=None):
app = w.application
c = w.logical_cursor()
newc = None
ranges = find_ranges(s, 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)
else:
limit = Point(x + len(s) + 1 - offset, y)
indices.reverse()
for i in indices:
if ((direction == 'next' and ranges[i][0] > limit) or
(direction != 'next' and ranges[i][1] < limit)):
ranges[i][3] = selected_color
newc = (ranges[i][0], ranges[i][1])
break
if ranges and not newc:
return None
app.clear_highlighted_ranges()
if newc:
w.goto(newc[0])
for (p1, p2, fg, bg) in ranges:
if p1 < w.first:
continue
elif p2 > w.last:
break
app.add_highlighted_range(w, p1, p2, fg, bg)
return newc
def find_previous(s, w, move=False, start=None, end=None):
return find(s, w, move, 'previous', start, end)
def find_next(s, w, move=False, start=None, end=None):
return find(s, w, move, 'next', start, end)