#!/usr/bin/env python
# This file was taken from:
# https://github.com/Kronuz/ansi2html/blob/master/ansi2html.py
# Copyright © 2013 German M. Bravo (Kronuz)
# License: https://github.com/Kronuz/ansi2html/blob/master/LICENSE
# Changes made to original file: removed main, added run() function.
from __future__ import print_function
import re
import sys
_ANSI2HTML_STYLES = {}
# pylint: disable=anomalous-backslash-in-string
ANSI2HTML_CODES_RE = re.compile('(?:\033\\[(\\d+(?:;\\d+)*)?([cnRhlABCDfsurgKJipm]))')
ANSI2HTML_PALETTE = {
# See http://ethanschoonover.com/solarized
'solarized': ['#073642', '#D30102', '#859900', '#B58900', '#268BD2', '#D33682', '#2AA198',
'#EEE8D5', '#002B36', '#CB4B16', '#586E75', '#657B83', '#839496', '#6C71C4',
'#93A1A1', '#FDF6E3'],
# Above mapped onto the xterm 256 color palette
'solarized-xterm': ['#262626', '#AF0000', '#5F8700', '#AF8700', '#0087FF', '#AF005F',
'#00AFAF', '#E4E4E4', '#1C1C1C', '#D75F00', '#585858', '#626262',
'#808080', '#5F5FAF', '#8A8A8A', '#FFFFD7'],
# Gnome default:
'tango': ['#000000', '#CC0000', '#4E9A06', '#C4A000', '#3465A4', '#75507B', '#06989A',
'#D3D7CF', '#555753', '#EF2929', '#8AE234', '#FCE94F', '#729FCF', '#AD7FA8',
'#34E2E2', '#EEEEEC'],
# xterm:
'xterm': ['#000000', '#CD0000', '#00CD00', '#CDCD00', '#0000EE', '#CD00CD', '#00CDCD',
'#E5E5E5', '#7F7F7F', '#FF0000', '#00FF00', '#FFFF00', '#5C5CFF', '#FF00FF',
'#00FFFF', '#FFFFFF'],
'console': ['#000000', '#AA0000', '#00AA00', '#AA5500', '#0000AA', '#AA00AA', '#00AAAA',
'#AAAAAA', '#555555', '#FF5555', '#55FF55', '#FFFF55', '#5555FF', '#FF55FF',
'#55FFFF', '#FFFFFF'],
}
def _ansi2html_get_styles(palette):
if palette not in _ANSI2HTML_STYLES:
p = ANSI2HTML_PALETTE.get(palette, ANSI2HTML_PALETTE['console'])
regular_style = {
'1': '', # bold
'2': 'opacity:0.5',
'4': 'text-decoration:underline',
'5': 'font-weight:bold',
'7': '',
'8': 'display:none',
}
bold_style = regular_style.copy()
for i in range(8):
regular_style['3%s' % i] = 'color:%s' % p[i]
regular_style['4%s' % i] = 'background-color:%s' % p[i]
bold_style['3%s' % i] = 'color:%s' % p[i + 8]
bold_style['4%s' % i] = 'background-color:%s' % p[i + 8]
# The default xterm 256 colour p:
indexed_style = {}
for i in range(16):
indexed_style['%s' % i] = p[i]
for rr in range(6):
for gg in range(6):
for bb in range(6):
i = 16 + rr * 36 + gg * 6 + bb
r = (rr * 40 + 55) if rr else 0
g = (gg * 40 + 55) if gg else 0
b = (bb * 40 + 55) if bb else 0
indexed_style['%s' % i] = ''.join(
'%02X' % c if 0 <= c <= 255 else None for c in (r, g, b))
for g in range(24):
i = g + 232
j = g * 10 + 8
indexed_style['%s' % i] = ''.join(
'%02X' % c if 0 <= c <= 255 else None for c in (j, j, j))
_ANSI2HTML_STYLES[palette] = (regular_style, bold_style, indexed_style)
return _ANSI2HTML_STYLES[palette]
[docs]def ansi2html(text, palette='solarized'):
# pylint: disable=too-many-branches, too-many-statements
def _ansi2html(m):
if m.group(2) != 'm':
return ''
state = None
sub = ''
cs = m.group(1)
cs = cs.strip() if cs else ''
for c in cs.split(';'):
c = c.strip().lstrip('0') or '0'
if c == '0':
while stack:
sub += '</span>'
stack.pop()
elif c in ('38', '48'):
extra = [c]
state = 'extra'
elif state == 'extra':
if c == '5':
state = 'idx'
elif c == '2':
state = 'r'
elif state:
if state == 'idx':
extra.append(c)
state = None
color = indexed_style.get(c) # 256 colors
if color is not None:
sub += \
'<span style="%s:%s">' % \
('color' if extra[0] == '38' else 'background-color', color)
stack.append(extra)
elif state in ('r', 'g', 'b'):
extra.append(c)
if state == 'r':
state = 'g'
elif state == 'g':
state = 'b'
else:
state = None
try:
color = '#' + ''.join(
'%02X' % c if 0 <= c <= 255 else None for x in extra for c in
[int(x)])
except (ValueError, TypeError):
pass
else:
sub += \
'<span style="%s:%s">' % \
('color' if extra[0] == '38' else 'background-color', color)
stack.append(extra)
else:
if '1' in stack:
style = bold_style.get(c)
else:
style = regular_style.get(c)
if style is not None:
sub += '<span style="%s">' % style
stack.append(c) # Still needs to be added to the stack even if style is empty
# (so it can check '1' in stack above, for example)
return sub
stack = []
regular_style, bold_style, indexed_style = _ansi2html_get_styles(palette)
sub = ANSI2HTML_CODES_RE.sub(_ansi2html, text)
while stack:
sub += '</span>'
stack.pop()
return sub
[docs]def run(file, out):
try:
html = ''
try:
with open(file) as fp:
html += '<pre>' + ansi2html(fp.read()) + '</pre>'
except IOError:
print("File not found: %r" % 'pylint.txt', file=sys.stderr)
with open(out, 'w') as out_fp:
out_fp.write(html)
except KeyboardInterrupt:
pass