mercurial/grep.py
changeset 45696 de6f2afc0247
child 45697 494642ed3c50
equal deleted inserted replaced
45695:760bb4d74aad 45696:de6f2afc0247
       
     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])