Patchwork [2,of,5] color: insert color code after every "\e[0m" (issue5413)

login
register
mail settings
Submitter Yuya Nishihara
Date March 18, 2017, 2:12 p.m.
Message ID <2ddc0cdf8a31d932ce76.1489846332@mimosa>
Download mbox | patch
Permalink /patch/19435/
State Accepted
Headers show

Comments

Yuya Nishihara - March 18, 2017, 2:12 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1489835475 -32400
#      Sat Mar 18 20:11:15 2017 +0900
# Node ID 2ddc0cdf8a31d932ce769396cf5bed3a4f840caa
# Parent  c2c07fbe795a863799630dd08a9418041b981c8b
color: insert color code after every "\e[0m" (issue5413)

This assumes the last color wins, tested in ANSI mode. I guess terminfo mode
would work in the same way.

Patch

diff --git a/mercurial/color.py b/mercurial/color.py
--- a/mercurial/color.py
+++ b/mercurial/color.py
@@ -296,6 +296,23 @@  def _effect_str(ui, effect):
     else:
         return curses.tparm(curses.tigetstr('setaf'), val)
 
+def _mergeeffects(text, start, stop):
+    """Insert start sequence at every occurrence of stop sequence
+
+    >>> s = _mergeeffects('cyan', '[C]', '|')
+    >>> s = _mergeeffects(s + 'yellow', '[Y]', '|')
+    >>> s = _mergeeffects('ma' + s + 'genta', '[M]', '|')
+    >>> s = _mergeeffects('red' + s, '[R]', '|')
+    >>> s
+    '[R]red[M]ma[Y][C]cyan|[R][M][Y]yellow|[R][M]genta|'
+    """
+    parts = []
+    for t in text.split(stop):
+        if not t:
+            continue
+        parts.extend([start, t, stop])
+    return ''.join(parts)
+
 def _render_effects(ui, text, effects):
     'Wrap text in commands to turn on each effect.'
     if not text:
@@ -308,7 +325,7 @@  def _render_effects(ui, text, effects):
         start = [str(_effects[e]) for e in ['none'] + effects.split()]
         start = '\033[' + ';'.join(start) + 'm'
         stop = '\033[' + str(_effects['none']) + 'm'
-    return ''.join([start, text, stop])
+    return _mergeeffects(text, start, stop)
 
 def colorlabel(ui, msg, label):
     """add color control code according to the mode"""
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -3348,6 +3348,12 @@  color effect can be specified without qu
   $ hg log --color=always -l 1 --template '{label(red, "text\n")}'
   \x1b[0;31mtext\x1b[0m (esc)
 
+color effects can be nested (issue5413)
+
+  $ hg debugtemplate --color=always \
+  > '{label(red, "red{label(magenta, "ma{label(cyan, "cyan")}{label(yellow, "yellow")}genta")}")}\n'
+  \x1b[0;31mred\x1b[0;35mma\x1b[0;36mcyan\x1b[0m\x1b[0;31m\x1b[0;35m\x1b[0;33myellow\x1b[0m\x1b[0;31m\x1b[0;35mgenta\x1b[0m (esc)
+
 label should be no-op if color is disabled:
 
   $ hg log --color=never -l 1 --template '{label(red, "text\n")}'
diff --git a/tests/test-doctest.py b/tests/test-doctest.py
--- a/tests/test-doctest.py
+++ b/tests/test-doctest.py
@@ -23,6 +23,7 @@  def testmod(name, optionflags=0, testtar
 
 testmod('mercurial.changegroup')
 testmod('mercurial.changelog')
+testmod('mercurial.color')
 testmod('mercurial.config')
 testmod('mercurial.dagparser', optionflags=doctest.NORMALIZE_WHITESPACE)
 testmod('mercurial.dispatch')