diff options
author | Philipp Imhof <52650214+PhilippImhof@users.noreply.github.com> | 2021-03-05 08:32:49 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-05 08:32:49 +0100 |
commit | fea3b53b834610e6004e65cb803a66feb512e906 (patch) | |
tree | d8ea338ae0a8cbe12e0765e2d0dbdb916780de0d | |
parent | ffac8bde66a1060a255334ff4fb0aaf42b825eff (diff) | |
download | pygments-git-fea3b53b834610e6004e65cb803a66feb512e906.tar.gz |
Add formatter for Pango Markup (#1727)
* Add formatter for Pango Markup
* Code style improvement
* Code improvement + test case
* Changed test
* retrigger checks
* Make test independent of color style
-rw-r--r-- | AUTHORS | 1 | ||||
-rwxr-xr-x | pygments/formatters/_mapping.py | 1 | ||||
-rw-r--r-- | pygments/formatters/pangomarkup.py | 81 | ||||
-rw-r--r-- | tests/test_pangomarkup_formatter.py | 45 |
4 files changed, 128 insertions, 0 deletions
@@ -239,5 +239,6 @@ Other contributors, listed alphabetically, are: * 15b3 -- Image Formatter improvements * Fabian Neumann -- CDDL lexer * Thomas Duboucher -- CDDL lexer +* Philipp Imhof -- Pango Markup formatter Many thanks for all contributions! diff --git a/pygments/formatters/_mapping.py b/pygments/formatters/_mapping.py index 2592ef82..9a8ab84a 100755 --- a/pygments/formatters/_mapping.py +++ b/pygments/formatters/_mapping.py @@ -22,6 +22,7 @@ FORMATTERS = { 'JpgImageFormatter': ('pygments.formatters.img', 'img_jpg', ('jpg', 'jpeg'), ('*.jpg',), 'Create a JPEG image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'), 'LatexFormatter': ('pygments.formatters.latex', 'LaTeX', ('latex', 'tex'), ('*.tex',), 'Format tokens as LaTeX code. This needs the `fancyvrb` and `color` standard packages.'), 'NullFormatter': ('pygments.formatters.other', 'Text only', ('text', 'null'), ('*.txt',), 'Output the text unchanged without any formatting.'), + 'PangoMarkupFormatter': ('pygments.formatters.pangomarkup', 'Pango Markup', ('pango', 'pangomarkup'), (), 'Format tokens as Pango Markup code. It can then be rendered to an SVG.'), 'RawTokenFormatter': ('pygments.formatters.other', 'Raw tokens', ('raw', 'tokens'), ('*.raw',), 'Format tokens as a raw representation for storing token streams.'), 'RtfFormatter': ('pygments.formatters.rtf', 'RTF', ('rtf',), ('*.rtf',), 'Format tokens as RTF markup. This formatter automatically outputs full RTF documents with color information and other useful stuff. Perfect for Copy and Paste into Microsoft(R) Word(R) documents.'), 'SvgFormatter': ('pygments.formatters.svg', 'SVG', ('svg',), ('*.svg',), 'Format tokens as an SVG graphics file. This formatter is still experimental. Each line of code is a ``<text>`` element with explicit ``x`` and ``y`` coordinates containing ``<tspan>`` elements with the individual token styles.'), diff --git a/pygments/formatters/pangomarkup.py b/pygments/formatters/pangomarkup.py new file mode 100644 index 00000000..387b3e91 --- /dev/null +++ b/pygments/formatters/pangomarkup.py @@ -0,0 +1,81 @@ +""" + pygments.formatters.pango + ~~~~~~~~~~~~~~~~~~~~~~~~ + + Formatter for Pango markup output. + + :copyright: Copyright 2006-2021 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +from pygments.formatter import Formatter + + +__all__ = ['PangoMarkupFormatter'] + + +_escape_table = { + ord('&'): '&', + ord('<'): '<', +} + + +def escape_special_chars(text, table=_escape_table): + """Escape & and < for Pango Markup.""" + return text.translate(table) + + +class PangoMarkupFormatter(Formatter): + """ + Format tokens as Pango Markup code. It can then be rendered to an SVG. + """ + + name = 'Pango Markup' + aliases = ['pango', 'pangomarkup'] + filenames = [] + + def __init__(self, **options): + Formatter.__init__(self, **options) + + self.styles = {} + + for token, style in self.style: + start = '' + end = '' + if style['color']: + start += '<span fgcolor="#%s">' % style['color'] + end = '</span>' + end + if style['bold']: + start += '<b>' + end = '</b>' + end + if style['italic']: + start += '<i>' + end = '</i>' + end + if style['underline']: + start += '<u>' + end = '</u>' + end + self.styles[token] = (start, end) + + def format_unencoded(self, tokensource, outfile): + lastval = '' + lasttype = None + + outfile.write('<tt>') + + for ttype, value in tokensource: + while ttype not in self.styles: + ttype = ttype.parent + if ttype == lasttype: + lastval += escape_special_chars(value) + else: + if lastval: + stylebegin, styleend = self.styles[lasttype] + outfile.write(stylebegin + lastval + styleend) + lastval = escape_special_chars(value) + lasttype = ttype + + if lastval: + stylebegin, styleend = self.styles[lasttype] + outfile.write(stylebegin + lastval + styleend) + + outfile.write('</tt>') diff --git a/tests/test_pangomarkup_formatter.py b/tests/test_pangomarkup_formatter.py new file mode 100644 index 00000000..f4543826 --- /dev/null +++ b/tests/test_pangomarkup_formatter.py @@ -0,0 +1,45 @@ +""" + Pygments Pango Markup formatter tests + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :copyright: Copyright 2006-2021 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import pytest +import re + +from pygments import highlight +from pygments.formatters import PangoMarkupFormatter +from pygments.lexers import JavascriptLexer + +INPUT = r""" +function foobar(a, b) { + if (a > b) { + return a & b; + } + if (a < b) { + return true; + } + console.log("single quote ' and double quote \"") + console.log('single quote \' and double quote "') + // comment with äöü ç +} +""" + +OUTPUT = r"""<tt><span fgcolor="#"><b>function</b></span> foobar(a, b) { + <span fgcolor="#"><b>if</b></span> (a <span fgcolor="#">></span> b) { + <span fgcolor="#"><b>return</b></span> a <span fgcolor="#">&</span> b; + } + <span fgcolor="#"><b>if</b></span> (a <span fgcolor="#"><</span> b) { + <span fgcolor="#"><b>return</b></span> <span fgcolor="#"><b>true</b></span>; + } + console.log(<span fgcolor="#">"single quote ' and double quote \""</span>) + console.log(<span fgcolor="#">'single quote \' and double quote "'</span>) + <span fgcolor="#"><i>// comment with äöü ç +</i></span>} +</tt>""" + +def test_correct_output(): + markup = highlight(INPUT, JavascriptLexer(), PangoMarkupFormatter()) + assert OUTPUT == re.sub('<span fgcolor="#[^"]{6}">', '<span fgcolor="#">', markup) |