removed the is_vista verification, write the text by chunks and default to the default stream writer when not a tty

This commit is contained in:
Thomas Nagy 2014-01-04 23:20:17 +01:00
parent 526620f16d
commit fa5f149775
No known key found for this signature in database
GPG Key ID: 67A565EDFDF90E64
1 changed files with 31 additions and 22 deletions

View File

@ -13,13 +13,12 @@ console commands.
import sys, os, re, threading import sys, os, re, threading
TINY_STEP = 3000
try: try:
from ctypes import Structure, windll, c_short, c_ulong, c_int, byref, c_wchar from ctypes import Structure, windll, c_short, c_ulong, c_int, byref, c_wchar
except ImportError: except ImportError:
pass pass
else: else:
class COORD(Structure): class COORD(Structure):
_fields_ = [("X", c_short), ("Y", c_short)] _fields_ = [("X", c_short), ("Y", c_short)]
@ -32,8 +31,6 @@ else:
class CONSOLE_CURSOR_INFO(Structure): class CONSOLE_CURSOR_INFO(Structure):
_fields_ = [('dwSize',c_ulong), ('bVisible', c_int)] _fields_ = [('dwSize',c_ulong), ('bVisible', c_int)]
is_vista = getattr(sys, "getwindowsversion", None) and sys.getwindowsversion()[0] >= 6
try: try:
_type = unicode _type = unicode
except NameError: except NameError:
@ -49,12 +46,12 @@ else:
""" """
emulate a vt100 terminal in cmd.exe emulate a vt100 terminal in cmd.exe
""" """
def __init__(self, stream): def __init__(self, s):
self.stream = stream self.stream = s
self.encoding = self.stream.encoding self.encoding = s.encoding
self.cursor_history = [] self.cursor_history = []
handle = (stream.fileno() == 2) and STD_ERROR_HANDLE or STD_OUTPUT_HANDLE handle = (s.fileno() == 2) and STD_ERROR_HANDLE or STD_OUTPUT_HANDLE
self.hconsole = windll.kernel32.GetStdHandle(handle) self.hconsole = windll.kernel32.GetStdHandle(handle)
self._sbinfo = CONSOLE_SCREEN_BUFFER_INFO() self._sbinfo = CONSOLE_SCREEN_BUFFER_INFO()
@ -68,6 +65,9 @@ else:
self._isatty = r == 1 self._isatty = r == 1
def screen_buffer_info(self): def screen_buffer_info(self):
"""
Updates self._sbinfo and returns it
"""
windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(self._sbinfo)) windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(self._sbinfo))
return self._sbinfo return self._sbinfo
@ -173,13 +173,9 @@ else:
def set_color(self, param): def set_color(self, param):
cols = param.split(';') cols = param.split(';')
sbinfo = self.screen_buffer_info() sbinfo = self.screen_buffer_info()
windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(sbinfo))
attr = sbinfo.Attributes attr = sbinfo.Attributes
for c in cols: for c in cols:
if is_vista: c = to_int(c, 0)
c = int(c)
else:
c = to_int(c, 0)
if c in range(30,38): # fgcolor if c in range(30,38): # fgcolor
attr = (attr & 0xfff0) | self.rgb2bgr(c-30) attr = (attr & 0xfff0) | self.rgb2bgr(c-30)
elif c in range(40,48): # bgcolor elif c in range(40,48): # bgcolor
@ -225,14 +221,16 @@ else:
def write(self, text): def write(self, text):
try: try:
wlock.acquire() wlock.acquire()
for param, cmd, txt in self.ansi_tokens.findall(text): if self._isatty:
if cmd: for param, cmd, txt in self.ansi_tokens.findall(text):
if self._isatty: if cmd:
cmd_func = self.ansi_command_table.get(cmd) cmd_func = self.ansi_command_table.get(cmd)
if cmd_func: if cmd_func:
cmd_func(self, param) cmd_func(self, param)
else: else:
self.writeconsole(txt) self.writeconsole(txt)
else:
self.stream.write(text)
finally: finally:
wlock.release() wlock.release()
@ -242,10 +240,21 @@ else:
if isinstance(txt, _type): if isinstance(txt, _type):
writeconsole = windll.kernel32.WriteConsoleW writeconsole = windll.kernel32.WriteConsoleW
for x in range(0, len(txt), TINY_STEP): # MSDN says that there is a shared buffer of 64 KB for the console
# According MSDN, size should NOT exceed 64 kb (issue #746) # writes. Attempt to not get ERROR_NOT_ENOUGH_MEMORY, see waf issue #746
tiny = txt[x : x + TINY_STEP] done = 0
writeconsole(self.hconsole, tiny, len(tiny), byref(chars_written), None) todo = len(txt)
chunk = 32<<10
while todo != 0:
doing = min(chunk, todo)
buf = txt[done:done+doing]
r = writeconsole(self.hconsole, buf, doing, byref(chars_written), None)
if r == 0:
chunk >>= 1
continue
done += doing
todo -= doing
def fileno(self): def fileno(self):
return self.stream.fileno() return self.stream.fileno()