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.
This commit is contained in:
Brandon T. Willard 2018-10-28 22:02:08 -05:00 committed by Kodi Arfer
parent e468d5f081
commit cadfa4152b
2 changed files with 38 additions and 23 deletions

View File

@ -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)

View File

@ -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]):