Revision: | 1.2 |
Committed: | Wed Jan 17 18:17:59 2007 UTC (18 years, 3 months ago) by slacapra |
Content type: | text/x-python |
Branch: | MAIN |
CVS Tags: | CRAB_2_9_1, CRAB_2_9_1_pre2, CRAB_2_9_1_pre1, CRAB_2_9_0, CRAB_2_9_0_pre2, CRAB_2_9_0_pre1, CRAB_2_8_8, CRAB_2_8_8_pre1, CRAB_2_8_7_patch3, CRAB_2_8_7_patch2, CRAB_2_8_7_patch1, CRAB_2_8_7, CRAB_2_8_7_pre2, CRAB_2_8_7_pre1, CRAB_2_8_6, CRAB_2_8_6_pre1, CRAB_2_8_5_patch3, CRAB_2_8_5_patch2, CRAB_2_8_5_patch1, CRAB_2_8_5, CRAB_2_8_5_pre5, CRAB_2_8_5_pre4, CRAB_2_8_5_pre3, CRAB_2_8_4_patch3, CRAB_2_8_5_pre2, CRAB_2_8_4_patch2, CRAB_2_8_5_pre1, CRAB_2_8_4_patch1, CRAB_2_8_4, CRAB_2_8_4_pre5, CRAB_2_8_4_pre4, CRAB_2_8_4_pre3, CRAB_2_8_4_pre2, CRAB_2_8_4_pre1, CRAB_2_8_3, CRAB_2_8_3_pre4, CRAB_2_8_3_pre3, CRAB_2_8_3_pre2, CRAB_2_8_3_pre1, CRAB_2_8_2_patch1, CRAB_2_8_2, CRAB_2_8_2_pre5, CRAB_2_8_2_pre4, CRAB_2_8_2_pre3, CRAB_2_8_2_pre2, CRAB_2_8_2_pre1, CRAB_2_8_1, CRAB_2_8_0, CRAB_2_8_0_pre1, CRAB_2_7_10_pre3, CRAB_2_7_9_patch2_pre1, CRAB_2_7_10_pre2, CRAB_2_7_10_pre1, CRAB_2_7_9_patch1, CRAB_2_7_9, CRAB_2_7_9_pre5, CRAB_2_7_9_pre4, CRAB_2_7_9_pre3, CRAB_2_7_9_pre2, CRAB_2_7_8_patch2, CRAB_2_7_9_pre1, CRAB_2_7_8_patch2_pre1, CRAB_2_7_8_patch1, CRAB_2_7_8_patch1_pre1, CRAB_2_7_8, CRAB_2_7_8_pre3, CRAB_2_7_8_pre2, CRAB_2_7_8_dash3, CRAB_2_7_8_dash2, CRAB_2_7_8_dash, CRAB_2_7_7_patch1, CRAB_2_7_7_patch1_pre1, CRAB_2_7_8_pre1, CRAB_2_7_7, CRAB_2_7_7_pre2, CRAB_2_7_7_pre1, CRAB_2_7_6_patch1, CRAB_2_7_6, CRAB_2_7_6_pre1, CRAB_2_7_5_patch1, CRAB_2_7_5, CRAB_2_7_5_pre3, CRAB_2_7_5_pre2, CRAB_2_7_5_pre1, CRAB_2_7_4_patch1, CRAB_2_7_4, CRAB_2_7_4_pre6, CRAB_2_7_4_pre5, CRAB_2_7_4_pre4, CRAB_2_7_4_pre3, CRAB_2_7_4_pre2, CRAB_2_7_4_pre1, CRAB_2_7_3, CRAB_2_7_3_pre3, CRAB_2_7_3_pre3_beta, CRAB_2_7_3_pre2, CRAB_2_7_3_pre2_beta, CRAB_2_7_3_pre1, CRAB_2_7_3_beta3, CRAB_2_7_3_beta2, CRAB_2_7_3_beta1, CRAB_2_7_3_beta, CRAB_2_7_2_p1, CRAB_2_7_1_branch_firstMERGE, CRAB_2_7_2, CRAB_2_7_2_pre4, CRAB_2_7_2_pre3, CRAB_2_7_2_pre2, CRAB_2_7_2_pre1, CRAB_2_7_1, fede_170310, CRAB_2_7_1_pre12, CRAB_2_7_1_pre11, CRAB_2_7_1_pre10, CRAB_2_7_1_pre9, CRAB_LumiMask, CRAB_2_7_lumi, from_LimiMask, CRAB_2_7_1_pre8, CRAB_2_7_1_pre6, CRAB_2_7_1_pre5, CRAB_2_7_1_wmbs_pre4, CRAB_2_7_1_pre4, CRAB_2_7_1_pre3, CRAB_2_6_6_pre6, CRAB_2_7_1_pre2, CRAB_2_6_6_pre5, CRAB_2_7_1_pre1, CRAB_2_6_6_pre4, CRAB_2_6_6_pre3, CRAB_2_6_6_pre2, CRAB_2_6_6_check, CRAB_2_6_6, CRAB_2_6_6_pre1, CRAB_2_7_0, CRAB_2_6_5, CRAB_2_7_0_pre8, CRAB_2_6_5_pre1, CRAB_2_7_0_pre7, CRAB_2_6_4, CRAB_2_7_0_pre6, CRAB_2_6_4_pre1, CRAB_2_7_0_pre5, CRAB_2_6_3_patch_2, CRAB_2_6_3_patch_2_pre2, CRAB_2_6_3_patch_2_pre1, CRAB_2_6_3_patch_1, CRAB_2_7_0_pre4, CRAB_2_7_0_pre3, CRAB_2_6_3, CRAB_2_6_3_pre5, CRAB_2_6_3_pre4, CRAB_2_6_3_pre3, CRAB_2_6_3_pre2, CRAB_2_7_0_pre2, CRAB_2_6_3_pre1, test_1, CRAB_2_7_0_pre1, CRAB_2_6_2, CRAB_2_6_2_pre2, CRAB_2_6_2_pre1, CRAB_2_6_1_pre4, CRAB_2_6_1_pre3, CRAB_2_6_1_pre2, CRAB_2_6_1_pre1, CRAB_2_6_1, CRAB_2_6_0, CRAB_2_6_0_pre14, CRAB_2_6_0_pre13, CRAB_2_6_0_pre12, CRAB_2_6_0_pre11, CRAB_2_6_0_pre10, CRAB_2_6_0_pre9, CRAB_2_6_0_pre8, CRAB_2_6_0_pre7, CRAB_2_6_0_pre6, CRAB_2_6_0_pre5, CRAB_2_6_0_pre4, CRAB_2_6_0_pre3, CRAB_2_6_0_pre2, CRAB_2_6_0_pre1, CRAB_2_5_1, CRAB_2_5_1_pre4, CRAB_2_5_1_pre3, CRAB_2_5_1_pre2, CRAB_2_5_1_pre1, CRAB_2_5_0, CRAB_2_5_0_pre7, CRAB_2_5_0_pre6, CRAB_2_5_0_pre5, CRAB_2_5_0_pre4, CRAB_2_5_0_pre3, CRAB_2_5_0_pre2, CRAB_2_5_0_pre1, CRAB_2_4_4, CRAB_2_4_4_pre6, CRAB_2_4_4_pre5, CRAB_2_4_4_pre4, CRAB_2_4_4_pre3, CRAB_2_4_4_pre2, CRAB_2_4_4_pre1, CRAB_2_4_3, CRAB_2_4_3_pre8, CRAB_2_4_3_pre7, CRAB_2_4_3_pre6, CRAB_2_4_3_pre5, CRAB_2_4_3_pre3, CRAB_2_4_3_pre2, CRAB_2_4_3_pre1, CRAB_2_4_2, CRAB_2_4_2_pre3, CRAB_2_4_2_pre2, CRAB_2_4_2_pre1, CRAB_2_4_1, CRAB_2_4_1_pre4, CRAB_2_4_1_pre3, CRAB_2_4_1_pre2, CRAB_2_4_1_pre1, CRAB_2_4_0_Tutorial, CRAB_2_4_0_Tutorial_pre1, CRAB_2_4_0, CRAB_2_4_0_pre9, CRAB_2_4_0_pre8, CRAB_2_4_0_pre7, CRAB_2_4_0_pre6, CRAB_2_4_0_pre5, CRAB_2_4_0_pre4, CRAB_2_4_0_pre3, CRAB_2_4_0_pre2, CRAB_2_4_0_pre1, CRAB_DLS_PHED1, CRAB_DLS_PHED, CRAB_2_3_2_Fnal, CRAB_2_3_2, CRAB_2_3_2_pre7, CRAB_2_3_2_pre5, CRAB_2_3_2_pre4, CRAB_2_3_2_pre3, CRAB_2_3_2_pre2, CRAB_2_3_2_pre1, CRAB_2_4_0_test, CRAB_2_3_1, CRAB_2_3_1_pre6, CRAB_2_3_1_pre5, CRAB_2_3_1_pre4, CRAB_2_3_1_pre3, CRAB_2_3_1_pre2, CRAB_2_3_1_pre1, CRAB_2_3_0, CRAB_2_3_0_pre6, CRAB_2_3_0_pre1, CRAB_2_2_2_pre5, CRAB_2_2_2_pre4, CRAB_2_2_2_pre3, CRAB_2_2_2_pre2, CRAB_2_2_2_pre1, CRAB_2_2_1, CRAB_2_2_1_pre6, CRAB_2_2_1_pre5, CRAB_2_2_1_pre4, PRODCOMMON_0_10_7_testCS2, CRAB_2_2_1_pre3, CRAB_2_2_1_pre2, CRAB_2_2_1_pre1, CRAB_2_2_0, CRAB_2_2_0_pre21, CRAB_2_2_0_pre19, CRAB_2_2_0_pre18, CRAB_2_2_0_pre17, CRAB_2_2_0_pre16, CRAB_2_2_0_pre15, CRAB_2_2_0_pre13, CRAB_2_2_0_pre12, CRAB_2_2_0_pre11, CRAB_2_2_0_pre10, bp_osg_bdii, CRAB_2_2_0_pre9, CRAB_2_2_0_pre8, CRAB_2_2_0_pre7, CRAB_2_1_2, CRAB_2_2_0_pre5, CRAB_2_1_2_pre2, CRAB_2_1_2_pre1, CRAB_2_2_0_pre4, CRAB_2_2_0_pre2, CRAB_2_1_1, CRAB_2_1_1_pre3, CRAB_2_2_0_pre1, CRAB_2_1_1_pre1, CRAB_2_1_0, CRAB_2_1_0_pre6, CRAB_2_1_0_pre5, CRAB_2_1_0_pre4, CRAB_2_1_0_pre3, CRAB_2_1_0_pre2, CRAB_2_1_0_pre1, CRAB_2_0_4, CRAB_2_0_4_pre2, CRAB_2_0_4_pre1, CRAB_2_0_3, CRAB_2_0_3_pre1, CRAB_2_0_2, CRAB_2_0_2_pre6, CRAB_2_0_2_pre5, CRAB_2_0_2_pre4, CRAB_2_0_2_pre3, CRAB_1_5_4_SLC3, CRAB_1_5_4_SLC3_pre4, CRAB_2_0_2_pre2, CRAB_2_0_2_pre1, CRAB_1_5_4_SLC3_pre3, CRAB_2_0_1, CRAB_1_5_4_SLC3_pre2, CRAB_2_0_1_pre1, CRAB_1_5_4_SLC3_pre1, CRAB_2_0_0, CRAB_2_0_0_pre10, CRAB_2_0_0_pre9, CRAB_1_5_4, CRAB_1_5_4_pre2, CRAB_1_5_4_pre1, CRAB_2_0_0_pre7, CRAB_2_0_0_pre6, CRAB_1_5_3, CRAB_1_5_3_pre5, CRAB_1_5_3_pre4, CRAB_2_0_0_pre5, CRAB_1_5_3_pre3, configure, CRAB_2_0_0_pre4, CRAB_1_5_3_pre2, CRAB_1_5_3_pre1, CRAB_2_0_0_pre3, CRAB_1_5_2, CRAB_2_0_0_pre2, CRAB_2_0_0_pre1, CRAB_1_5_1, CRAB_1_5_1_pre4, CRAB_1_5_1_pre3, CRAB_1_5_1_pre2, CRAB_1_5_1_pre1, CRAB_1_5_0, CRAB_1_5_0_pre9, CRAB_1_5_0_pre8, CRAB_1_5_0_pre7, CRAB_1_5_0_pre6, CRAB_1_5_0_pre5, CRAB_1_5_0_pre4, HEAD |
Branch point for: | CRAB_multiout, CRAB_2_7_1_branch, Lumi2_8, CRAB_2_6_X_br, AnaDataSet, CRAB_2_3_0_br, osg_bdii, CRAB_2_1_2_br, CRAB_2_1_1_pre2, CRAB_1_5_4_SLC3_pre4_br, CRAB_1_5_4_SLC3_start |
Changes since 1.1: | +1 -1 lines |
Log Message: | many minor fixes reported by pychecker, mostly unsude import and unused variables |
# | Content |
---|---|
1 | #!/usr/bin/env python |
2 | |
3 | import sys, re |
4 | |
5 | class TerminalController: |
6 | """ |
7 | A class that can be used to portably generate formatted output to |
8 | a terminal. |
9 | |
10 | `TerminalController` defines a set of instance variables whose |
11 | values are initialized to the control sequence necessary to |
12 | perform a given action. These can be simply included in normal |
13 | output to the terminal: |
14 | |
15 | >>> term = TerminalController() |
16 | >>> print 'This is '+term.GREEN+'green'+term.NORMAL |
17 | |
18 | Alternatively, the `render()` method can used, which replaces |
19 | '${action}' with the string required to perform 'action': |
20 | |
21 | >>> term = TerminalController() |
22 | >>> print term.render('This is ${GREEN}green${NORMAL}') |
23 | |
24 | If the terminal doesn't support a given action, then the value of |
25 | the corresponding instance variable will be set to ''. As a |
26 | result, the above code will still work on terminals that do not |
27 | support color, except that their output will not be colored. |
28 | Also, this means that you can test whether the terminal supports a |
29 | given action by simply testing the truth value of the |
30 | corresponding instance variable: |
31 | |
32 | >>> term = TerminalController() |
33 | >>> if term.CLEAR_SCREEN: |
34 | ... print 'This terminal supports clearning the screen.' |
35 | |
36 | Finally, if the width and height of the terminal are known, then |
37 | they will be stored in the `COLS` and `LINES` attributes. |
38 | """ |
39 | # Cursor movement: |
40 | BOL = '' #: Move the cursor to the beginning of the line |
41 | UP = '' #: Move the cursor up one line |
42 | DOWN = '' #: Move the cursor down one line |
43 | LEFT = '' #: Move the cursor left one char |
44 | RIGHT = '' #: Move the cursor right one char |
45 | |
46 | # Deletion: |
47 | CLEAR_SCREEN = '' #: Clear the screen and move to home position |
48 | CLEAR_EOL = '' #: Clear to the end of the line. |
49 | CLEAR_BOL = '' #: Clear to the beginning of the line. |
50 | CLEAR_EOS = '' #: Clear to the end of the screen |
51 | |
52 | # Output modes: |
53 | BOLD = '' #: Turn on bold mode |
54 | BLINK = '' #: Turn on blink mode |
55 | DIM = '' #: Turn on half-bright mode |
56 | REVERSE = '' #: Turn on reverse-video mode |
57 | NORMAL = '' #: Turn off all modes |
58 | |
59 | # Cursor display: |
60 | HIDE_CURSOR = '' #: Make the cursor invisible |
61 | SHOW_CURSOR = '' #: Make the cursor visible |
62 | |
63 | # Terminal size: |
64 | COLS = None #: Width of the terminal (None for unknown) |
65 | LINES = None #: Height of the terminal (None for unknown) |
66 | |
67 | # Foreground colors: |
68 | BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = '' |
69 | |
70 | # Background colors: |
71 | BG_BLACK = BG_BLUE = BG_GREEN = BG_CYAN = '' |
72 | BG_RED = BG_MAGENTA = BG_YELLOW = BG_WHITE = '' |
73 | |
74 | _STRING_CAPABILITIES = """ |
75 | BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1 |
76 | CLEAR_SCREEN=clear CLEAR_EOL=el CLEAR_BOL=el1 CLEAR_EOS=ed BOLD=bold |
77 | BLINK=blink DIM=dim REVERSE=rev UNDERLINE=smul NORMAL=sgr0 |
78 | HIDE_CURSOR=cinvis SHOW_CURSOR=cnorm""".split() |
79 | _COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split() |
80 | _ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split() |
81 | |
82 | def __init__(self, term_stream=sys.stdout): |
83 | """ |
84 | Create a `TerminalController` and initialize its attributes |
85 | with appropriate values for the current terminal. |
86 | `term_stream` is the stream that will be used for terminal |
87 | output; if this stream is not a tty, then the terminal is |
88 | assumed to be a dumb terminal (i.e., have no capabilities). |
89 | """ |
90 | # Curses isn't available on all platforms |
91 | try: import curses |
92 | except: return |
93 | |
94 | # If the stream isn't a tty, then assume it has no capabilities. |
95 | if not term_stream.isatty(): return |
96 | |
97 | # Check the terminal type. If we fail, then assume that the |
98 | # terminal has no capabilities. |
99 | try: curses.setupterm() |
100 | except: return |
101 | |
102 | # Look up numeric capabilities. |
103 | self.COLS = curses.tigetnum('cols') |
104 | self.LINES = curses.tigetnum('lines') |
105 | |
106 | # Look up string capabilities. |
107 | for capability in self._STRING_CAPABILITIES: |
108 | (attrib, cap_name) = capability.split('=') |
109 | setattr(self, attrib, self._tigetstr(cap_name) or '') |
110 | |
111 | # Colors |
112 | set_fg = self._tigetstr('setf') |
113 | if set_fg: |
114 | for i,color in zip(range(len(self._COLORS)), self._COLORS): |
115 | setattr(self, color, curses.tparm(set_fg, i) or '') |
116 | set_fg_ansi = self._tigetstr('setaf') |
117 | if set_fg_ansi: |
118 | for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS): |
119 | setattr(self, color, curses.tparm(set_fg_ansi, i) or '') |
120 | set_bg = self._tigetstr('setb') |
121 | if set_bg: |
122 | for i,color in zip(range(len(self._COLORS)), self._COLORS): |
123 | setattr(self, 'BG_'+color, curses.tparm(set_bg, i) or '') |
124 | set_bg_ansi = self._tigetstr('setab') |
125 | if set_bg_ansi: |
126 | for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS): |
127 | setattr(self, 'BG_'+color, curses.tparm(set_bg_ansi, i) or '') |
128 | |
129 | def _tigetstr(self, cap_name): |
130 | # String capabilities can include "delays" of the form "$<2>". |
131 | # For any modern terminal, we should be able to just ignore |
132 | # these, so strip them out. |
133 | import curses |
134 | cap = curses.tigetstr(cap_name) or '' |
135 | return re.sub(r'\$<\d+>[/*]?', '', cap) |
136 | |
137 | def render(self, template): |
138 | """ |
139 | Replace each $-substitutions in the given template string with |
140 | the corresponding terminal control string (if it's defined) or |
141 | '' (if it's not). |
142 | """ |
143 | return re.sub(r'\$\$|\${\w+}', self._render_sub, template) |
144 | |
145 | def _render_sub(self, match): |
146 | s = match.group() |
147 | if s == '$$': return s |
148 | else: return getattr(self, s[2:-1]) |
149 | |
150 | |
151 | if __name__ == '__main__': |
152 | term = TerminalController() |
153 | print 'This is '+term.GREEN+term.BG_WHITE+'green'+term.NORMAL |