#!/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