@ -18,6 +18,81 @@ import ctypes
import math
import sys
if sys . platform == " win32 " :
class _Coord ( ctypes . Structure ) :
_fields_ = [ ( " x " , ctypes . c_short ) ,
( " y " , ctypes . c_short ) ]
class _SmallRect ( ctypes . Structure ) :
_fields_ = [ ( " Left " , ctypes . c_short ) ,
( " Top " , ctypes . c_short ) ,
( " Right " , ctypes . c_short ) ,
( " Bottom " , ctypes . c_short ) , ]
class _ConsoleScreenBufferInfo ( ctypes . Structure ) :
_fields_ = [ ( " dwSize " , _Coord ) ,
( " dwCursorPosition " , _Coord ) ,
( " wAttributes " , ctypes . c_ushort ) ,
( " srWindow " , _SmallRect ) ,
( " dwMaximumWindowSize " , _Coord ) ]
class _ConsoleCursor :
def __init__ ( self ) :
self . _handle = ctypes . windll . kernel32 . GetStdHandle ( - 11 )
self . position = _Coord ( 0 , 0 )
def __del__ ( self ) :
ctypes . windll . kernel32 . CloseHandle ( self . _handle )
@property
def _screen_buffer_info ( self ) :
info = _ConsoleScreenBufferInfo ( )
ctypes . windll . kernel32 . GetConsoleScreenBufferInfo ( self . _handle , ctypes . pointer ( info ) )
return info
def clear ( self ) :
info = self . _screen_buffer_info
curPos = info . dwCursorPosition
num_cols = curPos . y - self . position . y
num_rows = curPos . x - self . position . x
num_chars = ( info . dwSize . x * num_cols ) + num_rows
if num_chars :
nWrite = ctypes . c_ulong ( )
empty_char = ctypes . c_char ( b ' ' )
ctypes . windll . kernel32 . FillConsoleOutputCharacterA ( self . _handle , empty_char ,
num_chars , self . position ,
ctypes . pointer ( nWrite ) )
def reset ( self ) :
ctypes . windll . kernel32 . SetConsoleCursorPosition ( self . _handle , self . position )
def update ( self ) :
info = _ConsoleScreenBufferInfo ( )
ctypes . windll . kernel32 . GetConsoleScreenBufferInfo ( self . _handle , ctypes . pointer ( info ) )
self . position = info . dwCursorPosition
else :
class _ConsoleCursor :
def clear ( self ) :
# Only clears the current line, unfortunately.
sys . stdout . write ( " \x1B [K " )
def reset ( self ) :
# Forcibly clears the line after resetting, just in case more
# than one junk line was printed from somewhere else.
sys . stdout . write ( " \x1B [u \x1B [K " )
def update ( self ) :
sys . stdout . write ( " \x1B [s " )
class ConsoleCursor ( _ConsoleCursor ) :
def __enter__ ( self ) :
self . clear ( )
self . reset ( )
return self
def __exit__ ( self , type , value , traceback ) :
self . update ( )
class ConsoleToggler :
_instance = None