Submitter | Yuya Nishihara |
---|---|
Date | March 18, 2017, 2:12 p.m. |
Message ID | <24aa1c6738157851268a.1489846335@mimosa> |
Download | mbox | patch |
Permalink | /patch/19438/ |
State | Accepted |
Headers | show |
Comments
On Sat, Mar 18, 2017 at 11:12:15PM +0900, Yuya Nishihara wrote: > # HG changeset patch > # User Yuya Nishihara <yuya@tcha.org> > # Date 1489838540 -32400 > # Sat Mar 18 21:02:20 2017 +0900 > # Node ID 24aa1c6738157851268a1c59fea1eb44cc9fdbae > # Parent 6b73f4d9380f6fc57cdbdfb42add4822a94f3960 > templater: make pad() strip color codes before computing width (issue5416) These are queued, many thanks. > > Tested in ANSI mode. We might have to extend _ansieffectre to support > terminfo mode. > > diff --git a/mercurial/color.py b/mercurial/color.py > --- a/mercurial/color.py > +++ b/mercurial/color.py > @@ -7,6 +7,8 @@ > > from __future__ import absolute_import > > +import re > + > from .i18n import _ > > from . import ( > @@ -327,6 +329,12 @@ def _render_effects(ui, text, effects): > stop = '\033[' + str(_effects['none']) + 'm' > return _mergeeffects(text, start, stop) > > +_ansieffectre = re.compile(br'\x1b\[[0-9;]*m') > + > +def stripeffects(text): > + """Strip ANSI control codes which could be inserted by colorlabel()""" > + return _ansieffectre.sub('', text) > + > def colorlabel(ui, msg, label): > """add color control code according to the mode""" > if ui._colormode == 'debug': > @@ -352,7 +360,6 @@ def colorlabel(ui, msg, label): > w32effects = None > if pycompat.osname == 'nt': > import ctypes > - import re > > _kernel32 = ctypes.windll.kernel32 > > diff --git a/mercurial/templater.py b/mercurial/templater.py > --- a/mercurial/templater.py > +++ b/mercurial/templater.py > @@ -13,6 +13,7 @@ import types > > from .i18n import _ > from . import ( > + color, > config, > encoding, > error, > @@ -576,13 +577,13 @@ def pad(context, mapping, args): > fillchar = ' ' > if len(args) > 2: > fillchar = evalstring(context, mapping, args[2]) > - if len(fillchar) != 1: > + if len(color.stripeffects(fillchar)) != 1: > # i18n: "pad" is a keyword > raise error.ParseError(_("pad() expects a single fill character")) > if len(args) > 3: > left = evalboolean(context, mapping, args[3]) > > - fillwidth = width - encoding.colwidth(text) > + fillwidth = width - encoding.colwidth(color.stripeffects(text)) > if fillwidth <= 0: > return text > if left: > 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 > @@ -3354,6 +3354,12 @@ color effects can be nested (issue5413) > > '{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) > > +pad() should interact well with color codes (issue5416) > + > + $ hg debugtemplate --color=always \ > + > '{pad(label(red, "red"), 5, label(cyan, "-"))}\n' > + \x1b[0;31mred\x1b[0m\x1b[0;36m-\x1b[0m\x1b[0;36m-\x1b[0m (esc) > + > label should be no-op if color is disabled: > > $ hg log --color=never -l 1 --template '{label(red, "text\n")}' > _______________________________________________ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Patch
diff --git a/mercurial/color.py b/mercurial/color.py --- a/mercurial/color.py +++ b/mercurial/color.py @@ -7,6 +7,8 @@ from __future__ import absolute_import +import re + from .i18n import _ from . import ( @@ -327,6 +329,12 @@ def _render_effects(ui, text, effects): stop = '\033[' + str(_effects['none']) + 'm' return _mergeeffects(text, start, stop) +_ansieffectre = re.compile(br'\x1b\[[0-9;]*m') + +def stripeffects(text): + """Strip ANSI control codes which could be inserted by colorlabel()""" + return _ansieffectre.sub('', text) + def colorlabel(ui, msg, label): """add color control code according to the mode""" if ui._colormode == 'debug': @@ -352,7 +360,6 @@ def colorlabel(ui, msg, label): w32effects = None if pycompat.osname == 'nt': import ctypes - import re _kernel32 = ctypes.windll.kernel32 diff --git a/mercurial/templater.py b/mercurial/templater.py --- a/mercurial/templater.py +++ b/mercurial/templater.py @@ -13,6 +13,7 @@ import types from .i18n import _ from . import ( + color, config, encoding, error, @@ -576,13 +577,13 @@ def pad(context, mapping, args): fillchar = ' ' if len(args) > 2: fillchar = evalstring(context, mapping, args[2]) - if len(fillchar) != 1: + if len(color.stripeffects(fillchar)) != 1: # i18n: "pad" is a keyword raise error.ParseError(_("pad() expects a single fill character")) if len(args) > 3: left = evalboolean(context, mapping, args[3]) - fillwidth = width - encoding.colwidth(text) + fillwidth = width - encoding.colwidth(color.stripeffects(text)) if fillwidth <= 0: return text if left: 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 @@ -3354,6 +3354,12 @@ color effects can be nested (issue5413) > '{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) +pad() should interact well with color codes (issue5416) + + $ hg debugtemplate --color=always \ + > '{pad(label(red, "red"), 5, label(cyan, "-"))}\n' + \x1b[0;31mred\x1b[0m\x1b[0;36m-\x1b[0m\x1b[0;36m-\x1b[0m (esc) + label should be no-op if color is disabled: $ hg log --color=never -l 1 --template '{label(red, "text\n")}'