Viewing file: Terminal.py (9.83 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
######################################################################## # $Header: /var/local/cvsroot/4Suite/Ft/Lib/Terminal.py,v 1.3 2005/03/14 07:38:19 mbrown Exp $ """ Provides some of the information from the terminfo database.
Copyright 2005 Fourthought, Inc. (USA). Detailed license and copyright information: http://4suite.org/COPYRIGHT Project home, documentation, distributions: http://4suite.org/ """
import os, re, sys
from Ft.Lib.Terminfo import TERMTYPES as _ANSITERMS from Ft.Lib.Terminfo import DEFAULT_LINES as _LINES from Ft.Lib.Terminfo import DEFAULT_COLUMNS as _COLUMNS
if sys.platform == 'win32': import msvcrt from Ft.Lib import _win32con elif os.name == 'posix': _HAVE_TIOCGWINSZ = False try: import fcntl, termios, struct except ImportError: pass else: _HAVE_TIOCGWINSZ = hasattr(termios, 'TIOCGWINSZ')
# ISO 6429 color sequences are composed of sequences of numbers # separated by semicolons. The most common codes are: # # 0 to restore default color # 1 for brighter colors # 4 for underlined text # 5 for flashing text # 30 for black foreground # 31 for red foreground # 32 for green foreground # 33 for yellow (or brown) foreground # 34 for blue foreground # 35 for purple foreground # 36 for cyan foreground # 37 for white (or gray) foreground # 40 for black background # 41 for red background # 42 for green background # 43 for yellow (or brown) background # 44 for blue background # 45 for purple background # 46 for cyan background # 47 for white (or gray) background
class AnsiEscapes:
class Colors: DEFAULT = '\033[0m' BOLD = '\033[1m'
FOREGROUND_BLACK = '\033[30m' FOREGROUND_MAROON = '\033[31m' FOREGROUND_GREEN = '\033[32m' FOREGROUND_BROWN = FOREGROUND_OLIVE = '\033[33m' FOREGROUND_NAVY = '\033[34m' FOREGROUND_PURPLE = '\033[35m' FOREGROUND_TEAL = '\033[36m' FOREGROUND_SILVER = '\033[37m'
FOREGROUND_GRAY = '\033[1;30m' FOREGROUND_RED = '\033[1;31m' FOREGROUND_LIME = '\033[1;32m' FOREGROUND_YELLOW = '\033[1;33m' FOREGROUND_BLUE = '\033[1;34m' FOREGROUND_MAGENTA = FOREGROUND_FUCHSIA = '\033[1;35m' FOREGROUND_CYAN = FOREGROUND_AQUA = '\033[1;36m' FOREGROUND_WHITE = '\033[1;37m'
BACKGROUND_BLACK = '\033[40m' BACKGROUND_MAROON = '\033[41m' BACKGROUND_GREEN = '\033[42m' BACKGROUND_BROWN = BACKGROUND_OLIVE = '\033[43m' BACKGROUND_NAVY = '\033[44m' BACKGROUND_PURPLE = '\033[45m' BACKGROUND_TEAL = '\033[46m' BACKGROUND_SILVER = '\033[47m'
# Methods a Terminal instance should expose from its underly stream. _file_methods = ('flush', 'write')
class Terminal:
def __init__(self, stream, keepAnsiEscapes=True): self._stream = stream if hasattr(stream, 'isatty') and stream.isatty(): if sys.platform == 'win32': self._init_win32(stream, keepAnsiEscapes) elif os.name == 'posix' and os.environ.get('TERM') in _ANSITERMS: self._init_posix(stream, keepAnsiEscapes)
for name in _file_methods: setattr(self, name, getattr(stream, name)) return
def _init_win32(self, stream, keepAnsiEscapes): try: self._handle = h = msvcrt.get_osfhandle(stream.fileno()) except IOError: pass else: if keepAnsiEscapes: self._write_escape = self._escape_win32 self._default_attribute = \ _win32con.GetConsoleScreenBufferInfo(self._handle)[2]
self.size = self._size_win32 return
def _init_posix(self, stream, keepAnsiEscapes): if keepAnsiEscapes: # stream handles ANSI escapes natively self.writetty = stream.write if _HAVE_TIOCGWINSZ: self.size = self._size_termios return def lines(self): return self.size()[0]
def columns(self): return self.size()[1]
def size(self): return (_LINES, _COLUMNS)
# ANSI Set Display Mode: ESC[#;...;#m _ansi_sdm = re.compile('\033\\[([0-9]+)(?:;([0-9]+))*m')
def writetty(self, bytes): start = 0 match = self._ansi_sdm.search(bytes) while match is not None: # write everything up to the escape sequence self._stream.write(bytes[start:match.start()])
# process the color codes self._write_escape(match.groups()) # skip over the escape sequence start = match.end()
# find the next sequence match = self._ansi_sdm.search(bytes, start) # write the remainder self._stream.write(bytes[start:]) return
def _write_escape(self, codes): """ Escape function for handling ANSI Set Display Mode.
Default behavior is to simply ignore the call (e.g. nothing is added to the output). """ return
# -- Terminal specific functions -----------------------------------
def _size_termios(self): ws = struct.pack("HHHH", 0, 0, 0, 0) ws = fcntl.ioctl(self._stream.fileno(), termios.TIOCGWINSZ, ws) lines, columns, x, y = struct.unpack("HHHH", ws) return (lines, columns)
def _escape_win32(self, codes): """Translates the ANSI color codes into the Win32 API equivalents."""
# get the current text attributes for the stream size, cursor, attributes, window = \ _win32con.GetConsoleScreenBufferInfo(self._handle) for code in map(int, filter(None, codes)): if code == 0: # normal # the default attribute attributes = self._default_attribute elif code == 1: # bold # bold only applies to the foreground color attributes |= _win32con.FOREGROUND_INTENSITY elif code == 30: # black attributes &= _win32con.BACKGROUND elif code == 31: # red attributes &= (_win32con.FOREGROUND_INTENSITY | _win32con.BACKGROUND) attributes |= _win32con.FOREGROUND_RED elif code == 32: # green attributes &= (_win32con.FOREGROUND_INTENSITY | _win32con.BACKGROUND) attributes |= _win32con.FOREGROUND_GREEN elif code == 33: # brown (bold: yellow) attributes &= (_win32con.FOREGROUND_INTENSITY | _win32con.BACKGROUND) attributes |= (_win32con.FOREGROUND_RED | _win32con.FOREGROUND_GREEN) elif code == 34: # blue attributes &= (_win32con.FOREGROUND_INTENSITY | _win32con.BACKGROUND) attributes |= _win32con.FOREGROUND_BLUE elif code == 35: # purple (bold: magenta) attributes &= (_win32con.FOREGROUND_INTENSITY | _win32con.BACKGROUND) attributes |= (_win32con.FOREGROUND_RED | _win32con.FOREGROUND_BLUE) elif code == 36: # cyan attributes &= (_win32con.FOREGROUND_INTENSITY | _win32con.BACKGROUND) attributes |= (_win32con.FOREGROUND_BLUE | _win32con.FOREGROUND_GREEN) elif code == 37: # gray (bold: white) attributes &= (_win32con.FOREGROUND_INTENSITY | _win32con.BACKGROUND) attributes |= (_win32con.FOREGROUND_RED | _win32con.FOREGROUND_GREEN | _win32con.FOREGROUND_BLUE) elif code == 40: # black attributes &= _win32con.FOREGROUND elif code == 41: # red attributes &= _win32con.FOREGROUND attributes |= _win32con.BACKGROUND_RED elif code == 42: # green attributes &= _win32con.FOREGROUND attributes |= _win32con.BACKGROUND_GREEN elif code == 43: # brown attributes &= _win32con.FOREGROUND attributes |= (_win32con.BACKGROUND_RED | _win32con.BACKGROUND_GREEN) elif code == 44: # blue attributes &= _win32con.FOREGROUND attributes |= _win32con.BACKGROUND_BLUE elif code == 45: # purple attributes &= _win32con.FOREGROUND attributes |= (_win32con.BACKGROUND_RED | _win32con.BACKGROUND_BLUE) elif code == 46: # cyan attributes &= _win32con.FOREGROUND attributes |= (_win32con.BACKGROUND_BLUE | _win32con.BACKGROUND_GREEN) elif code == 47: # gray attributes &= _win32con.FOREGROUND attributes |= (_win32con.BACKGROUND_RED | _win32con.BACKGROUND_GREEN | _win32con.BACKGROUND_BLUE) _win32con.SetConsoleTextAttribute(self._handle, attributes) return
def _size_win32(self): size, cursor, attributes, window = \ _win32con.GetConsoleScreenBufferInfo(self._handle) left, top, right, bottom = window # use the buffer size for the column width as Windows wraps text # there instead of at the displayed window size columns, lines = size return (bottom - top, columns - 1)
|