grep: refactor loop that yields matched text with label
authorYuya Nishihara <yuya@tcha.org>
Thu, 18 Aug 2016 14:03:25 +0900
changeset 29854 b842b1adfea2
parent 29849 f148bfa40489
child 29855 fac24eab65a4
grep: refactor loop that yields matched text with label As preparation for formatter support, this and the next patch split linestate.__iter__() into two functions, line scanner and displayer. New code uses regexp.search(str, pos) in place of regexp.search(substr), which appears to fix a bug of highlighting.
mercurial/commands.py
tests/test-grep.t
--- a/mercurial/commands.py	Tue Jul 05 09:37:07 2016 +0200
+++ b/mercurial/commands.py	Thu Aug 18 14:03:25 2016 +0900
@@ -4345,19 +4345,24 @@
         def __eq__(self, other):
             return self.line == other.line
 
+        def findpos(self):
+            """Iterate all (start, end) indices of matches"""
+            yield self.colstart, self.colend
+            p = self.colend
+            while p < len(self.line):
+                m = regexp.search(self.line, p)
+                if not m:
+                    break
+                yield m.span()
+                p = m.end()
+
         def __iter__(self):
-            yield (self.line[:self.colstart], '')
-            yield (self.line[self.colstart:self.colend], 'grep.match')
-            rest = self.line[self.colend:]
-            while rest != '':
-                match = regexp.search(rest)
-                if not match:
-                    yield (rest, '')
-                    break
-                mstart, mend = match.span()
-                yield (rest[:mstart], '')
-                yield (rest[mstart:mend], 'grep.match')
-                rest = rest[mend:]
+            p = 0
+            for s, e in self.findpos():
+                yield self.line[p:s], ''
+                yield self.line[s:e], 'grep.match'
+                p = e
+            yield self.line[p:], ''
 
     matches = {}
     copies = {}
--- a/tests/test-grep.t	Tue Jul 05 09:37:07 2016 +0200
+++ b/tests/test-grep.t	Thu Aug 18 14:03:25 2016 +0900
@@ -111,6 +111,12 @@
   color:2:-:orange
   color:1:+:orange
 
+test substring match: '^' should only match at the beginning
+
+  $ hg grep '^.' --config extensions.color= --color debug
+  [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.match|b]lack
+  [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.match|o]range
+  [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.match|b]lue
 
 match in last "line" without newline