[PATCH 1 of 3] color: diff colorization

Brodie Rao dackze at gmail.com
Wed Nov 12 18:10:19 CST 2008


# HG changeset patch
# User Brodie Rao <me+hg at dackz.net>
# Date 1226534479 18000
# Node ID 746c643d0ff6ee7f10ecc7039ebf0f7332b27c77
# Parent  b0fa5dbd9cdd7e6caaa07c5b2acd42465e3c1298
color: diff colorization

This colorizes diff, qdiff, log -p, outgoing -p, and incoming -p.

diff -r b0fa5dbd9cdd -r 746c643d0ff6 hgext/color.py
--- a/hgext/color.py	Wed Nov 12 19:12:32 2008 +0100
+++ b/hgext/color.py	Wed Nov 12 19:01:19 2008 -0500
@@ -16,15 +16,16 @@
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-'''add color output to the status and qseries commands
+'''add color output to status, qseries, and diff-related commands
 
 This extension modifies the status command to add color to its output to
-reflect file status, and the qseries command to add color to reflect patch
-status (applied, unapplied, missing).  Other effects in addition to color,
-like bold and underlined text, are also available.  Effects are rendered
-with the ECMA-48 SGR control function (aka ANSI escape codes).  This module
-also provides the render_text function, which can be used to add effects to
-any text.
+reflect file status, the qseries command to add color to reflect patch status
+(applied, unapplied, missing), and to diff-related commands to highlight
+additions, removals, diff headers, and trailing whitespace.  Other effects in
+addition to color, like bold and underlined text, are also available.
+Effects are rendered with the ECMA-48 SGR control function (aka ANSI escape
+codes).  This module also provides the render_text function, which can be
+used to add effects to any text.
 
 To enable this extension, add this to your .hgrc file:
 [extensions]
@@ -47,6 +48,12 @@
 qseries.applied = blue bold underline
 qseries.unapplied = black bold
 qseries.missing = red bold
+
+diff.head = bold
+diff.group = magenta bold
+diff.del = red bold
+diff.ins = green
+diff.whitespace = bold red_background
 '''
 
 import re, sys
@@ -166,12 +173,59 @@
                    'missing': ('red', 'bold'),
                    'unapplied': ('black', 'bold'), }
 
+def colordiff(orig, ui, repo, *dummy, **opts):
+    '''run diff-related commands with colored output'''
+
+    from mercurial.commands import incoming, log, outgoing
+    if orig in (incoming, log, outgoing) and not opts['patch']:
+        return orig(ui, repo, *dummy, **opts)
+
+    # This assumes that ui.write is called only with full lines (which is
+    # currently the case).
+    def wrapper(orig, s):
+        lines = s.split('\n')
+        for i, line in enumerate(lines):
+            if line.startswith('diff'):
+                lines[i] = render_effects(line, *_diff_effects['head'])
+            elif line.startswith('@@'):
+                lines[i] = render_effects(line, *_diff_effects['group'])
+            elif line and line[0] in ('-', '+'):
+                # Highlight trailing whitespace (unconditionally)
+                rline = line.rstrip()
+                if line != rline:
+                    pos = len(rline)
+                    line = ''.join([line[:pos],
+                        render_effects(line[pos:],
+                                       *_diff_effects['whitespace'])])
+                if line[0] == '-':
+                    lines[i] = render_effects(line, *_diff_effects['del'])
+                else:
+                    lines[i] = render_effects(line, *_diff_effects['ins'])
+        orig('\n'.join(lines))
+
+    old_write = extensions.wrapfunction(ui, 'write', wrapper)
+    try:
+        orig(ui, repo, *dummy, **opts)
+    finally:
+        ui.write = old_write
+
+_diff_effects = { 'head': ('bold', ),
+                  'group': ('magenta', 'bold'),
+                  'del': ('red', 'bold'),
+                  'ins': ('green', ),
+                  'whitespace': ('bold', 'red_background'), }
+
 def uisetup(ui):
     '''Initialize the extension.'''
+    _setupcmd(ui, 'diff', commands.table, colordiff, _diff_effects)
+    _setupcmd(ui, 'incoming', commands.table, colordiff, _diff_effects)
+    _setupcmd(ui, 'log', commands.table, colordiff, _diff_effects)
+    _setupcmd(ui, 'outgoing', commands.table, colordiff, _diff_effects)
     _setupcmd(ui, 'status', commands.table, colorstatus, _status_effects)
     if ui.config('extensions', 'hgext.mq') is not None or \
             ui.config('extensions', 'mq') is not None:
         from hgext import mq
+        _setupcmd(ui, 'qdiff', mq.cmdtable, colordiff, _diff_effects)
         _setupcmd(ui, 'qseries', mq.cmdtable, colorqseries, _patch_effects)
 
 def _setupcmd(ui, cmd, table, func, effectsmap):


More information about the Mercurial-devel mailing list