scons: Use the textwrap module to wrap warnings/errors neatly.

Otherwise the error and warning messages get chopped off and wrapped by
the terminal wherever they happened to end. That's ugly and hard to
read.

This mechanism attempts to wrap the text using the console width which
it attempts to determine in two ways, first with shutil which should
work in python 3.3 and above, and then with the curses python module. If
neither of those works, it just falls back to 80 columns which is not
ideal but is reasonable.

Change-Id: I961936295505f93f5f36eb6d9cebc5073b5f793b
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/27128
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2020-03-26 04:04:42 -07:00
committed by Gabe Black
parent ec236a55ee
commit 47579e693b

View File

@@ -41,6 +41,7 @@
from __future__ import print_function
import os
import textwrap
from gem5_scons.util import get_termcap
import SCons.Script
@@ -127,9 +128,48 @@ class Transform(object):
return ', '.join(f)
return self.format % (com_pfx, fmt(srcs), fmt(tgts))
# The width warning and error messages should be wrapped at.
text_width = None
# This should work in python 3.3 and above.
if text_width is None:
try:
import shutil
text_width = shutil.get_terminal_size().columns
except:
pass
# This should work if the curses python module is installed.
if text_width is None:
try:
import curses
try:
_, text_width = curses.initscr().getmaxyx()
finally:
curses.endwin()
except:
pass
# If all else fails, default to 80 columns.
if text_width is None:
text_width = 80
def print_message(prefix, color, message, **kwargs):
# Precompute some useful values.
prefix_len = len(prefix)
wrap_width = text_width - prefix_len
padding = ' ' * prefix_len
# First split on newlines.
lines = message.split('\n')
message = prefix + ('\n' + ' ' * len(prefix)).join(lines)
# Then wrap each line to the required width.
wrapped_lines = []
for line in lines:
wrapped_lines.extend(textwrap.wrap(line, wrap_width))
# Finally add the prefix and padding on extra lines, and glue it all back
# together.
message = prefix + ('\n' + padding).join(wrapped_lines)
# Print the message in bold in the requested color.
print(color + termcap.Bold + message + termcap.Normal, **kwargs)
def warning(*args, **kwargs):