Patchwork grep: highlight all matched words

login
register
mail settings
Submitter Takumi IINO
Date March 30, 2014, 4:05 p.m.
Message ID <76046ae80d10e1b3a986.1396195503@iinotakken-no-MacBook-Air.local>
Download mbox | patch
Permalink /patch/4147/
State Accepted
Commit 5014f985305ab64aa8df97fe1b5546ff89fd5b87
Headers show

Comments

Takumi IINO - March 30, 2014, 4:05 p.m.
# HG changeset patch
# User Takumi IINO <trot.thunder@gmail.com>
# Date 1396195205 -32400
#      Mon Mar 31 01:00:05 2014 +0900
# Node ID 76046ae80d10e1b3a9862319a57835d3ce89cfdb
# Parent  596960a4ad0d342506cf2a601e9736c446a04699
grep: highlight all matched words

"hg grep" highlights first matched word only.
This behavior is different from GNU grep.

This patch makes highlight all matched words.
Augie Fackler - April 12, 2014, 8:42 p.m.
On Mon, Mar 31, 2014 at 01:05:03AM +0900, Takumi IINO wrote:
> # HG changeset patch
> # User Takumi IINO <trot.thunder@gmail.com>
> # Date 1396195205 -32400
> #      Mon Mar 31 01:00:05 2014 +0900
> # Node ID 76046ae80d10e1b3a9862319a57835d3ce89cfdb
> # Parent  596960a4ad0d342506cf2a601e9736c446a04699
> grep: highlight all matched words

Just showed this to mpm in person and he said "yeah" so queued, thanks.

>
> "hg grep" highlights first matched word only.
> This behavior is different from GNU grep.
>
> This patch makes highlight all matched words.
>
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -3313,10 +3313,24 @@ def grep(ui, repo, pattern, *pats, **opt
>              return hash((self.linenum, self.line))
>
>          def __eq__(self, other):
>              return self.line == other.line
>
> +        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:]
> +
>      matches = {}
>      copies = {}
>      def grepbody(fn, rev, body):
>          matches[rev].setdefault(fn, [])
>          m = matches[rev][fn]
> @@ -3352,39 +3366,33 @@ def grep(ui, repo, pattern, *pats, **opt
>              iter = difflinestates(pstates, states)
>          else:
>              iter = [('', l) for l in states]
>          for change, l in iter:
>              cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
> -            before, match, after = None, None, None
>
>              if opts.get('line_number'):
>                  cols.append((str(l.linenum), 'grep.linenumber'))
>              if opts.get('all'):
>                  cols.append((change, 'grep.change'))
>              if opts.get('user'):
>                  cols.append((ui.shortuser(ctx.user()), 'grep.user'))
>              if opts.get('date'):
>                  cols.append((datefunc(ctx.date()), 'grep.date'))
> -            if not opts.get('files_with_matches'):
> -                before = l.line[:l.colstart]
> -                match = l.line[l.colstart:l.colend]
> -                after = l.line[l.colend:]
>              for col, label in cols[:-1]:
>                  ui.write(col, label=label)
>                  ui.write(sep, label='grep.sep')
>              ui.write(cols[-1][0], label=cols[-1][1])
> -            if before is not None:
> +            if not opts.get('files_with_matches'):
>                  ui.write(sep, label='grep.sep')
>                  if not opts.get('text') and binary():
>                      ui.write(" Binary file matches")
>                  else:
> -                    ui.write(before)
> -                    ui.write(match, label='grep.match')
> -                    ui.write(after)
> +                    for s, label in l:
> +                        ui.write(s, label=label)
>              ui.write(eol)
>              found = True
> -            if before is None:
> +            if opts.get('files_with_matches'):
>                  break
>          return found
>
>      skip = {}
>      revfiles = {}
> diff --git a/tests/test-grep.t b/tests/test-grep.t
> --- a/tests/test-grep.t
> +++ b/tests/test-grep.t
> @@ -36,11 +36,11 @@ simple with color
>
>    $ hg --config extensions.color= grep --config color.mode=ansi \
>    >     --color=always port port
>    \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m4\x1b[0m\x1b[0;36m:\x1b[0mex\x1b[0;31;1mport\x1b[0m (esc)
>    \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m4\x1b[0m\x1b[0;36m:\x1b[0mva\x1b[0;31;1mport\x1b[0might (esc)
> -  \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m4\x1b[0m\x1b[0;36m:\x1b[0mim\x1b[0;31;1mport\x1b[0m/export (esc)
> +  \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m4\x1b[0m\x1b[0;36m:\x1b[0mim\x1b[0;31;1mport\x1b[0m/ex\x1b[0;31;1mport\x1b[0m (esc)
>
>  all
>
>    $ hg grep --traceback --all -nu port port
>    port:4:4:-:spam:import/export
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel

Patch

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3313,10 +3313,24 @@  def grep(ui, repo, pattern, *pats, **opt
             return hash((self.linenum, self.line))
 
         def __eq__(self, other):
             return self.line == other.line
 
+        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:]
+
     matches = {}
     copies = {}
     def grepbody(fn, rev, body):
         matches[rev].setdefault(fn, [])
         m = matches[rev][fn]
@@ -3352,39 +3366,33 @@  def grep(ui, repo, pattern, *pats, **opt
             iter = difflinestates(pstates, states)
         else:
             iter = [('', l) for l in states]
         for change, l in iter:
             cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
-            before, match, after = None, None, None
 
             if opts.get('line_number'):
                 cols.append((str(l.linenum), 'grep.linenumber'))
             if opts.get('all'):
                 cols.append((change, 'grep.change'))
             if opts.get('user'):
                 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
             if opts.get('date'):
                 cols.append((datefunc(ctx.date()), 'grep.date'))
-            if not opts.get('files_with_matches'):
-                before = l.line[:l.colstart]
-                match = l.line[l.colstart:l.colend]
-                after = l.line[l.colend:]
             for col, label in cols[:-1]:
                 ui.write(col, label=label)
                 ui.write(sep, label='grep.sep')
             ui.write(cols[-1][0], label=cols[-1][1])
-            if before is not None:
+            if not opts.get('files_with_matches'):
                 ui.write(sep, label='grep.sep')
                 if not opts.get('text') and binary():
                     ui.write(" Binary file matches")
                 else:
-                    ui.write(before)
-                    ui.write(match, label='grep.match')
-                    ui.write(after)
+                    for s, label in l:
+                        ui.write(s, label=label)
             ui.write(eol)
             found = True
-            if before is None:
+            if opts.get('files_with_matches'):
                 break
         return found
 
     skip = {}
     revfiles = {}
diff --git a/tests/test-grep.t b/tests/test-grep.t
--- a/tests/test-grep.t
+++ b/tests/test-grep.t
@@ -36,11 +36,11 @@  simple with color
 
   $ hg --config extensions.color= grep --config color.mode=ansi \
   >     --color=always port port
   \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m4\x1b[0m\x1b[0;36m:\x1b[0mex\x1b[0;31;1mport\x1b[0m (esc)
   \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m4\x1b[0m\x1b[0;36m:\x1b[0mva\x1b[0;31;1mport\x1b[0might (esc)
-  \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m4\x1b[0m\x1b[0;36m:\x1b[0mim\x1b[0;31;1mport\x1b[0m/export (esc)
+  \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m4\x1b[0m\x1b[0;36m:\x1b[0mim\x1b[0;31;1mport\x1b[0m/ex\x1b[0;31;1mport\x1b[0m (esc)
 
 all
 
   $ hg grep --traceback --all -nu port port
   port:4:4:-:spam:import/export