diff options
author | paulhopkins <paulhopkins@users.noreply.github.com> | 2017-07-31 20:57:47 +0100 |
---|---|---|
committer | Todd Gamblin <tgamblin@llnl.gov> | 2017-07-31 12:57:47 -0700 |
commit | 1c7e5724d9ff90b27f31faffd712867520e400c6 (patch) | |
tree | 5d6ff249782b04c4780954f2f17b86697dbffb3c /lib/spack/llnl/util/tty/color.py | |
parent | f3c70c235c3a1ef12b3fc9f35458e42228231016 (diff) | |
download | spack-1c7e5724d9ff90b27f31faffd712867520e400c6.tar.gz spack-1c7e5724d9ff90b27f31faffd712867520e400c6.tar.bz2 spack-1c7e5724d9ff90b27f31faffd712867520e400c6.tar.xz spack-1c7e5724d9ff90b27f31faffd712867520e400c6.zip |
Add --color=[always|never|auto] argument; fix color when piping (#3013)
* Disable spec colorization when redirecting stdout and add command line flag to re-enable
* Add command line `--color` flag to control output colorization
* Add options to `llnl.util.tty.color` to allow color to be auto/always/never
* Add `Spec.cformat()` function to be used when `format()` should have auto-coloring
Diffstat (limited to 'lib/spack/llnl/util/tty/color.py')
-rw-r--r-- | lib/spack/llnl/util/tty/color.py | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/lib/spack/llnl/util/tty/color.py b/lib/spack/llnl/util/tty/color.py index fc3b697827..a39b5b95f8 100644 --- a/lib/spack/llnl/util/tty/color.py +++ b/lib/spack/llnl/util/tty/color.py @@ -80,6 +80,7 @@ To output an @, use '@@'. To output a } inside braces, use '}}'. """ import re import sys +from contextlib import contextmanager class ColorParseError(Exception): @@ -107,15 +108,62 @@ colors = {'k': 30, 'K': 90, # black # Regex to be used for color formatting color_re = r'@(?:@|\.|([*_])?([a-zA-Z])?(?:{((?:[^}]|}})*)})?)' +# Mapping from color arguments to values for tty.set_color +color_when_values = { + 'always': True, + 'auto': None, + 'never': False +} -# Force color even if stdout is not a tty. -_force_color = False +# Force color; None: Only color if stdout is a tty +# True: Always colorize output, False: Never colorize output +_force_color = None + + +def _color_when_value(when): + """Raise a ValueError for an invalid color setting. + + Valid values are 'always', 'never', and 'auto', or equivalently, + True, False, and None. + """ + if when in color_when_values: + return color_when_values[when] + elif when not in color_when_values.values(): + raise ValueError('Invalid color setting: %s' % when) + return when + + +def get_color_when(): + """Return whether commands should print color or not.""" + if _force_color is not None: + return _force_color + return sys.stdout.isatty() + + +def set_color_when(when): + """Set when color should be applied. Options are: + + * True or 'always': always print color + * False or 'never': never print color + * None or 'auto': only print color if sys.stdout is a tty. + """ + global _force_color + _force_color = _color_when_value(when) + + +@contextmanager +def color_when(value): + """Context manager to temporarily use a particular color setting.""" + old_value = value + set_color(value) + yield + set_color(old_value) class match_to_ansi(object): def __init__(self, color=True): - self.color = color + self.color = _color_when_value(color) def escape(self, s): """Returns a TTY escape sequence for a color""" @@ -166,7 +214,7 @@ def colorize(string, **kwargs): color (bool): If False, output will be plain text without control codes, for output to non-console devices. """ - color = kwargs.get('color', True) + color = _color_when_value(kwargs.get('color', get_color_when())) return re.sub(color_re, match_to_ansi(color), string) @@ -188,7 +236,7 @@ def cwrite(string, stream=sys.stdout, color=None): then it will be set based on stream.isatty(). """ if color is None: - color = stream.isatty() or _force_color + color = get_color_when() stream.write(colorize(string, color=color)) @@ -217,7 +265,7 @@ class ColorStream(object): if raw: color = True else: - color = self._stream.isatty() or _force_color + color = get_color_when() raw_write(colorize(string, color=color)) def writelines(self, sequence, **kwargs): |