summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Imhof <52650214+PhilippImhof@users.noreply.github.com>2021-03-05 08:32:49 +0100
committerGitHub <noreply@github.com>2021-03-05 08:32:49 +0100
commitfea3b53b834610e6004e65cb803a66feb512e906 (patch)
treed8ea338ae0a8cbe12e0765e2d0dbdb916780de0d
parentffac8bde66a1060a255334ff4fb0aaf42b825eff (diff)
downloadpygments-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--AUTHORS1
-rwxr-xr-xpygments/formatters/_mapping.py1
-rw-r--r--pygments/formatters/pangomarkup.py81
-rw-r--r--tests/test_pangomarkup_formatter.py45
4 files changed, 128 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
index e86b35b2..7f36b9d0 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -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('&'): '&amp;',
+ ord('<'): '&lt;',
+}
+
+
+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="#">&amp;</span> b;
+ }
+ <span fgcolor="#"><b>if</b></span> (a <span fgcolor="#">&lt;</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)