1# Copyright (c) 2011 Advanced Micro Devices, Inc. 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: redistributions of source code must retain the above copyright 7# notice, this list of conditions and the following disclaimer; 8# redistributions in binary form must reproduce the above copyright 9# notice, this list of conditions and the following disclaimer in the 10# documentation and/or other materials provided with the distribution; 11# neither the name of the copyright holders nor the names of its 12# contributors may be used to endorse or promote products derived from 13# this software without specific prior written permission. 14# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 15# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 16# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 17# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24# 25# Author: Steve Reinhardt 26 27import sys 28import fcntl 29import termios 30import struct 31 32# Intended usage example: 33# 34# if force_colors: 35# from m5.util.terminal import termcap 36# elif no_colors: 37# from m5.util.terminal import no_termcap as termcap 38# else: 39# from m5.util.terminal import tty_termcap as termcap 40# print termcap.Blue + "This could be blue!" + termcap.Normal 41 42# ANSI color names in index order 43color_names = "Black Red Green Yellow Blue Magenta Cyan White".split() 44default_separator = '=' 45 46# Character attribute capabilities. Note that not all terminals 47# support all of these capabilities, or support them 48# differently/meaningfully. For example: 49# 50# - In PuTTY (with the default settings), Dim has no effect, Standout 51# is the same as Reverse, and Blink does not blink but switches to a 52# gray background. 53# 54# Please feel free to add information about other terminals here. 55# 56capability_map = { 57 'Bold': 'bold', 58 'Dim': 'dim', 59 'Blink': 'blink', 60 'Underline': 'smul', 61 'Reverse': 'rev', 62 'Standout': 'smso', 63 'Normal': 'sgr0' 64} 65 66capability_names = capability_map.keys() 67 68def null_cap_string(s, *args): 69 return '' 70 71try: 72 import curses 73 curses.setupterm() 74 def cap_string(s, *args): 75 cap = curses.tigetstr(s) 76 if cap: 77 return curses.tparm(cap, *args) 78 else: 79 return '' 80except: 81 cap_string = null_cap_string 82 83class ColorStrings(object): 84 def __init__(self, cap_string): 85 for i, c in enumerate(color_names): 86 setattr(self, c, cap_string('setaf', i)) 87 for name, cap in capability_map.iteritems(): 88 setattr(self, name, cap_string(cap)) 89 90termcap = ColorStrings(cap_string) 91no_termcap = ColorStrings(null_cap_string) 92 93if sys.stdout.isatty(): 94 tty_termcap = termcap 95else: 96 tty_termcap = no_termcap 97 98def get_termcap(use_colors = None): 99 if use_colors: 100 return termcap 101 elif use_colors is None: 102 # option unspecified; default behavior is to use colors iff isatty 103 return tty_termcap 104 else: 105 return no_termcap 106 107def terminal_size(): 108 '''Return the (width, heigth) of the terminal screen.''' 109 try: 110 h, w, hp, wp = struct.unpack('HHHH', 111 fcntl.ioctl(0, termios.TIOCGWINSZ, 112 struct.pack('HHHH', 0, 0, 0, 0))) 113 return w, h 114 except IOError: 115 # It's possible that in sandboxed environments the above ioctl is not 116 # allowed (e.g., some jenkins setups) 117 return 80, 24 118 119 120def separator(char=default_separator, color=None): 121 ''' 122 Return a separator of the given character that is the length of the full 123 width of the terminal screen. 124 ''' 125 (w, h) = terminal_size() 126 if color: 127 return color + char*w + termcap.Normal 128 else: 129 return char*w 130 131def insert_separator(inside, char=default_separator, 132 min_barrier=3, color=None): 133 ''' 134 Place the given string inside of the separator. If it does not fit inside, 135 expand the separator to fit it with at least min_barrier. 136 137 .. seealso:: :func:`separator` 138 ''' 139 # Use a bytearray so it's efficient to manipulate 140 string = bytearray(separator(char, color=color)) 141 142 # Check if we can fit inside with at least min_barrier. 143 gap = (len(string) - len(inside)) - min_barrier * 2 144 if gap > 0: 145 # We'll need to expand the string to fit us. 146 string.extend([ char for _ in range(-gap)]) 147 # Emplace inside 148 middle = ((len(string)-1)/2) 149 start_idx = middle - len(inside)/2 150 string[start_idx:len(inside)+start_idx] = inside 151 return str(string) 152 153 154if __name__ == '__main__': 155 def test_termcap(obj): 156 for c_name in color_names: 157 c_str = getattr(obj, c_name) 158 print c_str + c_name + obj.Normal 159 for attr_name in capability_names: 160 if attr_name == 'Normal': 161 continue 162 attr_str = getattr(obj, attr_name) 163 print attr_str + c_str + attr_name + " " + c_name + obj.Normal 164 print obj.Bold + obj.Underline + \ 165 c_name + "Bold Underline " + c_str + obj.Normal 166 167 print "=== termcap enabled ===" 168 test_termcap(termcap) 169 print termcap.Normal 170 print "=== termcap disabled ===" 171 test_termcap(no_termcap) 172