Revert "Include initial use of colorama"
Crashes. git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@106709 0039d316-1c4b-4281-b951-d872f2087c98experimental/szager/collated-output
parent
037bd18864
commit
d8aba2cea8
@ -1,33 +0,0 @@
|
|||||||
Copyright (c) 2010 Jonathan Hartley <tartley@tartley.com>
|
|
||||||
|
|
||||||
Released under the New BSD license (reproduced below), or alternatively you may
|
|
||||||
use this software under any OSI approved open source license such as those at
|
|
||||||
http://opensource.org/licenses/alphabetical
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name(s) of the copyright holders, nor those of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
|||||||
Name: colorama
|
|
||||||
URL: http://code.google.com/p/colorama
|
|
||||||
Version: 2.3 + c25659277b30
|
|
||||||
Revision: c25659277b30
|
|
||||||
|
|
||||||
Description:
|
|
||||||
Provides a simple cross-platform API to print colored terminal text from Python
|
|
||||||
applications.
|
|
||||||
|
|
||||||
LICENSE.txt is the license file copied from upstream.
|
|
@ -1,264 +0,0 @@
|
|||||||
Download and docs:
|
|
||||||
http://pypi.python.org/pypi/colorama
|
|
||||||
Development:
|
|
||||||
http://code.google.com/p/colorama
|
|
||||||
|
|
||||||
Description
|
|
||||||
===========
|
|
||||||
|
|
||||||
Makes ANSI escape character sequences, for producing colored terminal text and
|
|
||||||
cursor positioning, work under MS Windows.
|
|
||||||
|
|
||||||
ANSI escape character sequences have long been used to produce colored terminal
|
|
||||||
text and cursor positioning on Unix and Macs. Colorama makes this work on
|
|
||||||
Windows, too. It also provides some shortcuts to help generate ANSI sequences,
|
|
||||||
and works fine in conjunction with any other ANSI sequence generation library,
|
|
||||||
such as Termcolor (http://pypi.python.org/pypi/termcolor.)
|
|
||||||
|
|
||||||
This has the upshot of providing a simple cross-platform API for printing
|
|
||||||
colored terminal text from Python, and has the happy side-effect that existing
|
|
||||||
applications or libraries which use ANSI sequences to produce colored output on
|
|
||||||
Linux or Macs can now also work on Windows, simply by calling
|
|
||||||
``colorama.init()``.
|
|
||||||
|
|
||||||
Demo scripts in the source code repository prints some colored text using
|
|
||||||
ANSI sequences. Compare their output under Gnome-terminal's built in ANSI
|
|
||||||
handling, versus on Windows Command-Prompt using Colorama:
|
|
||||||
|
|
||||||
.. image:: http://colorama.googlecode.com/hg/screenshots/ubuntu-demo.png
|
|
||||||
:width: 661
|
|
||||||
:height: 357
|
|
||||||
:alt: ANSI sequences on Ubuntu under gnome-terminal.
|
|
||||||
|
|
||||||
.. image:: http://colorama.googlecode.com/hg/screenshots/windows-demo.png
|
|
||||||
:width: 668
|
|
||||||
:height: 325
|
|
||||||
:alt: Same ANSI sequences on Windows, using Colorama.
|
|
||||||
|
|
||||||
These screengrabs show that Colorama on Windows does not support ANSI 'dim
|
|
||||||
text': it looks the same as 'normal text'.
|
|
||||||
|
|
||||||
|
|
||||||
Dependencies
|
|
||||||
============
|
|
||||||
|
|
||||||
None, other than Python. Tested on Python 2.5.5, 2.6.5, 2.7, 3.1.2, and 3.2
|
|
||||||
|
|
||||||
|
|
||||||
Usage
|
|
||||||
=====
|
|
||||||
|
|
||||||
Initialisation
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Applications should initialise Colorama using::
|
|
||||||
|
|
||||||
from colorama import init
|
|
||||||
init()
|
|
||||||
|
|
||||||
If you are on Windows, the call to ``init()`` will start filtering ANSI escape
|
|
||||||
sequences out of any text sent to stdout or stderr, and will replace them with
|
|
||||||
equivalent Win32 calls.
|
|
||||||
|
|
||||||
Calling ``init()`` has no effect on other platforms (unless you request other
|
|
||||||
optional functionality, see keyword args below.) The intention is that
|
|
||||||
applications can call ``init()`` unconditionally on all platforms, after which
|
|
||||||
ANSI output should just work.
|
|
||||||
|
|
||||||
To stop using colorama before your program exits, simply call ``deinit()``.
|
|
||||||
This will restore stdout and stderr to their original values, so that Colorama
|
|
||||||
is disabled. To start using Colorama again, call ``reinit()``, which wraps
|
|
||||||
stdout and stderr again, but is cheaper to call than doing ``init()`` all over
|
|
||||||
again.
|
|
||||||
|
|
||||||
|
|
||||||
Colored Output
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Cross-platform printing of colored text can then be done using Colorama's
|
|
||||||
constant shorthand for ANSI escape sequences::
|
|
||||||
|
|
||||||
from colorama import Fore, Back, Style
|
|
||||||
print Fore.RED + 'some red text'
|
|
||||||
print Back.GREEN + and with a green background'
|
|
||||||
print Style.DIM + 'and in dim text'
|
|
||||||
print + Fore.RESET + Back.RESET + Style.RESET_ALL
|
|
||||||
print 'back to normal now'
|
|
||||||
|
|
||||||
or simply by manually printing ANSI sequences from your own code::
|
|
||||||
|
|
||||||
print '/033[31m' + 'some red text'
|
|
||||||
print '/033[30m' # and reset to default color
|
|
||||||
|
|
||||||
or Colorama can be used happily in conjunction with existing ANSI libraries
|
|
||||||
such as Termcolor::
|
|
||||||
|
|
||||||
from colorama import init
|
|
||||||
from termcolor import colored
|
|
||||||
|
|
||||||
# use Colorama to make Termcolor work on Windows too
|
|
||||||
init()
|
|
||||||
|
|
||||||
# then use Termcolor for all colored text output
|
|
||||||
print colored('Hello, World!', 'green', 'on_red')
|
|
||||||
|
|
||||||
Available formatting constants are::
|
|
||||||
|
|
||||||
Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
|
|
||||||
Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
|
|
||||||
Style: DIM, NORMAL, BRIGHT, RESET_ALL
|
|
||||||
|
|
||||||
Style.RESET_ALL resets foreground, background and brightness. Colorama will
|
|
||||||
perform this reset automatically on program exit.
|
|
||||||
|
|
||||||
|
|
||||||
Cursor Positioning
|
|
||||||
------------------
|
|
||||||
|
|
||||||
ANSI codes to reposition the cursor are supported. See demos/demo06.py for
|
|
||||||
an example of how to generate them.
|
|
||||||
|
|
||||||
|
|
||||||
Init Keyword Args
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
``init()`` accepts some kwargs to override default behaviour.
|
|
||||||
|
|
||||||
init(autoreset=False):
|
|
||||||
If you find yourself repeatedly sending reset sequences to turn off color
|
|
||||||
changes at the end of every print, then ``init(autoreset=True)`` will
|
|
||||||
automate that::
|
|
||||||
|
|
||||||
from colorama import init
|
|
||||||
init(autoreset=True)
|
|
||||||
print Fore.RED + 'some red text'
|
|
||||||
print 'automatically back to default color again'
|
|
||||||
|
|
||||||
init(strip=None):
|
|
||||||
Pass ``True`` or ``False`` to override whether ansi codes should be
|
|
||||||
stripped from the output. The default behaviour is to strip if on Windows.
|
|
||||||
|
|
||||||
init(convert=None):
|
|
||||||
Pass ``True`` or ``False`` to override whether to convert ansi codes in the
|
|
||||||
output into win32 calls. The default behaviour is to convert if on Windows
|
|
||||||
and output is to a tty (terminal).
|
|
||||||
|
|
||||||
init(wrap=True):
|
|
||||||
On Windows, colorama works by replacing ``sys.stdout`` and ``sys.stderr``
|
|
||||||
with proxy objects, which override the .write() method to do their work. If
|
|
||||||
this wrapping causes you problems, then this can be disabled by passing
|
|
||||||
``init(wrap=False)``. The default behaviour is to wrap if autoreset or
|
|
||||||
strip or convert are True.
|
|
||||||
|
|
||||||
When wrapping is disabled, colored printing on non-Windows platforms will
|
|
||||||
continue to work as normal. To do cross-platform colored output, you can
|
|
||||||
use Colorama's ``AnsiToWin32`` proxy directly::
|
|
||||||
|
|
||||||
from colorama import init, AnsiToWin32
|
|
||||||
init(wrap=False)
|
|
||||||
stream = AnsiToWin32(sys.stderr).stream
|
|
||||||
print >>stream, Fore.BLUE + 'blue text on stderr'
|
|
||||||
|
|
||||||
|
|
||||||
Status & Known Problems
|
|
||||||
=======================
|
|
||||||
|
|
||||||
I've personally only tested it on WinXP (CMD, Console2) and Ubuntu
|
|
||||||
(gnome-terminal, xterm), although it sounds like others are using it on other
|
|
||||||
platforms too.
|
|
||||||
|
|
||||||
See outstanding issues and wishlist at:
|
|
||||||
http://code.google.com/p/colorama/issues/list
|
|
||||||
|
|
||||||
If anything doesn't work for you, or doesn't do what you expected or hoped for,
|
|
||||||
I'd *love* to hear about it on that issues list.
|
|
||||||
|
|
||||||
|
|
||||||
Recognised ANSI Sequences
|
|
||||||
=========================
|
|
||||||
|
|
||||||
ANSI sequences generally take the form:
|
|
||||||
|
|
||||||
ESC [ <param> ; <param> ... <command>
|
|
||||||
|
|
||||||
Where <param> is an integer, and <command> is a single letter. Zero or more
|
|
||||||
params are passed to a <command>. If no params are passed, it is generally
|
|
||||||
synonymous with passing a single zero. No spaces exist in the sequence, they
|
|
||||||
have just been inserted here to make it easy to read.
|
|
||||||
|
|
||||||
The only ANSI sequences that colorama converts into win32 calls are::
|
|
||||||
|
|
||||||
ESC [ 0 m # reset all (colors and brightness)
|
|
||||||
ESC [ 1 m # bright
|
|
||||||
ESC [ 2 m # dim (looks same as normal brightness)
|
|
||||||
ESC [ 22 m # normal brightness
|
|
||||||
|
|
||||||
# FOREGROUND:
|
|
||||||
ESC [ 30 m # black
|
|
||||||
ESC [ 31 m # red
|
|
||||||
ESC [ 32 m # green
|
|
||||||
ESC [ 33 m # yellow
|
|
||||||
ESC [ 34 m # blue
|
|
||||||
ESC [ 35 m # magenta
|
|
||||||
ESC [ 36 m # cyan
|
|
||||||
ESC [ 37 m # white
|
|
||||||
ESC [ 39 m # reset
|
|
||||||
|
|
||||||
# BACKGROUND
|
|
||||||
ESC [ 40 m # black
|
|
||||||
ESC [ 41 m # red
|
|
||||||
ESC [ 42 m # green
|
|
||||||
ESC [ 43 m # yellow
|
|
||||||
ESC [ 44 m # blue
|
|
||||||
ESC [ 45 m # magenta
|
|
||||||
ESC [ 46 m # cyan
|
|
||||||
ESC [ 47 m # white
|
|
||||||
ESC [ 49 m # reset
|
|
||||||
|
|
||||||
# cursor positioning
|
|
||||||
ESC [ x;y H # position cursor at x,y
|
|
||||||
|
|
||||||
# clear the screen
|
|
||||||
ESC [ mode J # clear the screen. Only mode 2 (clear entire screen)
|
|
||||||
# is supported. It should be easy to add other modes,
|
|
||||||
# let me know if that would be useful.
|
|
||||||
|
|
||||||
Multiple numeric params to the 'm' command can be combined into a single
|
|
||||||
sequence, eg::
|
|
||||||
|
|
||||||
ESC [ 36 ; 45 ; 1 m # bright cyan text on magenta background
|
|
||||||
|
|
||||||
All other ANSI sequences of the form ``ESC [ <param> ; <param> ... <command>``
|
|
||||||
are silently stripped from the output on Windows.
|
|
||||||
|
|
||||||
Any other form of ANSI sequence, such as single-character codes or alternative
|
|
||||||
initial characters, are not recognised nor stripped. It would be cool to add
|
|
||||||
them though. Let me know if it would be useful for you, via the issues on
|
|
||||||
google code.
|
|
||||||
|
|
||||||
|
|
||||||
Development
|
|
||||||
===========
|
|
||||||
|
|
||||||
Running tests requires:
|
|
||||||
|
|
||||||
- Michael Foord's 'mock' module to be installed.
|
|
||||||
- Tests are written using the 2010 era updates to 'unittest', and require to
|
|
||||||
be run either using Python2.7 or greater, or else to have Michael Foord's
|
|
||||||
'unittest2' module installed.
|
|
||||||
|
|
||||||
unittest2 test discovery doesn't work for colorama, so I use 'nose'::
|
|
||||||
|
|
||||||
nosetests -s
|
|
||||||
|
|
||||||
The -s is required because 'nosetests' otherwise applies a proxy of its own to
|
|
||||||
stdout, which confuses the unit tests.
|
|
||||||
|
|
||||||
|
|
||||||
Thanks
|
|
||||||
======
|
|
||||||
Daniel Griffith for multiple fabulous patches.
|
|
||||||
Oscar Lesta for valuable fix to stop ANSI chars being sent to non-tty output.
|
|
||||||
Roger Binns, for many suggestions, valuable feedback, & bug reports.
|
|
||||||
Tim Golden for thought and much appreciated feedback on the initial idea.
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
|||||||
from .initialise import init, deinit, reinit
|
|
||||||
from .ansi import Fore, Back, Style
|
|
||||||
from .ansitowin32 import AnsiToWin32
|
|
||||||
|
|
||||||
VERSION = '0.2.4'
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
|||||||
'''
|
|
||||||
This module generates ANSI character codes to printing colors to terminals.
|
|
||||||
See: http://en.wikipedia.org/wiki/ANSI_escape_code
|
|
||||||
'''
|
|
||||||
|
|
||||||
CSI = '\033['
|
|
||||||
|
|
||||||
def code_to_chars(code):
|
|
||||||
return CSI + str(code) + 'm'
|
|
||||||
|
|
||||||
class AnsiCodes(object):
|
|
||||||
def __init__(self, codes):
|
|
||||||
for name in dir(codes):
|
|
||||||
if not name.startswith('_'):
|
|
||||||
value = getattr(codes, name)
|
|
||||||
setattr(self, name, code_to_chars(value))
|
|
||||||
|
|
||||||
class AnsiFore:
|
|
||||||
BLACK = 30
|
|
||||||
RED = 31
|
|
||||||
GREEN = 32
|
|
||||||
YELLOW = 33
|
|
||||||
BLUE = 34
|
|
||||||
MAGENTA = 35
|
|
||||||
CYAN = 36
|
|
||||||
WHITE = 37
|
|
||||||
RESET = 39
|
|
||||||
|
|
||||||
class AnsiBack:
|
|
||||||
BLACK = 40
|
|
||||||
RED = 41
|
|
||||||
GREEN = 42
|
|
||||||
YELLOW = 43
|
|
||||||
BLUE = 44
|
|
||||||
MAGENTA = 45
|
|
||||||
CYAN = 46
|
|
||||||
WHITE = 47
|
|
||||||
RESET = 49
|
|
||||||
|
|
||||||
class AnsiStyle:
|
|
||||||
BRIGHT = 1
|
|
||||||
DIM = 2
|
|
||||||
NORMAL = 22
|
|
||||||
RESET_ALL = 0
|
|
||||||
|
|
||||||
Fore = AnsiCodes( AnsiFore )
|
|
||||||
Back = AnsiCodes( AnsiBack )
|
|
||||||
Style = AnsiCodes( AnsiStyle )
|
|
||||||
|
|
@ -1,189 +0,0 @@
|
|||||||
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style
|
|
||||||
from .winterm import WinTerm, WinColor, WinStyle
|
|
||||||
from .win32 import windll
|
|
||||||
|
|
||||||
|
|
||||||
if windll is not None:
|
|
||||||
winterm = WinTerm()
|
|
||||||
|
|
||||||
|
|
||||||
def is_a_tty(stream):
|
|
||||||
return hasattr(stream, 'isatty') and stream.isatty()
|
|
||||||
|
|
||||||
|
|
||||||
class StreamWrapper(object):
|
|
||||||
'''
|
|
||||||
Wraps a stream (such as stdout), acting as a transparent proxy for all
|
|
||||||
attribute access apart from method 'write()', which is delegated to our
|
|
||||||
Converter instance.
|
|
||||||
'''
|
|
||||||
def __init__(self, wrapped, converter):
|
|
||||||
# double-underscore everything to prevent clashes with names of
|
|
||||||
# attributes on the wrapped stream object.
|
|
||||||
self.__wrapped = wrapped
|
|
||||||
self.__convertor = converter
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
|
||||||
return getattr(self.__wrapped, name)
|
|
||||||
|
|
||||||
def write(self, text):
|
|
||||||
self.__convertor.write(text)
|
|
||||||
|
|
||||||
|
|
||||||
class AnsiToWin32(object):
|
|
||||||
'''
|
|
||||||
Implements a 'write()' method which, on Windows, will strip ANSI character
|
|
||||||
sequences from the text, and if outputting to a tty, will convert them into
|
|
||||||
win32 function calls.
|
|
||||||
'''
|
|
||||||
ANSI_RE = re.compile('\033\[((?:\d|;)*)([a-zA-Z])')
|
|
||||||
|
|
||||||
def __init__(self, wrapped, convert=None, strip=None, autoreset=False):
|
|
||||||
# The wrapped stream (normally sys.stdout or sys.stderr)
|
|
||||||
self.wrapped = wrapped
|
|
||||||
|
|
||||||
# should we reset colors to defaults after every .write()
|
|
||||||
self.autoreset = autoreset
|
|
||||||
|
|
||||||
# create the proxy wrapping our output stream
|
|
||||||
self.stream = StreamWrapper(wrapped, self)
|
|
||||||
|
|
||||||
on_windows = sys.platform.startswith('win')
|
|
||||||
|
|
||||||
# should we strip ANSI sequences from our output?
|
|
||||||
if strip is None:
|
|
||||||
strip = on_windows
|
|
||||||
self.strip = strip
|
|
||||||
|
|
||||||
# should we should convert ANSI sequences into win32 calls?
|
|
||||||
if convert is None:
|
|
||||||
convert = on_windows and is_a_tty(wrapped)
|
|
||||||
self.convert = convert
|
|
||||||
|
|
||||||
# dict of ansi codes to win32 functions and parameters
|
|
||||||
self.win32_calls = self.get_win32_calls()
|
|
||||||
|
|
||||||
# are we wrapping stderr?
|
|
||||||
self.on_stderr = self.wrapped is sys.stderr
|
|
||||||
|
|
||||||
|
|
||||||
def should_wrap(self):
|
|
||||||
'''
|
|
||||||
True if this class is actually needed. If false, then the output
|
|
||||||
stream will not be affected, nor will win32 calls be issued, so
|
|
||||||
wrapping stdout is not actually required. This will generally be
|
|
||||||
False on non-Windows platforms, unless optional functionality like
|
|
||||||
autoreset has been requested using kwargs to init()
|
|
||||||
'''
|
|
||||||
return self.convert or self.strip or self.autoreset
|
|
||||||
|
|
||||||
|
|
||||||
def get_win32_calls(self):
|
|
||||||
if self.convert and winterm:
|
|
||||||
return {
|
|
||||||
AnsiStyle.RESET_ALL: (winterm.reset_all, ),
|
|
||||||
AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT),
|
|
||||||
AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL),
|
|
||||||
AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL),
|
|
||||||
AnsiFore.BLACK: (winterm.fore, WinColor.BLACK),
|
|
||||||
AnsiFore.RED: (winterm.fore, WinColor.RED),
|
|
||||||
AnsiFore.GREEN: (winterm.fore, WinColor.GREEN),
|
|
||||||
AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW),
|
|
||||||
AnsiFore.BLUE: (winterm.fore, WinColor.BLUE),
|
|
||||||
AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA),
|
|
||||||
AnsiFore.CYAN: (winterm.fore, WinColor.CYAN),
|
|
||||||
AnsiFore.WHITE: (winterm.fore, WinColor.GREY),
|
|
||||||
AnsiFore.RESET: (winterm.fore, ),
|
|
||||||
AnsiBack.BLACK: (winterm.back, WinColor.BLACK),
|
|
||||||
AnsiBack.RED: (winterm.back, WinColor.RED),
|
|
||||||
AnsiBack.GREEN: (winterm.back, WinColor.GREEN),
|
|
||||||
AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW),
|
|
||||||
AnsiBack.BLUE: (winterm.back, WinColor.BLUE),
|
|
||||||
AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA),
|
|
||||||
AnsiBack.CYAN: (winterm.back, WinColor.CYAN),
|
|
||||||
AnsiBack.WHITE: (winterm.back, WinColor.GREY),
|
|
||||||
AnsiBack.RESET: (winterm.back, ),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def write(self, text):
|
|
||||||
if self.strip or self.convert:
|
|
||||||
self.write_and_convert(text)
|
|
||||||
else:
|
|
||||||
self.wrapped.write(text)
|
|
||||||
self.wrapped.flush()
|
|
||||||
if self.autoreset:
|
|
||||||
self.reset_all()
|
|
||||||
|
|
||||||
|
|
||||||
def reset_all(self):
|
|
||||||
if self.convert:
|
|
||||||
self.call_win32('m', (0,))
|
|
||||||
elif is_a_tty(self.wrapped):
|
|
||||||
self.wrapped.write(Style.RESET_ALL)
|
|
||||||
|
|
||||||
|
|
||||||
def write_and_convert(self, text):
|
|
||||||
'''
|
|
||||||
Write the given text to our wrapped stream, stripping any ANSI
|
|
||||||
sequences from the text, and optionally converting them into win32
|
|
||||||
calls.
|
|
||||||
'''
|
|
||||||
cursor = 0
|
|
||||||
for match in self.ANSI_RE.finditer(text):
|
|
||||||
start, end = match.span()
|
|
||||||
self.write_plain_text(text, cursor, start)
|
|
||||||
self.convert_ansi(*match.groups())
|
|
||||||
cursor = end
|
|
||||||
self.write_plain_text(text, cursor, len(text))
|
|
||||||
|
|
||||||
|
|
||||||
def write_plain_text(self, text, start, end):
|
|
||||||
if start < end:
|
|
||||||
self.wrapped.write(text[start:end])
|
|
||||||
self.wrapped.flush()
|
|
||||||
|
|
||||||
|
|
||||||
def convert_ansi(self, paramstring, command):
|
|
||||||
if self.convert:
|
|
||||||
params = self.extract_params(paramstring)
|
|
||||||
self.call_win32(command, params)
|
|
||||||
|
|
||||||
|
|
||||||
def extract_params(self, paramstring):
|
|
||||||
def split(paramstring):
|
|
||||||
for p in paramstring.split(';'):
|
|
||||||
if p != '':
|
|
||||||
yield int(p)
|
|
||||||
return tuple(split(paramstring))
|
|
||||||
|
|
||||||
|
|
||||||
def call_win32(self, command, params):
|
|
||||||
if params == []:
|
|
||||||
params = [0]
|
|
||||||
if command == 'm':
|
|
||||||
for param in params:
|
|
||||||
if param in self.win32_calls:
|
|
||||||
func_args = self.win32_calls[param]
|
|
||||||
func = func_args[0]
|
|
||||||
args = func_args[1:]
|
|
||||||
kwargs = dict(on_stderr=self.on_stderr)
|
|
||||||
func(*args, **kwargs)
|
|
||||||
elif command in ('H', 'f'): # set cursor position
|
|
||||||
func = winterm.set_cursor_position
|
|
||||||
func(params, on_stderr=self.on_stderr)
|
|
||||||
elif command in ('J'):
|
|
||||||
func = winterm.erase_data
|
|
||||||
func(params, on_stderr=self.on_stderr)
|
|
||||||
elif command == 'A':
|
|
||||||
if params == () or params == None:
|
|
||||||
num_rows = 1
|
|
||||||
else:
|
|
||||||
num_rows = params[0]
|
|
||||||
func = winterm.cursor_up
|
|
||||||
func(num_rows, on_stderr=self.on_stderr)
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
|||||||
import atexit
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from .ansitowin32 import AnsiToWin32
|
|
||||||
|
|
||||||
|
|
||||||
orig_stdout = sys.stdout
|
|
||||||
orig_stderr = sys.stderr
|
|
||||||
|
|
||||||
wrapped_stdout = sys.stdout
|
|
||||||
wrapped_stderr = sys.stderr
|
|
||||||
|
|
||||||
atexit_done = False
|
|
||||||
|
|
||||||
|
|
||||||
def reset_all():
|
|
||||||
AnsiToWin32(orig_stdout).reset_all()
|
|
||||||
|
|
||||||
|
|
||||||
def init(autoreset=False, convert=None, strip=None, wrap=True):
|
|
||||||
|
|
||||||
if not wrap and any([autoreset, convert, strip]):
|
|
||||||
raise ValueError('wrap=False conflicts with any other arg=True')
|
|
||||||
|
|
||||||
global wrapped_stdout, wrapped_stderr
|
|
||||||
sys.stdout = wrapped_stdout = \
|
|
||||||
wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
|
|
||||||
sys.stderr = wrapped_stderr = \
|
|
||||||
wrap_stream(orig_stderr, convert, strip, autoreset, wrap)
|
|
||||||
|
|
||||||
global atexit_done
|
|
||||||
if not atexit_done:
|
|
||||||
atexit.register(reset_all)
|
|
||||||
atexit_done = True
|
|
||||||
|
|
||||||
|
|
||||||
def deinit():
|
|
||||||
sys.stdout = orig_stdout
|
|
||||||
sys.stderr = orig_stderr
|
|
||||||
|
|
||||||
|
|
||||||
def reinit():
|
|
||||||
sys.stdout = wrapped_stdout
|
|
||||||
sys.stderr = wrapped_stdout
|
|
||||||
|
|
||||||
|
|
||||||
def wrap_stream(stream, convert, strip, autoreset, wrap):
|
|
||||||
if wrap:
|
|
||||||
wrapper = AnsiToWin32(stream,
|
|
||||||
convert=convert, strip=strip, autoreset=autoreset)
|
|
||||||
if wrapper.should_wrap():
|
|
||||||
stream = wrapper.stream
|
|
||||||
return stream
|
|
||||||
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
|||||||
|
|
||||||
# from winbase.h
|
|
||||||
STDOUT = -11
|
|
||||||
STDERR = -12
|
|
||||||
|
|
||||||
try:
|
|
||||||
from ctypes import windll
|
|
||||||
except ImportError:
|
|
||||||
windll = None
|
|
||||||
SetConsoleTextAttribute = lambda *_: None
|
|
||||||
else:
|
|
||||||
from ctypes import (
|
|
||||||
byref, Structure, c_char, c_short, c_uint32, c_ushort
|
|
||||||
)
|
|
||||||
|
|
||||||
handles = {
|
|
||||||
STDOUT: windll.kernel32.GetStdHandle(STDOUT),
|
|
||||||
STDERR: windll.kernel32.GetStdHandle(STDERR),
|
|
||||||
}
|
|
||||||
|
|
||||||
SHORT = c_short
|
|
||||||
WORD = c_ushort
|
|
||||||
DWORD = c_uint32
|
|
||||||
TCHAR = c_char
|
|
||||||
|
|
||||||
class COORD(Structure):
|
|
||||||
"""struct in wincon.h"""
|
|
||||||
_fields_ = [
|
|
||||||
('X', SHORT),
|
|
||||||
('Y', SHORT),
|
|
||||||
]
|
|
||||||
|
|
||||||
class SMALL_RECT(Structure):
|
|
||||||
"""struct in wincon.h."""
|
|
||||||
_fields_ = [
|
|
||||||
("Left", SHORT),
|
|
||||||
("Top", SHORT),
|
|
||||||
("Right", SHORT),
|
|
||||||
("Bottom", SHORT),
|
|
||||||
]
|
|
||||||
|
|
||||||
class CONSOLE_SCREEN_BUFFER_INFO(Structure):
|
|
||||||
"""struct in wincon.h."""
|
|
||||||
_fields_ = [
|
|
||||||
("dwSize", COORD),
|
|
||||||
("dwCursorPosition", COORD),
|
|
||||||
("wAttributes", WORD),
|
|
||||||
("srWindow", SMALL_RECT),
|
|
||||||
("dwMaximumWindowSize", COORD),
|
|
||||||
]
|
|
||||||
def __str__(self):
|
|
||||||
return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % (
|
|
||||||
self.dwSize.Y, self.dwSize.X
|
|
||||||
, self.dwCursorPosition.Y, self.dwCursorPosition.X
|
|
||||||
, self.wAttributes
|
|
||||||
, self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right
|
|
||||||
, self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X
|
|
||||||
)
|
|
||||||
|
|
||||||
def GetConsoleScreenBufferInfo(stream_id=STDOUT):
|
|
||||||
handle = handles[stream_id]
|
|
||||||
csbi = CONSOLE_SCREEN_BUFFER_INFO()
|
|
||||||
success = windll.kernel32.GetConsoleScreenBufferInfo(
|
|
||||||
handle, byref(csbi))
|
|
||||||
return csbi
|
|
||||||
|
|
||||||
|
|
||||||
def SetConsoleTextAttribute(stream_id, attrs):
|
|
||||||
handle = handles[stream_id]
|
|
||||||
return windll.kernel32.SetConsoleTextAttribute(handle, attrs)
|
|
||||||
|
|
||||||
|
|
||||||
def SetConsoleCursorPosition(stream_id, position):
|
|
||||||
position = COORD(*position)
|
|
||||||
# If the position is out of range, do nothing.
|
|
||||||
if position.Y <= 0 or position.X <= 0:
|
|
||||||
return
|
|
||||||
# Adjust for Windows' SetConsoleCursorPosition:
|
|
||||||
# 1. being 0-based, while ANSI is 1-based.
|
|
||||||
# 2. expecting (x,y), while ANSI uses (y,x).
|
|
||||||
adjusted_position = COORD(position.Y - 1, position.X - 1)
|
|
||||||
# Adjust for viewport's scroll position
|
|
||||||
sr = GetConsoleScreenBufferInfo(STDOUT).srWindow
|
|
||||||
adjusted_position.Y += sr.Top
|
|
||||||
adjusted_position.X += sr.Left
|
|
||||||
# Resume normal processing
|
|
||||||
handle = handles[stream_id]
|
|
||||||
return windll.kernel32.SetConsoleCursorPosition(handle, adjusted_position)
|
|
||||||
|
|
||||||
def FillConsoleOutputCharacter(stream_id, char, length, start):
|
|
||||||
handle = handles[stream_id]
|
|
||||||
char = TCHAR(char)
|
|
||||||
length = DWORD(length)
|
|
||||||
num_written = DWORD(0)
|
|
||||||
# Note that this is hard-coded for ANSI (vs wide) bytes.
|
|
||||||
success = windll.kernel32.FillConsoleOutputCharacterA(
|
|
||||||
handle, char, length, start, byref(num_written))
|
|
||||||
return num_written.value
|
|
||||||
|
|
||||||
def FillConsoleOutputAttribute(stream_id, attr, length, start):
|
|
||||||
''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )'''
|
|
||||||
handle = handles[stream_id]
|
|
||||||
attribute = WORD(attr)
|
|
||||||
length = DWORD(length)
|
|
||||||
num_written = DWORD(0)
|
|
||||||
# Note that this is hard-coded for ANSI (vs wide) bytes.
|
|
||||||
return windll.kernel32.FillConsoleOutputAttribute(
|
|
||||||
handle, attribute, length, start, byref(num_written))
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
|||||||
|
|
||||||
from . import win32
|
|
||||||
|
|
||||||
|
|
||||||
# from wincon.h
|
|
||||||
class WinColor(object):
|
|
||||||
BLACK = 0
|
|
||||||
BLUE = 1
|
|
||||||
GREEN = 2
|
|
||||||
CYAN = 3
|
|
||||||
RED = 4
|
|
||||||
MAGENTA = 5
|
|
||||||
YELLOW = 6
|
|
||||||
GREY = 7
|
|
||||||
|
|
||||||
# from wincon.h
|
|
||||||
class WinStyle(object):
|
|
||||||
NORMAL = 0x00 # dim text, dim background
|
|
||||||
BRIGHT = 0x08 # bright text, dim background
|
|
||||||
|
|
||||||
|
|
||||||
class WinTerm(object):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes
|
|
||||||
self.set_attrs(self._default)
|
|
||||||
self._default_fore = self._fore
|
|
||||||
self._default_back = self._back
|
|
||||||
self._default_style = self._style
|
|
||||||
|
|
||||||
def get_attrs(self):
|
|
||||||
return self._fore + self._back * 16 + self._style
|
|
||||||
|
|
||||||
def set_attrs(self, value):
|
|
||||||
self._fore = value & 7
|
|
||||||
self._back = (value >> 4) & 7
|
|
||||||
self._style = value & WinStyle.BRIGHT
|
|
||||||
|
|
||||||
def reset_all(self, on_stderr=None):
|
|
||||||
self.set_attrs(self._default)
|
|
||||||
self.set_console(attrs=self._default)
|
|
||||||
|
|
||||||
def fore(self, fore=None, on_stderr=False):
|
|
||||||
if fore is None:
|
|
||||||
fore = self._default_fore
|
|
||||||
self._fore = fore
|
|
||||||
self.set_console(on_stderr=on_stderr)
|
|
||||||
|
|
||||||
def back(self, back=None, on_stderr=False):
|
|
||||||
if back is None:
|
|
||||||
back = self._default_back
|
|
||||||
self._back = back
|
|
||||||
self.set_console(on_stderr=on_stderr)
|
|
||||||
|
|
||||||
def style(self, style=None, on_stderr=False):
|
|
||||||
if style is None:
|
|
||||||
style = self._default_style
|
|
||||||
self._style = style
|
|
||||||
self.set_console(on_stderr=on_stderr)
|
|
||||||
|
|
||||||
def set_console(self, attrs=None, on_stderr=False):
|
|
||||||
if attrs is None:
|
|
||||||
attrs = self.get_attrs()
|
|
||||||
handle = win32.STDOUT
|
|
||||||
if on_stderr:
|
|
||||||
handle = win32.STDERR
|
|
||||||
win32.SetConsoleTextAttribute(handle, attrs)
|
|
||||||
|
|
||||||
def get_position(self, handle):
|
|
||||||
position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition
|
|
||||||
# Because Windows coordinates are 0-based,
|
|
||||||
# and win32.SetConsoleCursorPosition expects 1-based.
|
|
||||||
position.X += 1
|
|
||||||
position.Y += 1
|
|
||||||
return position
|
|
||||||
|
|
||||||
def set_cursor_position(self, position=None, on_stderr=False):
|
|
||||||
if position is None:
|
|
||||||
#I'm not currently tracking the position, so there is no default.
|
|
||||||
#position = self.get_position()
|
|
||||||
return
|
|
||||||
handle = win32.STDOUT
|
|
||||||
if on_stderr:
|
|
||||||
handle = win32.STDERR
|
|
||||||
win32.SetConsoleCursorPosition(handle, position)
|
|
||||||
|
|
||||||
def cursor_up(self, num_rows=0, on_stderr=False):
|
|
||||||
if num_rows == 0:
|
|
||||||
return
|
|
||||||
handle = win32.STDOUT
|
|
||||||
if on_stderr:
|
|
||||||
handle = win32.STDERR
|
|
||||||
position = self.get_position(handle)
|
|
||||||
adjusted_position = (position.Y - num_rows, position.X)
|
|
||||||
self.set_cursor_position(adjusted_position, on_stderr)
|
|
||||||
|
|
||||||
def erase_data(self, mode=0, on_stderr=False):
|
|
||||||
# 0 (or None) should clear from the cursor to the end of the screen.
|
|
||||||
# 1 should clear from the cursor to the beginning of the screen.
|
|
||||||
# 2 should clear the entire screen. (And maybe move cursor to (1,1)?)
|
|
||||||
#
|
|
||||||
# At the moment, I only support mode 2. From looking at the API, it
|
|
||||||
# should be possible to calculate a different number of bytes to clear,
|
|
||||||
# and to do so relative to the cursor position.
|
|
||||||
if mode[0] not in (2,):
|
|
||||||
return
|
|
||||||
handle = win32.STDOUT
|
|
||||||
if on_stderr:
|
|
||||||
handle = win32.STDERR
|
|
||||||
# here's where we'll home the cursor
|
|
||||||
coord_screen = win32.COORD(0,0)
|
|
||||||
csbi = win32.GetConsoleScreenBufferInfo(handle)
|
|
||||||
# get the number of character cells in the current buffer
|
|
||||||
dw_con_size = csbi.dwSize.X * csbi.dwSize.Y
|
|
||||||
# fill the entire screen with blanks
|
|
||||||
win32.FillConsoleOutputCharacter(handle, ord(' '), dw_con_size, coord_screen)
|
|
||||||
# now set the buffer's attributes accordingly
|
|
||||||
win32.FillConsoleOutputAttribute(handle, self.get_attrs(), dw_con_size, coord_screen );
|
|
||||||
# put the cursor at (0, 0)
|
|
||||||
win32.SetConsoleCursorPosition(handle, (coord_screen.X, coord_screen.Y))
|
|
Loading…
Reference in New Issue