diff -r 5ff1fc726848 -r c6bca38c1cbf eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/hgext/color.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/hgext/color.py Sat Jan 08 11:20:57 2011 +0530 @@ -0,0 +1,319 @@ +# color.py color output for the status and qseries commands +# +# Copyright (C) 2007 Kevin Christen +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +'''colorize output from some commands + +This extension modifies the status and resolve commands to add color to their +output to 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. + +Default effects may be overridden from your configuration file:: + + [color] + status.modified = blue bold underline red_background + status.added = green bold + status.removed = red bold blue_background + status.deleted = cyan bold underline + status.unknown = magenta bold underline + status.ignored = black bold + + # 'none' turns off all effects + status.clean = none + status.copied = none + + qseries.applied = blue bold underline + qseries.unapplied = black bold + qseries.missing = red bold + + diff.diffline = bold + diff.extended = cyan bold + diff.file_a = red bold + diff.file_b = green bold + diff.hunk = magenta + diff.deleted = red + diff.inserted = green + diff.changed = white + diff.trailingwhitespace = bold red_background + + resolve.unresolved = red bold + resolve.resolved = green bold + + bookmarks.current = green + + branches.active = none + branches.closed = black bold + branches.current = green + branches.inactive = none + +The color extension will try to detect whether to use ANSI codes or +Win32 console APIs, unless it is made explicit:: + + [color] + mode = ansi + +Any value other than 'ansi', 'win32', or 'auto' will disable color. + +''' + +import os + +from mercurial import commands, dispatch, extensions, ui as uimod, util +from mercurial.i18n import _ + +# start and stop parameters for effects +_effects = {'none': 0, 'black': 30, 'red': 31, 'green': 32, 'yellow': 33, + 'blue': 34, 'magenta': 35, 'cyan': 36, 'white': 37, 'bold': 1, + 'italic': 3, 'underline': 4, 'inverse': 7, + 'black_background': 40, 'red_background': 41, + 'green_background': 42, 'yellow_background': 43, + 'blue_background': 44, 'purple_background': 45, + 'cyan_background': 46, 'white_background': 47} + +_styles = {'grep.match': 'red bold', + 'branches.active': 'none', + 'branches.closed': 'black bold', + 'branches.current': 'green', + 'branches.inactive': 'none', + 'diff.changed': 'white', + 'diff.deleted': 'red', + 'diff.diffline': 'bold', + 'diff.extended': 'cyan bold', + 'diff.file_a': 'red bold', + 'diff.file_b': 'green bold', + 'diff.hunk': 'magenta', + 'diff.inserted': 'green', + 'diff.trailingwhitespace': 'bold red_background', + 'diffstat.deleted': 'red', + 'diffstat.inserted': 'green', + 'log.changeset': 'yellow', + 'resolve.resolved': 'green bold', + 'resolve.unresolved': 'red bold', + 'status.added': 'green bold', + 'status.clean': 'none', + 'status.copied': 'none', + 'status.deleted': 'cyan bold underline', + 'status.ignored': 'black bold', + 'status.modified': 'blue bold', + 'status.removed': 'red bold', + 'status.unknown': 'magenta bold underline'} + + +def render_effects(text, effects): + 'Wrap text in commands to turn on each effect.' + if not text: + return text + 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]) + +def extstyles(): + for name, ext in extensions.extensions(): + _styles.update(getattr(ext, 'colortable', {})) + +def configstyles(ui): + for status, cfgeffects in ui.configitems('color'): + if '.' not in status: + continue + cfgeffects = ui.configlist('color', status) + if cfgeffects: + good = [] + for e in cfgeffects: + if e in _effects: + good.append(e) + else: + ui.warn(_("ignoring unknown color/effect %r " + "(configured in color.%s)\n") + % (e, status)) + _styles[status] = ' '.join(good) + +class colorui(uimod.ui): + def popbuffer(self, labeled=False): + if labeled: + return ''.join(self.label(a, label) for a, label + in self._buffers.pop()) + return ''.join(a for a, label in self._buffers.pop()) + + _colormode = 'ansi' + def write(self, *args, **opts): + label = opts.get('label', '') + if self._buffers: + self._buffers[-1].extend([(str(a), label) for a in args]) + elif self._colormode == 'win32': + for a in args: + win32print(a, super(colorui, self).write, **opts) + else: + return super(colorui, self).write( + *[self.label(str(a), label) for a in args], **opts) + + def write_err(self, *args, **opts): + label = opts.get('label', '') + if self._colormode == 'win32': + for a in args: + win32print(a, super(colorui, self).write_err, **opts) + else: + return super(colorui, self).write_err( + *[self.label(str(a), label) for a in args], **opts) + + def label(self, msg, label): + effects = [] + for l in label.split(): + s = _styles.get(l, '') + if s: + effects.append(s) + effects = ''.join(effects) + if effects: + return '\n'.join([render_effects(s, effects) + for s in msg.split('\n')]) + return msg + + +def uisetup(ui): + if ui.plain(): + return + mode = ui.config('color', 'mode', 'auto') + if mode == 'auto': + if os.name == 'nt' and 'TERM' not in os.environ: + # looks line a cmd.exe console, use win32 API or nothing + mode = w32effects and 'win32' or 'none' + else: + mode = 'ansi' + if mode == 'win32': + if w32effects is None: + # only warn if color.mode is explicitly set to win32 + ui.warn(_('win32console not found, please install pywin32\n')) + return + _effects.update(w32effects) + elif mode != 'ansi': + return + def colorcmd(orig, ui_, opts, cmd, cmdfunc): + coloropt = opts['color'] + auto = coloropt == 'auto' + always = util.parsebool(coloropt) + if (always or + (always is None and + (auto and (os.environ.get('TERM') != 'dumb' and ui_.formatted())))): + colorui._colormode = mode + colorui.__bases__ = (ui_.__class__,) + ui_.__class__ = colorui + extstyles() + configstyles(ui_) + return orig(ui_, opts, cmd, cmdfunc) + extensions.wrapfunction(dispatch, '_runcommand', colorcmd) + +def extsetup(ui): + commands.globalopts.append( + ('', 'color', 'auto', + # i18n: 'always', 'auto', and 'never' are keywords and should + # not be translated + _("when to colorize (boolean, always, auto, or never)"), + _('TYPE'))) + +try: + import re, pywintypes, win32console as win32c + + # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx + w32effects = { + 'none': -1, + 'black': 0, + 'red': win32c.FOREGROUND_RED, + 'green': win32c.FOREGROUND_GREEN, + 'yellow': win32c.FOREGROUND_RED | win32c.FOREGROUND_GREEN, + 'blue': win32c.FOREGROUND_BLUE, + 'magenta': win32c.FOREGROUND_BLUE | win32c.FOREGROUND_RED, + 'cyan': win32c.FOREGROUND_BLUE | win32c.FOREGROUND_GREEN, + 'white': (win32c.FOREGROUND_RED | win32c.FOREGROUND_GREEN | + win32c.FOREGROUND_BLUE), + 'bold': win32c.FOREGROUND_INTENSITY, + 'black_background': 0x100, # unused value > 0x0f + 'red_background': win32c.BACKGROUND_RED, + 'green_background': win32c.BACKGROUND_GREEN, + 'yellow_background': win32c.BACKGROUND_RED | win32c.BACKGROUND_GREEN, + 'blue_background': win32c.BACKGROUND_BLUE, + 'purple_background': win32c.BACKGROUND_BLUE | win32c.BACKGROUND_RED, + 'cyan_background': win32c.BACKGROUND_BLUE | win32c.BACKGROUND_GREEN, + 'white_background': (win32c.BACKGROUND_RED | win32c.BACKGROUND_GREEN | + win32c.BACKGROUND_BLUE), + 'bold_background': win32c.BACKGROUND_INTENSITY, + 'underline': win32c.COMMON_LVB_UNDERSCORE, # double-byte charsets only + 'inverse': win32c.COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only + } + + passthrough = set([win32c.FOREGROUND_INTENSITY, + win32c.BACKGROUND_INTENSITY, + win32c.COMMON_LVB_UNDERSCORE, + win32c.COMMON_LVB_REVERSE_VIDEO]) + + try: + stdout = win32c.GetStdHandle(win32c.STD_OUTPUT_HANDLE) + if stdout is None: + raise ImportError() + origattr = stdout.GetConsoleScreenBufferInfo()['Attributes'] + except pywintypes.error: + # stdout may be defined but not support + # GetConsoleScreenBufferInfo(), when called from subprocess or + # redirected. + raise ImportError() + ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)', re.MULTILINE | re.DOTALL) + + def win32print(text, orig, **opts): + label = opts.get('label', '') + attr = origattr + + def mapcolor(val, attr): + if val == -1: + return origattr + elif val in passthrough: + return attr | val + elif val > 0x0f: + return (val & 0x70) | (attr & 0x8f) + else: + return (val & 0x07) | (attr & 0xf8) + + # determine console attributes based on labels + for l in label.split(): + style = _styles.get(l, '') + for effect in style.split(): + attr = mapcolor(w32effects[effect], attr) + + # hack to ensure regexp finds data + if not text.startswith('\033['): + text = '\033[m' + text + + # Look for ANSI-like codes embedded in text + m = re.match(ansire, text) + while m: + for sattr in m.group(1).split(';'): + if sattr: + attr = mapcolor(int(sattr), attr) + stdout.SetConsoleTextAttribute(attr) + orig(m.group(2), **opts) + m = re.match(ansire, m.group(3)) + + # Explicity reset original attributes + stdout.SetConsoleTextAttribute(origattr) + +except ImportError: + w32effects = None