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:
parent
e468d5f081
commit
cadfa4152b
49
hy/errors.py
49
hy/errors.py
@ -15,6 +15,7 @@ from clint.textui import colored
|
|||||||
|
|
||||||
_hy_filter_internal_errors = _initialize_env_var('HY_FILTER_INTERNAL_ERRORS',
|
_hy_filter_internal_errors = _initialize_env_var('HY_FILTER_INTERNAL_ERRORS',
|
||||||
True)
|
True)
|
||||||
|
_hy_colored_errors = _initialize_env_var('HY_COLORED_ERRORS', False)
|
||||||
|
|
||||||
|
|
||||||
class HyError(Exception):
|
class HyError(Exception):
|
||||||
@ -73,9 +74,16 @@ class HyTypeError(HyLanguageError, TypeError):
|
|||||||
source)
|
source)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
global _hy_colored_errors
|
||||||
|
|
||||||
result = ""
|
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
|
if all(getattr(self.expression, x, None) is not None
|
||||||
for x in ("start_line", "start_column", "end_column")):
|
for x in ("start_line", "start_column", "end_column")):
|
||||||
|
|
||||||
@ -97,28 +105,28 @@ class HyTypeError(HyLanguageError, TypeError):
|
|||||||
start)
|
start)
|
||||||
|
|
||||||
if len(source) == 1:
|
if len(source) == 1:
|
||||||
result += ' %s\n' % colored.red(source[0])
|
result += ' %s\n' % red(source[0])
|
||||||
result += ' %s%s\n' % (' '*(start-1),
|
result += ' %s%s\n' % (' '*(start-1),
|
||||||
colored.green('^' + '-'*(length-1) + '^'))
|
green('^' + '-'*(length-1) + '^'))
|
||||||
if len(source) > 1:
|
if len(source) > 1:
|
||||||
result += ' %s\n' % colored.red(source[0])
|
result += ' %s\n' % red(source[0])
|
||||||
result += ' %s%s\n' % (' '*(start-1),
|
result += ' %s%s\n' % (' '*(start-1),
|
||||||
colored.green('^' + '-'*length))
|
green('^' + '-'*length))
|
||||||
if len(source) > 2: # write the middle lines
|
if len(source) > 2: # write the middle lines
|
||||||
for line in source[1:-1]:
|
for line in source[1:-1]:
|
||||||
result += ' %s\n' % colored.red("".join(line))
|
result += ' %s\n' % red("".join(line))
|
||||||
result += ' %s\n' % colored.green("-"*len(line))
|
result += ' %s\n' % green("-"*len(line))
|
||||||
|
|
||||||
# write the last line
|
# write the last line
|
||||||
result += ' %s\n' % colored.red("".join(source[-1]))
|
result += ' %s\n' % red("".join(source[-1]))
|
||||||
result += ' %s\n' % colored.green('-'*(end-1) + '^')
|
result += ' %s\n' % green('-'*(end-1) + '^')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
result += ' File "%s", unknown location\n' % self.filename
|
result += ' File "%s", unknown location\n' % self.filename
|
||||||
|
|
||||||
result += colored.yellow("%s: %s\n\n" %
|
result += yellow("%s: %s\n\n" %
|
||||||
(self.__class__.__name__,
|
(self.__class__.__name__,
|
||||||
self.message))
|
self.message))
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -199,18 +207,21 @@ class HySyntaxError(HyLanguageError, SyntaxError):
|
|||||||
return HySyntaxError(message, filename, lineno, colno, source)
|
return HySyntaxError(message, filename, lineno, colno, source)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
global _hy_colored_errors
|
||||||
|
|
||||||
output = traceback.format_exception_only(SyntaxError,
|
output = traceback.format_exception_only(SyntaxError,
|
||||||
SyntaxError(*self.args))
|
SyntaxError(*self.args))
|
||||||
|
|
||||||
output[-1] = colored.yellow(output[-1])
|
if _hy_colored_errors:
|
||||||
if len(self.source) > 0:
|
from hy.errors import colored
|
||||||
output[-2] = colored.green(output[-2])
|
output[-1] = colored.yellow(output[-1])
|
||||||
for line in output[::-2]:
|
if len(self.source) > 0:
|
||||||
if line.strip().startswith(
|
output[-2] = colored.green(output[-2])
|
||||||
'File "{}", line'.format(self.filename)):
|
for line in output[::-2]:
|
||||||
break
|
if line.strip().startswith(
|
||||||
output[-3] = colored.red(output[-3])
|
'File "{}", line'.format(self.filename)):
|
||||||
|
break
|
||||||
|
output[-3] = colored.red(output[-3])
|
||||||
|
|
||||||
# Avoid "...expected str instance, ColoredString found"
|
# Avoid "...expected str instance, ColoredString found"
|
||||||
return reduce(lambda x, y: x + y, output)
|
return reduce(lambda x, y: x + y, output)
|
||||||
|
12
hy/models.py
12
hy/models.py
@ -1,16 +1,17 @@
|
|||||||
# Copyright 2019 the authors.
|
# Copyright 2019 the authors.
|
||||||
# This file is part of Hy, which is free software licensed under the Expat
|
# This file is part of Hy, which is free software licensed under the Expat
|
||||||
# license. See the LICENSE.
|
# license. See the LICENSE.
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from math import isnan, isinf
|
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 hy._compat import PY3, str_type, bytes_type, long_type, string_types
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from clint.textui import colored
|
from clint.textui import colored
|
||||||
|
|
||||||
|
|
||||||
PRETTY = True
|
PRETTY = True
|
||||||
|
_hy_colored_ast_objects = _initialize_env_var('HY_COLORED_AST_OBJECTS', False)
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
@ -271,8 +272,9 @@ class HySequence(HyObject, list):
|
|||||||
return str(self) if PRETTY else super(HySequence, self).__repr__()
|
return str(self) if PRETTY else super(HySequence, self).__repr__()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
global _hy_colored_ast_objects
|
||||||
with pretty():
|
with pretty():
|
||||||
c = self.color
|
c = self.color if _hy_colored_ast_objects else str
|
||||||
if self:
|
if self:
|
||||||
return ("{}{}\n {}{}").format(
|
return ("{}{}\n {}{}").format(
|
||||||
c(self.__class__.__name__),
|
c(self.__class__.__name__),
|
||||||
@ -298,10 +300,12 @@ class HyDict(HySequence):
|
|||||||
"""
|
"""
|
||||||
HyDict (just a representation of a dict)
|
HyDict (just a representation of a dict)
|
||||||
"""
|
"""
|
||||||
|
color = staticmethod(colored.green)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
global _hy_colored_ast_objects
|
||||||
with pretty():
|
with pretty():
|
||||||
g = colored.green
|
g = self.color if _hy_colored_ast_objects else str
|
||||||
if self:
|
if self:
|
||||||
pairs = []
|
pairs = []
|
||||||
for k, v in zip(self[::2],self[1::2]):
|
for k, v in zip(self[::2],self[1::2]):
|
||||||
|
Loading…
Reference in New Issue
Block a user