1 # Copyright (c) 2011 Advanced Micro Devices, Inc.
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.
25 # Author: Steve Reinhardt
33 # Intended usage example:
36 # from m5.util.terminal import termcap
38 # from m5.util.terminal import no_termcap as termcap
40 # from m5.util.terminal import tty_termcap as termcap
41 # print termcap.Blue + "This could be blue!" + termcap.Normal
43 # ANSI color names in index order
44 color_names
= "Black Red Green Yellow Blue Magenta Cyan White".split()
45 default_separator
= '='
47 # Character attribute capabilities. Note that not all terminals
48 # support all of these capabilities, or support them
49 # differently/meaningfully. For example:
51 # - In PuTTY (with the default settings), Dim has no effect, Standout
52 # is the same as Reverse, and Blink does not blink but switches to a
55 # Please feel free to add information about other terminals here.
67 capability_names
= capability_map
.keys()
69 def null_cap_string(s
, *args
):
75 def cap_string(s
, *args
):
76 cap
= curses
.tigetstr(s
)
78 return curses
.tparm(cap
, *args
).decode("utf-8")
82 cap_string
= null_cap_string
84 class ColorStrings(object):
85 def __init__(self
, cap_string
):
86 for i
, c
in enumerate(color_names
):
87 setattr(self
, c
, cap_string('setaf', i
))
88 for name
, cap
in six
.iteritems(capability_map
):
89 setattr(self
, name
, cap_string(cap
))
91 termcap
= ColorStrings(cap_string
)
92 no_termcap
= ColorStrings(null_cap_string
)
94 if sys
.stdout
.isatty():
97 tty_termcap
= no_termcap
99 def get_termcap(use_colors
= None):
102 elif use_colors
is None:
103 # option unspecified; default behavior is to use colors iff isatty
109 '''Return the (width, heigth) of the terminal screen.'''
111 h
, w
, hp
, wp
= struct
.unpack('HHHH',
112 fcntl
.ioctl(0, termios
.TIOCGWINSZ
,
113 struct
.pack('HHHH', 0, 0, 0, 0)))
116 # It's possible that in sandboxed environments the above ioctl is not
117 # allowed (e.g., some jenkins setups)
121 def separator(char
=default_separator
, color
=None):
123 Return a separator of the given character that is the length of the full
124 width of the terminal screen.
126 (w
, h
) = terminal_size()
128 return color
+ char
*w
+ termcap
.Normal
132 def insert_separator(inside
, char
=default_separator
,
133 min_barrier
=3, color
=None):
135 Place the given string inside of the separator. If it does not fit inside,
136 expand the separator to fit it with at least min_barrier.
138 .. seealso:: :func:`separator`
140 # Use a bytearray so it's efficient to manipulate
141 string
= bytearray(separator(char
, color
=color
), 'utf-8')
143 # Check if we can fit inside with at least min_barrier.
144 gap
= (len(string
) - len(inside
)) - min_barrier
* 2
146 # We'll need to expand the string to fit us.
147 string
.extend([ char
for _
in range(-gap
)])
149 middle
= (len(string
)-1)//2
150 start_idx
= middle
- len(inside
)//2
151 string
[start_idx
:len(inside
)+start_idx
] = str.encode(inside
)
152 return str(string
.decode("utf-8"))
155 if __name__
== '__main__':
156 def test_termcap(obj
):
157 for c_name
in color_names
:
158 c_str
= getattr(obj
, c_name
)
159 print(c_str
+ c_name
+ obj
.Normal
)
160 for attr_name
in capability_names
:
161 if attr_name
== 'Normal':
163 attr_str
= getattr(obj
, attr_name
)
164 print(attr_str
+ c_str
+ attr_name
+ " " + c_name
+ obj
.Normal
)
165 print(obj
.Bold
+ obj
.Underline
+ \
166 c_name
+ "Bold Underline " + c_str
+ obj
.Normal
)
168 print("=== termcap enabled ===")
169 test_termcap(termcap
)
170 print(termcap
.Normal
)
171 print("=== termcap disabled ===")
172 test_termcap(no_termcap
)