[PATCH 1 of 1 RESEND] color: add support for Windows consoles
Brodie Rao
dackze at gmail.com
Tue Apr 6 10:52:42 CDT 2010
On Apr 6, 2010, at 10:47 AM, steve at borho.org wrote:
> # HG changeset patch
> # User Steve Borho <steve at borho.org>
> # Date 1270561759 18000
> # Node ID 89c4c895bddc709c3f680dc0e07a73449608e2c8
> # Parent 06ede55eb9b0f0df9775b15291fd64d7b3255f76
> color: add support for Windows consoles
>
> Introduces ui.color configurable with values 'auto', 'ansi', or 'win32'. Any
> other value disables coloring. When 'auto' is selected, the win32 console
> method will be used if the win32console Python module is detected (requires
> pywin32 to be installed).
Why ui.color? Why not color.mode or color.format?
It also seems a little confusing considering there's also --color which takes auto, always, and never, but doesn't have anything to do with the output format.
>
> diff --git a/hgext/color.py b/hgext/color.py
> --- a/hgext/color.py
> +++ b/hgext/color.py
> @@ -150,19 +150,35 @@
> return ''.join(style(a, label) for a, label in _buffers.pop())
> return ''.join(a for a, label in _buffers.pop())
>
> +mode = 'ansi'
> def write(orig, *args, **opts):
> label = opts.get('label', '')
> global _buffers
> if _buffers:
> _buffers[-1].extend([(str(a), label) for a in args])
> + elif mode == 'win32':
> + for a in args:
> + win32print(a, orig, **opts)
> else:
> return orig(*[style(str(a), label) for a in args], **opts)
>
> def write_err(orig, *args, **opts):
> label = opts.get('label', '')
> - return orig(*[style(str(a), label) for a in args], **opts)
> + if mode == 'win32':
> + for a in args:
> + win32print(a, orig, **opts)
> + else:
> + return orig(*[style(str(a), label) for a in args], **opts)
>
> def uisetup(ui):
> + global mode
> + mode = ui.config('ui', 'color', 'auto')
> + if mode == 'auto':
> + mode = _w32effects and 'win32' or 'ansi'
What if someone's on win32 but is using an ANSI terminal?
> + if mode == 'win32':
> + _effects.update(_w32effects)
> + elif mode != 'ansi':
> + return
> def colorcmd(orig, ui_, opts, cmd, cmdfunc):
> if (opts['color'] == 'always' or
> (opts['color'] == 'auto' and (os.environ.get('TERM') != 'dumb'
> @@ -180,3 +196,64 @@
>
> commands.globalopts.append(('', 'color', 'auto',
> _("when to colorize (always, auto, or never)")))
> +
> +try:
> + import re
> + from win32console import *
> +
> + # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
> + _w32effects = {
> + 'none': 0,
> + 'black': 0,
> + 'red': FOREGROUND_RED,
> + 'green': FOREGROUND_GREEN,
> + 'yellow': FOREGROUND_RED | FOREGROUND_GREEN,
> + 'blue': FOREGROUND_BLUE,
> + 'magenta': FOREGROUND_BLUE | FOREGROUND_RED,
> + 'cyan': FOREGROUND_BLUE | FOREGROUND_GREEN,
> + 'white': FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
> + 'bold': FOREGROUND_INTENSITY,
> + 'black_background': 0,
> + 'red_background': BACKGROUND_RED,
> + 'green_background': BACKGROUND_GREEN,
> + 'blue_background': BACKGROUND_BLUE,
> + 'cyan_background': BACKGROUND_BLUE | BACKGROUND_GREEN,
> + 'bold_background': FOREGROUND_INTENSITY,
> + 'underline': COMMON_LVB_UNDERSCORE, # double-byte charsets only
> + 'inverse': COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
> + }
> +
> + stdout = GetStdHandle(STD_OUTPUT_HANDLE)
> + origattr = stdout.GetConsoleScreenBufferInfo()['Attributes']
> + ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)', re.MULTILINE | re.DOTALL)
> +
> + def win32print(text, orig, **opts):
> + label = opts.get('label', '')
> + attr = 0
> +
> + # determine console attributes based on labels
> + for l in label.split():
> + style = _styles.get(l, '')
> + for effect in style.split():
> + attr |= _w32effects[effect]
> +
> + # 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:
> + val = int(sattr)
> + attr = val and attr|val or 0
> + stdout.SetConsoleTextAttribute(attr or origattr)
> + orig(m.group(2), **opts)
> + m = re.match(ansire, m.group(3))
> +
> + # Explicity reset original attributes
> + stdout.SetConsoleTextAttribute(origattr)
> +
> +except ImportError:
> + _w32effects = None
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list