Skip to content

Commit

Permalink
Make colored output configurable
Browse files Browse the repository at this point in the history
Colored exception output is now disabled by default and configurable through
`hy.errors._hy_colored_errors` and the environment variable
`HY_FILTER_INTERNAL_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#1429, closes hylang#1510.
  • Loading branch information
brandonwillard committed Nov 29, 2018
1 parent fcd9149 commit 1ced1b2
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 25 deletions.
56 changes: 34 additions & 22 deletions hy/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
from functools import reduce
from contextlib import contextmanager

from clint.textui import colored


_hy_colored_errors = False
_hy_filter_internal_errors = True


Expand All @@ -22,6 +20,11 @@ def filter_errors():
_hy_filter_internal_errors)


def colored_errors():
global _hy_colored_errors
return os.environ.get('HY_COLORED_ERRORS', _hy_colored_errors)


class HyError(Exception):
def __init__(self, message, *args):
self.message = message
Expand Down Expand Up @@ -84,6 +87,13 @@ def __str__(self):
has_syntax_info = all(hasattr(self.expression, x)
for x in ("start_line", "start_column",
"end_column", "end_line"))

if colored_errors():
from clint.textui import colored
red, green, yellow = colored.red, colored.green, colored.yellow
else:
red = green = yellow = lambda x: x

if has_syntax_info:
line = self.expression.start_line
start = self.expression.start_column
Expand All @@ -103,28 +113,28 @@ def __str__(self):
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

Expand Down Expand Up @@ -209,14 +219,16 @@ def __str__(self):
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 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)
Expand Down
15 changes: 12 additions & 3 deletions hy/models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Copyright 2018 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

import os

from contextlib import contextmanager
from math import isnan, isinf
from hy._compat import PY3, str_type, bytes_type, long_type, string_types
Expand All @@ -11,6 +13,12 @@


PRETTY = True
_hy_colored_ast_objects = False


def colored_ast_objects():
global _hy_colored_ast_objects
return os.environ.get('HY_COLORED_AST_OBJECTS', _hy_colored_ast_objects)


@contextmanager
Expand Down Expand Up @@ -272,7 +280,7 @@ def __repr__(self):

def __str__(self):
with pretty():
c = self.color
c = self.color if colored_ast_objects() else str
if self:
return ("{}{}\n {}{}").format(
c(self.__class__.__name__),
Expand All @@ -298,10 +306,11 @@ class HyDict(HySequence):
"""
HyDict (just a representation of a dict)
"""
color = staticmethod(colored.green)

def __str__(self):
with pretty():
g = colored.green
g = self.color if colored_ast_objects() else str
if self:
pairs = []
for k, v in zip(self[::2],self[1::2]):
Expand Down

0 comments on commit 1ced1b2

Please sign in to comment.