Merge pull request #16 from adrienverge/coloured_output_on_tty

feat(cli): Colour output only on TTY
pull/12/merge
Adrien Vergé 9 years ago committed by GitHub
commit 82dd7dbf16

@ -18,8 +18,10 @@ try:
from cStringIO import StringIO from cStringIO import StringIO
except ImportError: except ImportError:
from io import StringIO from io import StringIO
import fcntl
import locale import locale
import os import os
import pty
import shutil import shutil
import tempfile import tempfile
import unittest import unittest
@ -308,7 +310,7 @@ class CommandLineTestCase(unittest.TestCase):
'(key-duplicates)\n') % file) '(key-duplicates)\n') % file)
self.assertEqual(err, '') self.assertEqual(err, '')
def test_run_colored_output(self): def test_run_piped_output_nocolor(self):
file = os.path.join(self.wd, 'a.yaml') file = os.path.join(self.wd, 'a.yaml')
sys.stdout, sys.stderr = StringIO(), StringIO() sys.stdout, sys.stderr = StringIO(), StringIO()
@ -318,6 +320,38 @@ class CommandLineTestCase(unittest.TestCase):
self.assertEqual(ctx.exception.code, 1) self.assertEqual(ctx.exception.code, 1)
out, err = sys.stdout.getvalue(), sys.stderr.getvalue() out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertEqual(out, (
'%s\n'
' 2:4 error trailing spaces (trailing-spaces)\n'
' 3:4 error no new line character at the end of file '
'(new-line-at-end-of-file)\n'
'\n' % file))
self.assertEqual(err, '')
def test_run_colored_output(self):
file = os.path.join(self.wd, 'a.yaml')
# Create a pseudo-TTY and redirect stdout to it
master, slave = pty.openpty()
sys.stdout = sys.stderr = os.fdopen(slave, 'w')
with self.assertRaises(SystemExit) as ctx:
cli.run((file, ))
sys.stdout.flush()
self.assertEqual(ctx.exception.code, 1)
# Read output from TTY
output = os.fdopen(master, 'r')
flag = fcntl.fcntl(master, fcntl.F_GETFD)
fcntl.fcntl(master, fcntl.F_SETFL, flag | os.O_NONBLOCK)
out = output.read().replace('\r\n', '\n')
sys.stdout.close()
sys.stderr.close()
output.close()
self.assertEqual(out, ( self.assertEqual(out, (
'\033[4m%s\033[0m\n' '\033[4m%s\033[0m\n'
' \033[2m2:4\033[0m \033[31merror\033[0m ' ' \033[2m2:4\033[0m \033[31merror\033[0m '
@ -326,4 +360,3 @@ class CommandLineTestCase(unittest.TestCase):
'no new line character at the end of file ' 'no new line character at the end of file '
'\033[2m(new-line-at-end-of-file)\033[0m\n' '\033[2m(new-line-at-end-of-file)\033[0m\n'
'\n' % file)) '\n' % file))
self.assertEqual(err, '')

@ -48,6 +48,17 @@ class Format(object):
@staticmethod @staticmethod
def standard(problem, filename): def standard(problem, filename):
line = ' %d:%d' % (problem.line, problem.column)
line += max(12 - len(line), 0) * ' '
line += problem.level
line += max(21 - len(line), 0) * ' '
line += problem.desc
if problem.rule:
line += ' (%s)' % problem.rule
return line
@staticmethod
def standard_color(problem, filename):
line = ' \033[2m%d:%d\033[0m' % (problem.line, problem.column) line = ' \033[2m%d:%d\033[0m' % (problem.line, problem.column)
line += max(20 - len(line), 0) * ' ' line += max(20 - len(line), 0) * ' '
if problem.level == 'warning': if problem.level == 'warning':
@ -119,11 +130,17 @@ def run(argv=None):
for problem in linter.run(f, conf): for problem in linter.run(f, conf):
if args.format == 'parsable': if args.format == 'parsable':
print(Format.parsable(problem, file)) print(Format.parsable(problem, file))
else: elif sys.stdout.isatty():
if first: if first:
print('\033[4m%s\033[0m' % file) print('\033[4m%s\033[0m' % file)
first = False first = False
print(Format.standard_color(problem, file))
else:
if first:
print(file)
first = False
print(Format.standard(problem, file)) print(Format.standard(problem, file))
if return_code == 0 and problem.level == 'error': if return_code == 0 and problem.level == 'error':

Loading…
Cancel
Save