112882Sspwilson2@wisc.edu# Copyright (c) 2011 Advanced Micro Devices, Inc. 212882Sspwilson2@wisc.edu# All rights reserved. 312882Sspwilson2@wisc.edu# 412882Sspwilson2@wisc.edu# Redistribution and use in source and binary forms, with or without 512882Sspwilson2@wisc.edu# modification, are permitted provided that the following conditions are 612882Sspwilson2@wisc.edu# met: redistributions of source code must retain the above copyright 712882Sspwilson2@wisc.edu# notice, this list of conditions and the following disclaimer; 812882Sspwilson2@wisc.edu# redistributions in binary form must reproduce the above copyright 912882Sspwilson2@wisc.edu# notice, this list of conditions and the following disclaimer in the 1012882Sspwilson2@wisc.edu# documentation and/or other materials provided with the distribution; 1112882Sspwilson2@wisc.edu# neither the name of the copyright holders nor the names of its 1212882Sspwilson2@wisc.edu# contributors may be used to endorse or promote products derived from 1312882Sspwilson2@wisc.edu# this software without specific prior written permission. 1412882Sspwilson2@wisc.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1512882Sspwilson2@wisc.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1612882Sspwilson2@wisc.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1712882Sspwilson2@wisc.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1812882Sspwilson2@wisc.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1912882Sspwilson2@wisc.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2012882Sspwilson2@wisc.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2112882Sspwilson2@wisc.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2212882Sspwilson2@wisc.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2312882Sspwilson2@wisc.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2412882Sspwilson2@wisc.edu# 2512882Sspwilson2@wisc.edu# Author: Steve Reinhardt 2612882Sspwilson2@wisc.edu 2712882Sspwilson2@wisc.eduimport sys 2812882Sspwilson2@wisc.eduimport fcntl 2912882Sspwilson2@wisc.eduimport termios 3012882Sspwilson2@wisc.eduimport struct 3112882Sspwilson2@wisc.edu 3212882Sspwilson2@wisc.edu# Intended usage example: 3312882Sspwilson2@wisc.edu# 3412882Sspwilson2@wisc.edu# if force_colors: 3512882Sspwilson2@wisc.edu# from m5.util.terminal import termcap 3612882Sspwilson2@wisc.edu# elif no_colors: 3712882Sspwilson2@wisc.edu# from m5.util.terminal import no_termcap as termcap 3812882Sspwilson2@wisc.edu# else: 3912882Sspwilson2@wisc.edu# from m5.util.terminal import tty_termcap as termcap 4012882Sspwilson2@wisc.edu# print termcap.Blue + "This could be blue!" + termcap.Normal 4112882Sspwilson2@wisc.edu 4212882Sspwilson2@wisc.edu# ANSI color names in index order 4312882Sspwilson2@wisc.educolor_names = "Black Red Green Yellow Blue Magenta Cyan White".split() 4412882Sspwilson2@wisc.edudefault_separator = '=' 4512882Sspwilson2@wisc.edu 4612882Sspwilson2@wisc.edu# Character attribute capabilities. Note that not all terminals 4712882Sspwilson2@wisc.edu# support all of these capabilities, or support them 4812882Sspwilson2@wisc.edu# differently/meaningfully. For example: 4912882Sspwilson2@wisc.edu# 5012882Sspwilson2@wisc.edu# - In PuTTY (with the default settings), Dim has no effect, Standout 5112882Sspwilson2@wisc.edu# is the same as Reverse, and Blink does not blink but switches to a 5212882Sspwilson2@wisc.edu# gray background. 5312882Sspwilson2@wisc.edu# 5412882Sspwilson2@wisc.edu# Please feel free to add information about other terminals here. 5512882Sspwilson2@wisc.edu# 5612882Sspwilson2@wisc.educapability_map = { 5712882Sspwilson2@wisc.edu 'Bold': 'bold', 5812882Sspwilson2@wisc.edu 'Dim': 'dim', 5912882Sspwilson2@wisc.edu 'Blink': 'blink', 6012882Sspwilson2@wisc.edu 'Underline': 'smul', 6112882Sspwilson2@wisc.edu 'Reverse': 'rev', 6212882Sspwilson2@wisc.edu 'Standout': 'smso', 6312882Sspwilson2@wisc.edu 'Normal': 'sgr0' 6412882Sspwilson2@wisc.edu} 6512882Sspwilson2@wisc.edu 6612882Sspwilson2@wisc.educapability_names = capability_map.keys() 6712882Sspwilson2@wisc.edu 6812882Sspwilson2@wisc.edudef null_cap_string(s, *args): 6912882Sspwilson2@wisc.edu return '' 7012882Sspwilson2@wisc.edu 7112882Sspwilson2@wisc.edutry: 7212882Sspwilson2@wisc.edu import curses 7312882Sspwilson2@wisc.edu curses.setupterm() 7412882Sspwilson2@wisc.edu def cap_string(s, *args): 7512882Sspwilson2@wisc.edu cap = curses.tigetstr(s) 7612882Sspwilson2@wisc.edu if cap: 7712882Sspwilson2@wisc.edu return curses.tparm(cap, *args) 7812882Sspwilson2@wisc.edu else: 7912882Sspwilson2@wisc.edu return '' 8012882Sspwilson2@wisc.eduexcept: 8112882Sspwilson2@wisc.edu cap_string = null_cap_string 8212882Sspwilson2@wisc.edu 8312882Sspwilson2@wisc.educlass ColorStrings(object): 8412882Sspwilson2@wisc.edu def __init__(self, cap_string): 8512882Sspwilson2@wisc.edu for i, c in enumerate(color_names): 8612882Sspwilson2@wisc.edu setattr(self, c, cap_string('setaf', i)) 8712882Sspwilson2@wisc.edu for name, cap in capability_map.iteritems(): 8812882Sspwilson2@wisc.edu setattr(self, name, cap_string(cap)) 8912882Sspwilson2@wisc.edu 9012882Sspwilson2@wisc.edutermcap = ColorStrings(cap_string) 9112882Sspwilson2@wisc.eduno_termcap = ColorStrings(null_cap_string) 9212882Sspwilson2@wisc.edu 9312882Sspwilson2@wisc.eduif sys.stdout.isatty(): 9412882Sspwilson2@wisc.edu tty_termcap = termcap 9512882Sspwilson2@wisc.eduelse: 9612882Sspwilson2@wisc.edu tty_termcap = no_termcap 9712882Sspwilson2@wisc.edu 9812882Sspwilson2@wisc.edudef get_termcap(use_colors = None): 9912882Sspwilson2@wisc.edu if use_colors: 10012882Sspwilson2@wisc.edu return termcap 10112882Sspwilson2@wisc.edu elif use_colors is None: 10212882Sspwilson2@wisc.edu # option unspecified; default behavior is to use colors iff isatty 10312882Sspwilson2@wisc.edu return tty_termcap 10412882Sspwilson2@wisc.edu else: 10512882Sspwilson2@wisc.edu return no_termcap 10612882Sspwilson2@wisc.edu 10712882Sspwilson2@wisc.edudef terminal_size(): 10812882Sspwilson2@wisc.edu '''Return the (width, heigth) of the terminal screen.''' 10913788Sjason@lowepower.com try: 11013788Sjason@lowepower.com h, w, hp, wp = struct.unpack('HHHH', 11113788Sjason@lowepower.com fcntl.ioctl(0, termios.TIOCGWINSZ, 11213788Sjason@lowepower.com struct.pack('HHHH', 0, 0, 0, 0))) 11313788Sjason@lowepower.com return w, h 11413788Sjason@lowepower.com except IOError: 11513788Sjason@lowepower.com # It's possible that in sandboxed environments the above ioctl is not 11613788Sjason@lowepower.com # allowed (e.g., some jenkins setups) 11713788Sjason@lowepower.com return 80, 24 11813788Sjason@lowepower.com 11912882Sspwilson2@wisc.edu 12012882Sspwilson2@wisc.edudef separator(char=default_separator, color=None): 12112882Sspwilson2@wisc.edu ''' 12212882Sspwilson2@wisc.edu Return a separator of the given character that is the length of the full 12312882Sspwilson2@wisc.edu width of the terminal screen. 12412882Sspwilson2@wisc.edu ''' 12512882Sspwilson2@wisc.edu (w, h) = terminal_size() 12612882Sspwilson2@wisc.edu if color: 12712882Sspwilson2@wisc.edu return color + char*w + termcap.Normal 12812882Sspwilson2@wisc.edu else: 12912882Sspwilson2@wisc.edu return char*w 13012882Sspwilson2@wisc.edu 13112882Sspwilson2@wisc.edudef insert_separator(inside, char=default_separator, 13212882Sspwilson2@wisc.edu min_barrier=3, color=None): 13312882Sspwilson2@wisc.edu ''' 13412882Sspwilson2@wisc.edu Place the given string inside of the separator. If it does not fit inside, 13512882Sspwilson2@wisc.edu expand the separator to fit it with at least min_barrier. 13612882Sspwilson2@wisc.edu 13712882Sspwilson2@wisc.edu .. seealso:: :func:`separator` 13812882Sspwilson2@wisc.edu ''' 13912882Sspwilson2@wisc.edu # Use a bytearray so it's efficient to manipulate 14012882Sspwilson2@wisc.edu string = bytearray(separator(char, color=color)) 14112882Sspwilson2@wisc.edu 14212882Sspwilson2@wisc.edu # Check if we can fit inside with at least min_barrier. 14312882Sspwilson2@wisc.edu gap = (len(string) - len(inside)) - min_barrier * 2 14412882Sspwilson2@wisc.edu if gap > 0: 14512882Sspwilson2@wisc.edu # We'll need to expand the string to fit us. 14612882Sspwilson2@wisc.edu string.extend([ char for _ in range(-gap)]) 14712882Sspwilson2@wisc.edu # Emplace inside 14812882Sspwilson2@wisc.edu middle = ((len(string)-1)/2) 14912882Sspwilson2@wisc.edu start_idx = middle - len(inside)/2 15012882Sspwilson2@wisc.edu string[start_idx:len(inside)+start_idx] = inside 15112882Sspwilson2@wisc.edu return str(string) 15212882Sspwilson2@wisc.edu 15312882Sspwilson2@wisc.edu 15412882Sspwilson2@wisc.eduif __name__ == '__main__': 15512882Sspwilson2@wisc.edu def test_termcap(obj): 15612882Sspwilson2@wisc.edu for c_name in color_names: 15712882Sspwilson2@wisc.edu c_str = getattr(obj, c_name) 15812882Sspwilson2@wisc.edu print c_str + c_name + obj.Normal 15912882Sspwilson2@wisc.edu for attr_name in capability_names: 16012882Sspwilson2@wisc.edu if attr_name == 'Normal': 16112882Sspwilson2@wisc.edu continue 16212882Sspwilson2@wisc.edu attr_str = getattr(obj, attr_name) 16312882Sspwilson2@wisc.edu print attr_str + c_str + attr_name + " " + c_name + obj.Normal 16412882Sspwilson2@wisc.edu print obj.Bold + obj.Underline + \ 16512882Sspwilson2@wisc.edu c_name + "Bold Underline " + c_str + obj.Normal 16612882Sspwilson2@wisc.edu 16712882Sspwilson2@wisc.edu print "=== termcap enabled ===" 16812882Sspwilson2@wisc.edu test_termcap(termcap) 16912882Sspwilson2@wisc.edu print termcap.Normal 17012882Sspwilson2@wisc.edu print "=== termcap disabled ===" 17112882Sspwilson2@wisc.edu test_termcap(no_termcap) 172