##// END OF EJS Templates
grep: move match and diff logic to new module...
Yuya Nishihara -
r46288:de6f2afc default
parent child Browse files
Show More
@@ -0,0 +1,71 b''
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])
@@ -7,7 +7,6 b''
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import difflib
11 import errno
10 import errno
12 import os
11 import os
13 import re
12 import re
@@ -41,6 +40,7 b' from . import ('
41 filemerge,
40 filemerge,
42 formatter,
41 formatter,
43 graphmod,
42 graphmod,
43 grep as grepmod,
44 hbisect,
44 hbisect,
45 help,
45 help,
46 hg,
46 hg,
@@ -3399,48 +3399,6 b' def grep(ui, repo, pattern, *pats, **opt'
3399 sep = eol = b'\0'
3399 sep = eol = b'\0'
3400
3400
3401 getfile = util.lrucachefunc(repo.file)
3401 getfile = util.lrucachefunc(repo.file)
3402
3403 def matchlines(body, regexp):
3404 begin = 0
3405 linenum = 0
3406 while begin < len(body):
3407 match = regexp.search(body, begin)
3408 if not match:
3409 break
3410 mstart, mend = match.span()
3411 linenum += body.count(b'\n', begin, mstart) + 1
3412 lstart = body.rfind(b'\n', begin, mstart) + 1 or begin
3413 begin = body.find(b'\n', mend) + 1 or len(body) + 1
3414 lend = begin - 1
3415 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3416
3417 class linestate(object):
3418 def __init__(self, line, linenum, colstart, colend):
3419 self.line = line
3420 self.linenum = linenum
3421 self.colstart = colstart
3422 self.colend = colend
3423
3424 def __hash__(self):
3425 return hash(self.line)
3426
3427 def __eq__(self, other):
3428 return self.line == other.line
3429
3430 def findpos(self, regexp):
3431 """Iterate all (start, end) indices of matches"""
3432 yield self.colstart, self.colend
3433 p = self.colend
3434 while p < len(self.line):
3435 m = regexp.search(self.line, p)
3436 if not m:
3437 break
3438 if m.end() == p:
3439 p += 1
3440 else:
3441 yield m.span()
3442 p = m.end()
3443
3444 matches = {}
3402 matches = {}
3445 copies = {}
3403 copies = {}
3446
3404
@@ -3450,25 +3408,10 b' def grep(ui, repo, pattern, *pats, **opt'
3450 if body is None:
3408 if body is None:
3451 return
3409 return
3452
3410
3453 for lnum, cstart, cend, line in matchlines(body, regexp):
3411 for lnum, cstart, cend, line in grepmod.matchlines(body, regexp):
3454 s = linestate(line, lnum, cstart, cend)
3412 s = grepmod.linestate(line, lnum, cstart, cend)
3455 m.append(s)
3413 m.append(s)
3456
3414
3457 def difflinestates(a, b):
3458 sm = difflib.SequenceMatcher(None, a, b)
3459 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3460 if tag == 'insert':
3461 for i in pycompat.xrange(blo, bhi):
3462 yield (b'+', b[i])
3463 elif tag == 'delete':
3464 for i in pycompat.xrange(alo, ahi):
3465 yield (b'-', a[i])
3466 elif tag == 'replace':
3467 for i in pycompat.xrange(alo, ahi):
3468 yield (b'-', a[i])
3469 for i in pycompat.xrange(blo, bhi):
3470 yield (b'+', b[i])
3471
3472 uipathfn = scmutil.getuipathfn(repo)
3415 uipathfn = scmutil.getuipathfn(repo)
3473
3416
3474 def display(fm, fn, ctx, pstates, states):
3417 def display(fm, fn, ctx, pstates, states):
@@ -3493,7 +3436,7 b' def grep(ui, repo, pattern, *pats, **opt'
3493
3436
3494 fieldnamemap = {b'linenumber': b'lineno'}
3437 fieldnamemap = {b'linenumber': b'lineno'}
3495 if diff:
3438 if diff:
3496 iter = difflinestates(pstates, states)
3439 iter = grepmod.difflinestates(pstates, states)
3497 else:
3440 else:
3498 iter = [(b'', l) for l in states]
3441 iter = [(b'', l) for l in states]
3499 for change, l in iter:
3442 for change, l in iter:
General Comments 0
You need to be logged in to leave comments. Login now