Commits

Takumi IINO  committed 0ecb860

import grepfile project

  • Participants

Comments (0)

Files changed (3)

+syntax: glob
+*~
+*.swp
+\#*\#
+.\#*
+*.pyc
+*.orig
+================================
+Grepfile extension for Mercurial
+================================
+
+Installing
+==========
+
+::
+
+  [extensions]
+  grepfile = [path to]/grepfile.py
+
+Usage
+=====
+
+This extension adds a new command ``grepfile`` that search files
+for a regular expression.
+
+Example::
+
+  hg grepfile -i -n ctx.walk
+"""search for a pattern in specified files
+"""
+
+import re
+from mercurial import commands, error, util, scmutil
+from mercurial.i18n import _
+
+def grepfile(ui, repo, pattern, *pats, **opts):
+    """search for a pattern in specified files
+
+    Search files for a regular expression.
+    """
+    rev = scmutil.revsingle(repo, opts.get('rev')).node()
+
+    reflags = re.M
+    if opts.get('ignore_case'):
+        reflags |= re.I
+    try:
+        regexp = re.compile(pattern, reflags)
+    except re.error, inst:
+        ui.warn(_("grep: invalid match pattern: %s\n") % inst)
+        return 1
+    sep, eol = ':', '\n'
+
+    getfile = util.lrucachefunc(repo.file)
+
+    def matchlines(body):
+        begin = 0
+        linenum = 0
+        while True:
+            match = regexp.search(body, begin)
+            if not match:
+                break
+            mstart, mend = match.span()
+            linenum += body.count('\n', begin, mstart) + 1
+            lstart = body.rfind('\n', begin, mstart) + 1 or begin
+            begin = body.find('\n', mend) + 1 or len(body) + 1
+            lend = begin - 1
+            yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
+
+    def display(fn, ctx, lnum, cstart, cend, line):
+        datefunc = ui.quiet and util.shortdate or util.datestr
+        def binary():
+            flog = getfile(fn)
+            return util.binary(flog.read(ctx.filenode(fn)))
+        before = line[:cstart]
+        match = line[cstart:cend]
+        after = line[cend:]
+        cols = [fn]
+        if opts.get('line_number'):
+            cols.append(str(lnum))
+        ui.write(sep.join(cols))
+        if not opts.get('text') and binary():
+            ui.write(sep + " Binary file matches")
+        else:
+            ui.write(sep + before)
+            ui.write(match, label='grep.match')
+            ui.write(after)
+        ui.write(eol)
+
+    m = scmutil.match(repo[rev], pats, opts, default='relglob')
+    m.bad = lambda x, y: False
+    ctx = repo[rev]
+    for fn in ctx.walk(m):
+        if not rev and fn not in repo.dirstate:
+            continue
+        flog = getfile(fn)
+        try:
+            fnode = ctx.filenode(fn)
+        except error.LookupError:
+            continue
+        for lnum, cstart, cend, line in matchlines(flog.read(fnode)):
+            display(fn, ctx, lnum, cstart, cend, line)
+    return 0
+
+cmdtable = {
+    "grepfile":
+    (grepfile,
+     [('a', 'text', None, _('treat all files as text')),
+      ('i', 'ignore-case', None, _('ignore case when matching')),
+      ('n', 'line-number', None, _('print matching line numbers')),
+      ('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
+      ] + commands.walkopts,
+     _('[OPTION]... PATTERN [FILE_PATTERN]...')),
+    }