|
1 # grep.py - logic for history walk and grep |
|
2 # |
|
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> |
|
4 # |
|
5 # This software may be used and distributed according to the terms of the |
|
6 # GNU General Public License version 2 or any later version. |
|
7 |
|
8 from __future__ import absolute_import |
|
9 |
|
10 import difflib |
|
11 |
|
12 from . import pycompat |
|
13 |
|
14 |
|
15 def matchlines(body, regexp): |
|
16 begin = 0 |
|
17 linenum = 0 |
|
18 while begin < len(body): |
|
19 match = regexp.search(body, begin) |
|
20 if not match: |
|
21 break |
|
22 mstart, mend = match.span() |
|
23 linenum += body.count(b'\n', begin, mstart) + 1 |
|
24 lstart = body.rfind(b'\n', begin, mstart) + 1 or begin |
|
25 begin = body.find(b'\n', mend) + 1 or len(body) + 1 |
|
26 lend = begin - 1 |
|
27 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend] |
|
28 |
|
29 |
|
30 class linestate(object): |
|
31 def __init__(self, line, linenum, colstart, colend): |
|
32 self.line = line |
|
33 self.linenum = linenum |
|
34 self.colstart = colstart |
|
35 self.colend = colend |
|
36 |
|
37 def __hash__(self): |
|
38 return hash(self.line) |
|
39 |
|
40 def __eq__(self, other): |
|
41 return self.line == other.line |
|
42 |
|
43 def findpos(self, regexp): |
|
44 """Iterate all (start, end) indices of matches""" |
|
45 yield self.colstart, self.colend |
|
46 p = self.colend |
|
47 while p < len(self.line): |
|
48 m = regexp.search(self.line, p) |
|
49 if not m: |
|
50 break |
|
51 if m.end() == p: |
|
52 p += 1 |
|
53 else: |
|
54 yield m.span() |
|
55 p = m.end() |
|
56 |
|
57 |
|
58 def difflinestates(a, b): |
|
59 sm = difflib.SequenceMatcher(None, a, b) |
|
60 for tag, alo, ahi, blo, bhi in sm.get_opcodes(): |
|
61 if tag == 'insert': |
|
62 for i in pycompat.xrange(blo, bhi): |
|
63 yield (b'+', b[i]) |
|
64 elif tag == 'delete': |
|
65 for i in pycompat.xrange(alo, ahi): |
|
66 yield (b'-', a[i]) |
|
67 elif tag == 'replace': |
|
68 for i in pycompat.xrange(alo, ahi): |
|
69 yield (b'-', a[i]) |
|
70 for i in pycompat.xrange(blo, bhi): |
|
71 yield (b'+', b[i]) |