From cadfa4152bca314e2e614baa19e2ccbf07ade00e Mon Sep 17 00:00:00 2001 From: "Brandon T. Willard" Date: Sun, 28 Oct 2018 22:02:08 -0500 Subject: [PATCH] Make colored output configurable Colored exception output is now disabled by default and configurable through `hy.errors._hy_colored_errors` and the environment variable `HY_COLORED_ERRORS`. Likewise, Hy model/AST color printing is now configurable and disabled by default. The corresponding variables are `hy.models._hy_colored_ast_objects` and `HY_COLORED_AST_OBJECTS`. Closes hylang/hy#1429, closes hylang/hy#1510. --- hy/errors.py | 49 ++++++++++++++++++++++++++++++------------------- hy/models.py | 12 ++++++++---- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/hy/errors.py b/hy/errors.py index 4ed56e5..9ca823e 100644 --- a/hy/errors.py +++ b/hy/errors.py @@ -15,6 +15,7 @@ from clint.textui import colored _hy_filter_internal_errors = _initialize_env_var('HY_FILTER_INTERNAL_ERRORS', True) +_hy_colored_errors = _initialize_env_var('HY_COLORED_ERRORS', False) class HyError(Exception): @@ -73,9 +74,16 @@ class HyTypeError(HyLanguageError, TypeError): source) def __str__(self): + global _hy_colored_errors result = "" + if _hy_colored_errors: + from clint.textui import colored + red, green, yellow = colored.red, colored.green, colored.yellow + else: + red = green = yellow = lambda x: x + if all(getattr(self.expression, x, None) is not None for x in ("start_line", "start_column", "end_column")): @@ -97,28 +105,28 @@ class HyTypeError(HyLanguageError, TypeError): start) if len(source) == 1: - result += ' %s\n' % colored.red(source[0]) + result += ' %s\n' % red(source[0]) result += ' %s%s\n' % (' '*(start-1), - colored.green('^' + '-'*(length-1) + '^')) + green('^' + '-'*(length-1) + '^')) if len(source) > 1: - result += ' %s\n' % colored.red(source[0]) + result += ' %s\n' % red(source[0]) result += ' %s%s\n' % (' '*(start-1), - colored.green('^' + '-'*length)) + green('^' + '-'*length)) if len(source) > 2: # write the middle lines for line in source[1:-1]: - result += ' %s\n' % colored.red("".join(line)) - result += ' %s\n' % colored.green("-"*len(line)) + result += ' %s\n' % red("".join(line)) + result += ' %s\n' % green("-"*len(line)) # write the last line - result += ' %s\n' % colored.red("".join(source[-1])) - result += ' %s\n' % colored.green('-'*(end-1) + '^') + result += ' %s\n' % red("".join(source[-1])) + result += ' %s\n' % green('-'*(end-1) + '^') else: result += ' File "%s", unknown location\n' % self.filename - result += colored.yellow("%s: %s\n\n" % - (self.__class__.__name__, - self.message)) + result += yellow("%s: %s\n\n" % + (self.__class__.__name__, + self.message)) return result @@ -199,18 +207,21 @@ class HySyntaxError(HyLanguageError, SyntaxError): return HySyntaxError(message, filename, lineno, colno, source) def __str__(self): + global _hy_colored_errors output = traceback.format_exception_only(SyntaxError, SyntaxError(*self.args)) - output[-1] = colored.yellow(output[-1]) - if len(self.source) > 0: - output[-2] = colored.green(output[-2]) - for line in output[::-2]: - if line.strip().startswith( - 'File "{}", line'.format(self.filename)): - break - output[-3] = colored.red(output[-3]) + if _hy_colored_errors: + from hy.errors import colored + output[-1] = colored.yellow(output[-1]) + if len(self.source) > 0: + output[-2] = colored.green(output[-2]) + for line in output[::-2]: + if line.strip().startswith( + 'File "{}", line'.format(self.filename)): + break + output[-3] = colored.red(output[-3]) # Avoid "...expected str instance, ColoredString found" return reduce(lambda x, y: x + y, output) diff --git a/hy/models.py b/hy/models.py index cf02dab..134e322 100644 --- a/hy/models.py +++ b/hy/models.py @@ -1,16 +1,17 @@ # Copyright 2019 the authors. # This file is part of Hy, which is free software licensed under the Expat # license. See the LICENSE. - from __future__ import unicode_literals + from contextlib import contextmanager from math import isnan, isinf +from hy import _initialize_env_var from hy._compat import PY3, str_type, bytes_type, long_type, string_types from fractions import Fraction from clint.textui import colored - PRETTY = True +_hy_colored_ast_objects = _initialize_env_var('HY_COLORED_AST_OBJECTS', False) @contextmanager @@ -271,8 +272,9 @@ class HySequence(HyObject, list): return str(self) if PRETTY else super(HySequence, self).__repr__() def __str__(self): + global _hy_colored_ast_objects with pretty(): - c = self.color + c = self.color if _hy_colored_ast_objects else str if self: return ("{}{}\n {}{}").format( c(self.__class__.__name__), @@ -298,10 +300,12 @@ class HyDict(HySequence): """ HyDict (just a representation of a dict) """ + color = staticmethod(colored.green) def __str__(self): + global _hy_colored_ast_objects with pretty(): - g = colored.green + g = self.color if _hy_colored_ast_objects else str if self: pairs = [] for k, v in zip(self[::2],self[1::2]):