You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ORPA-pyOpenRPA/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/nbconvert/filters/ansi.py

297 lines
7.8 KiB

"""Filters for processing ANSI colors within Jinja templates."""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
import re
import jinja2
__all__ = [
'strip_ansi',
'ansi2html',
'ansi2latex'
]
_ANSI_RE = re.compile('\x1b\\[(.*?)([@-~])')
_ANSI_COLORS = (
'ansi-black',
'ansi-red',
'ansi-green',
'ansi-yellow',
'ansi-blue',
'ansi-magenta',
'ansi-cyan',
'ansi-white',
'ansi-black-intense',
'ansi-red-intense',
'ansi-green-intense',
'ansi-yellow-intense',
'ansi-blue-intense',
'ansi-magenta-intense',
'ansi-cyan-intense',
'ansi-white-intense',
)
def strip_ansi(source):
"""
Remove ANSI escape codes from text.
Parameters
----------
source : str
Source to remove the ANSI from
"""
return _ANSI_RE.sub('', source)
def ansi2html(text):
"""
Convert ANSI colors to HTML colors.
Parameters
----------
text : unicode
Text containing ANSI colors to convert to HTML
"""
text = jinja2.utils.escape(text)
return _ansi2anything(text, _htmlconverter)
def ansi2latex(text):
"""
Convert ANSI colors to LaTeX colors.
Parameters
----------
text : unicode
Text containing ANSI colors to convert to LaTeX
"""
return _ansi2anything(text, _latexconverter)
def _htmlconverter(fg, bg, bold, underline, inverse):
"""
Return start and end tags for given foreground/background/bold/underline.
"""
if (fg, bg, bold, underline, inverse) == (None, None, False, False, False):
return '', ''
classes = []
styles = []
if inverse:
fg, bg = bg, fg
if isinstance(fg, int):
classes.append(_ANSI_COLORS[fg] + '-fg')
elif fg:
styles.append('color: rgb({},{},{})'.format(*fg))
elif inverse:
classes.append('ansi-default-inverse-fg')
if isinstance(bg, int):
classes.append(_ANSI_COLORS[bg] + '-bg')
elif bg:
styles.append('background-color: rgb({},{},{})'.format(*bg))
elif inverse:
classes.append('ansi-default-inverse-bg')
if bold:
classes.append('ansi-bold')
if underline:
classes.append('ansi-underline')
starttag = '<span'
if classes:
starttag += ' class="' + ' '.join(classes) + '"'
if styles:
starttag += ' style="' + '; '.join(styles) + '"'
starttag += '>'
return starttag, '</span>'
def _latexconverter(fg, bg, bold, underline, inverse):
"""
Return start and end markup given foreground/background/bold/underline.
"""
if (fg, bg, bold, underline, inverse) == (None, None, False, False, False):
return '', ''
starttag, endtag = '', ''
if inverse:
fg, bg = bg, fg
if isinstance(fg, int):
starttag += r'\textcolor{' + _ANSI_COLORS[fg] + '}{'
endtag = '}' + endtag
elif fg:
# See http://tex.stackexchange.com/a/291102/13684
starttag += r'\def\tcRGB{\textcolor[RGB]}\expandafter'
starttag += r'\tcRGB\expandafter{\detokenize{%s,%s,%s}}{' % fg
endtag = '}' + endtag
elif inverse:
starttag += r'\textcolor{ansi-default-inverse-fg}{'
endtag = '}' + endtag
if isinstance(bg, int):
starttag += r'\setlength{\fboxsep}{0pt}'
starttag += r'\colorbox{' + _ANSI_COLORS[bg] + '}{'
endtag = r'\strut}' + endtag
elif bg:
starttag += r'\setlength{\fboxsep}{0pt}'
# See http://tex.stackexchange.com/a/291102/13684
starttag += r'\def\cbRGB{\colorbox[RGB]}\expandafter'
starttag += r'\cbRGB\expandafter{\detokenize{%s,%s,%s}}{' % bg
endtag = r'\strut}' + endtag
elif inverse:
starttag += r'\setlength{\fboxsep}{0pt}'
starttag += r'\colorbox{ansi-default-inverse-bg}{'
endtag = r'\strut}' + endtag
if bold:
starttag += r'\textbf{'
endtag = '}' + endtag
if underline:
starttag += r'\underline{'
endtag = '}' + endtag
return starttag, endtag
def _ansi2anything(text, converter):
r"""
Convert ANSI colors to HTML or LaTeX.
See https://en.wikipedia.org/wiki/ANSI_escape_code
Accepts codes like '\x1b[32m' (red) and '\x1b[1;32m' (bold, red).
Non-color escape sequences (not ending with 'm') are filtered out.
Ideally, this should have the same behavior as the function
fixConsole() in notebook/notebook/static/base/js/utils.js.
"""
fg, bg = None, None
bold = False
underline = False
inverse = False
numbers = []
out = []
while text:
m = _ANSI_RE.search(text)
if m:
if m.group(2) == 'm':
try:
# Empty code is same as code 0
numbers = [int(n) if n else 0
for n in m.group(1).split(';')]
except ValueError:
pass # Invalid color specification
else:
pass # Not a color code
chunk, text = text[:m.start()], text[m.end():]
else:
chunk, text = text, ''
if chunk:
starttag, endtag = converter(
fg + 8 if bold and fg in range(8) else fg,
bg, bold, underline, inverse)
out.append(starttag)
out.append(chunk)
out.append(endtag)
while numbers:
n = numbers.pop(0)
if n == 0:
# Code 0 (same as empty code): reset everything
fg = bg = None
bold = underline = inverse = False
elif n == 1:
bold = True
elif n == 4:
underline = True
elif n == 5:
# Code 5: blinking
bold = True
elif n == 7:
inverse = True
elif n in (21, 22):
bold = False
elif n == 24:
underline = False
elif n == 27:
inverse = False
elif 30 <= n <= 37:
fg = n - 30
elif n == 38:
try:
fg = _get_extended_color(numbers)
except ValueError:
numbers.clear()
elif n == 39:
fg = None
elif 40 <= n <= 47:
bg = n - 40
elif n == 48:
try:
bg = _get_extended_color(numbers)
except ValueError:
numbers.clear()
elif n == 49:
bg = None
elif 90 <= n <= 97:
fg = n - 90 + 8
elif 100 <= n <= 107:
bg = n - 100 + 8
else:
pass # Unknown codes are ignored
return ''.join(out)
def _get_extended_color(numbers):
n = numbers.pop(0)
if n == 2 and len(numbers) >= 3:
# 24-bit RGB
r = numbers.pop(0)
g = numbers.pop(0)
b = numbers.pop(0)
if not all(0 <= c <= 255 for c in (r, g, b)):
raise ValueError()
elif n == 5 and len(numbers) >= 1:
# 256 colors
idx = numbers.pop(0)
if idx < 0:
raise ValueError()
elif idx < 16:
# 16 default terminal colors
return idx
elif idx < 232:
# 6x6x6 color cube, see http://stackoverflow.com/a/27165165/500098
r = (idx - 16) // 36
r = 55 + r * 40 if r > 0 else 0
g = ((idx - 16) % 36) // 6
g = 55 + g * 40 if g > 0 else 0
b = (idx - 16) % 6
b = 55 + b * 40 if b > 0 else 0
elif idx < 256:
# grayscale, see http://stackoverflow.com/a/27165165/500098
r = g = b = (idx - 232) * 10 + 8
else:
raise ValueError()
else:
raise ValueError()
return r, g, b