[PATCH 4 of 9] grep: add -e option for specifying multiple patterns

Idan Kamara idankk86 at gmail.com
Sun Oct 14 15:54:21 CDT 2012


# HG changeset patch
# User Idan Kamara <idankk86 at gmail.com>
# Date 1350073273 -7200
# Node ID 06edbeb509881597122b46de831da4332076c4a1
# Parent  806bab6620c0308b61a4cf9c0e95927650ccb513
grep: add -e option for specifying multiple patterns

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -2885,12 +2885,15 @@
      _('print only filenames and revisions that match')),
     ('n', 'line-number', None, _('print matching line numbers')),
     ('', 'no-filename', None, _('suppress filename from output')),
+    ('e', 'regexp', [],
+     _('use this pattern to find matches (must be used if a pattern'
+       ' starts with -), multiple patterns are or-ed'), _('PATTERN')),
     ('r', 'rev', [],
      _('only search files changed within revision range'), _('REV')),
     ('u', 'user', None, _('list the author (long with -v)')),
     ('d', 'date', None, _('list the date (short with -q)')),
     ] + walkopts,
-    _('[OPTION]... PATTERN [FILE]...'))
+    _('[OPTION]... [-e] PATTERN... [FILE]...'))
 def grep(ui, repo, pattern, *pats, **opts):
     """search for a pattern in specified files and revisions
 
@@ -2913,7 +2916,13 @@
     if opts.get('ignore_case'):
         reflags |= re.I
     try:
-        regexp = re.compile(pattern, reflags)
+        regexps = []
+        if opts.get('regexp'):
+            for p in opts.get('regexp'):
+                regexps.append(re.compile(p, reflags))
+            pats = (pattern,) + pats
+        else:
+            regexps.append(re.compile(pattern, reflags))
     except re.error, inst:
         ui.warn(_("grep: invalid match pattern: %s\n") % inst)
         return 1
@@ -2927,9 +2936,18 @@
         begin = 0
         linenum = 0
         while True:
-            match = regexp.search(body, begin)
-            if not match:
+            # Search all regexps and pick the one that starts earlier in the
+            # file. We could probably be more efficient here by only searching
+            # the regexp that was picked in the previous iteration and those
+            # whose span intersected with it.
+            matches = []
+            for regexp in regexps:
+                match = regexp.search(body, begin)
+                if match:
+                    matches.append(match)
+            if not matches:
                 break
+            match = min(matches, key=lambda m: m.span()[0])
             mstart, mend = match.span()
             linenum += body.count('\n', begin, mstart) + 1
             lstart = body.rfind('\n', begin, mstart) + 1 or begin
diff --git a/tests/test-debugcomplete.t b/tests/test-debugcomplete.t
--- a/tests/test-debugcomplete.t
+++ b/tests/test-debugcomplete.t
@@ -250,7 +250,7 @@
   debugwalk: include, exclude
   debugwireargs: three, four, five, ssh, remotecmd, insecure
   graft: rev, continue, edit, log, currentdate, currentuser, date, user, tool, dry-run
-  grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, no-filename, rev, user, date, include, exclude
+  grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, no-filename, regexp, rev, user, date, include, exclude
   heads: rev, topo, active, closed, style, template
   help: extension, command, keyword
   identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
diff --git a/tests/test-grep.t b/tests/test-grep.t
--- a/tests/test-grep.t
+++ b/tests/test-grep.t
@@ -27,6 +27,10 @@
   port:4:export
   port:4:vaportight
   port:4:import/export
+  $ hg grep -e exp -e vap -e imp port
+  port:4:export
+  port:4:vaportight
+  port:4:import/export
   $ hg grep --no-filename port port
   4:export
   4:vaportight


More information about the Mercurial-devel mailing list