[PATCH] hgext/win32chcp: switches the console into an encoding actually used (issue2926)

Adrian Buehlmann adrian at cadifra.com
Fri Jul 29 11:51:16 CDT 2011


On 2011-07-29 01:47, Andrei Polushin wrote:
> # HG changeset patch
> # User Andrei Polushin <polushin at gmail.com>
> # Date 1311886282 -25200
> # Branch stable
> # Node ID 79b6058b58e93cd5b3edbd3340b1348e46e043a7
> # Parent  56848e2bb0c5a43b580dd2ca7ce1e781d4e75b2b
> hgext/win32chcp: switches the console into an encoding actually used (issue2926)
> 
> The encoding of the Windows console is switched temporarily, for the time the
> Mercurial is running, and restored to the previous value on exit.
> 
> This solution is backward compatible, it changes almost nothing, i.e. neither
> stdout/pipe encoding, nor internal string handling are affected anyway.
> For maximum compatibility, it is implemented as an optional extension.
> 
> One problem still remains: `hg log | more' doesn't produce readable output on
> OEM console, I've found no way to change the console encoding when redirected.
> 
> One problem possibly introduced: killing hg process may not restore previous
> console encoding. I'm unable to reproduce the problem, however.
> 
> diff -r 56848e2bb0c5 -r 79b6058b58e9 hgext/win32chcp.py
> --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
> +++ b/hgext/win32chcp.py	Fri Jul 29 03:51:22 2011 +0700
> @@ -0,0 +1,30 @@
> +# Copyright 2011 Andrei Polushin <polushin at gmail.com>
> +#
> +# This software may be used and distributed according to the terms of the
> +# GNU General Public License version 2 or any later version.
> +
> +'''switch the Windows console into an encoding actually used on output'''
> +
> +import os, codecs
> +from mercurial.i18n import _
> +from mercurial import osutil, encoding
> +
> +_cpaliases = {
> +    'utf-8': 'cp65001',
> +}
> +
> +def uisetup(ui):
> +    if os.name != 'nt':
> +        ui.warn(_("[win32chcp] is not supported on this platform.\n"))
> +        return
> +
> +    cp = encoding.encoding
> +    try:
> +        cp = codecs.lookup(cp).name
> +        cp = _cpaliases.get(cp, cp)
> +        if cp.startswith('cp'):
> +            cp = cp[2:]
> +        osutil.forceconsoleencoding(int(cp))
> +    except (LookupError, ValueError):
> +        ui.warn(_("[win32chcp] unrecognized encoding: %s.\n") % cp)
> +        pass

Can you try this? (requires no change in core):


import os, codecs, ctypes, atexit
from mercurial.i18n import _
from mercurial import encoding

_cpaliases = {
    'utf-8': 'cp65001',
}

_inputcp = 0
_outputcp = 0

def restoreconsoleencoding():
    _kernel32 = ctypes.windll.kernel32
    _kernel32.SetConsoleCP(_inputcp)
    _kernel32.SetConsoleOutputCP(_outputcp)

def forceconsoleencoding(cp):
    global _inputcp
    global _outputcp
    _kernel32 = ctypes.windll.kernel32
    _inputcp  = _kernel32.GetConsoleCP()
    _outputcp = _kernel32.GetConsoleOutputCP()
    _kernel32.SetConsoleCP(cp)
    _kernel32.SetConsoleOutputCP(cp)
    atexit.register(restoreconsoleencoding)

def uisetup(ui):
    if os.name != 'nt':
        ui.warn(_("[win32chcp] is not supported on this platform.\n"))
        return

    cp = encoding.encoding
    try:
        cp = codecs.lookup(cp).name
        cp = _cpaliases.get(cp, cp)
        if cp.startswith('cp'):
            cp = cp[2:]
        forceconsoleencoding(int(cp))
    except (LookupError, ValueError):
        ui.warn(_("[win32chcp] unrecognized encoding: %s.\n") % cp)
        pass


More information about the Mercurial-devel mailing list