casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables
TerminalController.py
Go to the documentation of this file.
00001 import sys
00002 
00003 class TerminalController:
00004     """
00005     A class taken from epydoc that can be used to portably generate formatted
00006     output to a terminal.  See
00007     U{http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/475116} for
00008     documentation.  (This is a somewhat stripped-down version.)
00009     """
00010     BOL = ''             #: Move the cursor to the beginning of the line
00011     UP = ''              #: Move the cursor up one line
00012     DOWN = ''            #: Move the cursor down one line
00013     LEFT = ''            #: Move the cursor left one char
00014     RIGHT = ''           #: Move the cursor right one char
00015     CLEAR_EOL = ''       #: Clear to the end of the line.
00016     CLEAR_LINE = ''      #: Clear the current line; cursor to BOL.
00017     BOLD = ''            #: Turn on bold mode
00018     NORMAL = ''          #: Turn off all modes
00019     COLS = 80            #: Width of the terminal (default to 80)
00020     BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = ''
00021 
00022     _STRING_CAPABILITIES = """
00023     BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1
00024     CLEAR_EOL=el BOLD=bold UNDERLINE=smul NORMAL=sgr0""".split()
00025     _COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split()
00026     _ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split()
00027 
00028     #: If this is set to true, then new TerminalControllers will
00029     #: assume that the terminal is not capable of doing manipulation
00030     #: of any kind.
00031     FORCE_SIMPLE_TERM = False
00032 
00033     def __init__(self, term_stream=sys.stdout):
00034         # If the stream isn't a tty, then assume it has no capabilities.
00035         if not term_stream.isatty(): return
00036         if self.FORCE_SIMPLE_TERM: return
00037 
00038         # Curses isn't available on all platforms
00039         try: import curses
00040         except:
00041             # If it's not available, then try faking enough to get a
00042             # simple progress bar.
00043             self.BOL = '\r'
00044             self.CLEAR_LINE = '\r' + ' '*self.COLS + '\r'
00045 
00046         # Check the terminal type.  If we fail, then assume that the
00047         # terminal has no capabilities.
00048         try: curses.setupterm()
00049         except: return
00050 
00051         # Look up numeric capabilities.
00052         self.COLS = curses.tigetnum('cols')
00053 
00054         # Look up string capabilities.
00055         for capability in self._STRING_CAPABILITIES:
00056             (attrib, cap_name) = capability.split('=')
00057             setattr(self, attrib, self._tigetstr(cap_name) or '')
00058         if self.BOL and self.CLEAR_EOL:
00059             self.CLEAR_LINE = self.BOL+self.CLEAR_EOL
00060 
00061         # Colors
00062         set_fg = self._tigetstr('setf')
00063         if set_fg:
00064             for i,color in zip(range(len(self._COLORS)), self._COLORS):
00065                 setattr(self, color, curses.tparm(set_fg, i) or '')
00066         set_fg_ansi = self._tigetstr('setaf')
00067         if set_fg_ansi:
00068             for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS):
00069                 setattr(self, color, curses.tparm(set_fg_ansi, i) or '')
00070 
00071     def _tigetstr(self, cap_name):
00072         # String capabilities can include "delays" of the form "$<2>".
00073         # For any modern terminal, we should be able to just ignore
00074         # these, so strip them out.
00075         import curses, re
00076         cap = curses.tigetstr(cap_name) or ''
00077         return re.sub(r'\$<\d+>[/*]?', '', cap)