summaryrefslogtreecommitdiff
path: root/pygments/formatters/rtf.py
diff options
context:
space:
mode:
authorblackbird <devnull@localhost>2006-12-16 00:54:28 +0100
committerblackbird <devnull@localhost>2006-12-16 00:54:28 +0100
commit8de4ac49b28dc5740cad1ff625ce7b413aaaeac7 (patch)
tree77691102bf3b5d5892d193fc23934eea1e4c488f /pygments/formatters/rtf.py
parent48b76b387fb567365f31b1cc1a1137af31abe67e (diff)
downloadpygments-8de4ac49b28dc5740cad1ff625ce7b413aaaeac7.tar.gz
[svn] added rich text formatter (formatter for one of the worst file formats ever created)
Diffstat (limited to 'pygments/formatters/rtf.py')
-rw-r--r--pygments/formatters/rtf.py121
1 files changed, 121 insertions, 0 deletions
diff --git a/pygments/formatters/rtf.py b/pygments/formatters/rtf.py
new file mode 100644
index 00000000..70c12e66
--- /dev/null
+++ b/pygments/formatters/rtf.py
@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+"""
+ pygments.formatters.rtf
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ A formatter that generates RTF files.
+
+ :copyright: 2006 by Armin Ronacher.
+ :license: BSD, see LICENSE for more details.
+"""
+import cStringIO
+
+from pygments.formatter import Formatter
+from pygments.token import Token
+from pygments.util import get_bool_opt, get_int_opt
+
+
+__all__ = ['RtfFormatter']
+
+
+class RtfFormatter(Formatter):
+
+ def __init__(self, **options):
+ """
+ Additional options accepted:
+
+ ``fontface``
+ Name of the font used. Could for example be ``'Courier New'``
+ to further specify the default which is ``'\fmodern'``. The RTF
+ specification claims that ``\fmodern`` are "Fixed-pitch serif
+ and sans serif fonts". Hope every RTF implementation thinks
+ the same about modern...
+
+
+ """
+ Formatter.__init__(self, **options)
+ self.fontface = options.get('fontface') or ''
+
+ def _escape(self, text):
+ return text.replace('\\', '\\\\') \
+ .replace('{', '\\{') \
+ .replace('}', '\\}')
+
+ def _escape_text(self, text):
+ # empty strings, should give a small performance improvment
+ if not text:
+ return ''
+
+ # escape text
+ text = self._escape(text)
+
+ # byte strings
+ if isinstance(text, str):
+ for c in xrange(128, 256):
+ text = text.replace(chr(c), '\\\'%x' % c)
+
+ # unicode strings
+ elif isinstance(text, unicode):
+ buf = []
+ for c in text:
+ o = ord(c)
+ if o > 128:
+ ansic = c.encode('iso-8859-1', 'ignore') or '?'
+ if ord(ansic) > 128:
+ ansic = '\\\'%x' % ord(ansic)
+ buf.append(r'\ud{\u%d%s}' % (o, ansic))
+ else:
+ buf.append(str(c))
+ text = ''.join(buf)
+
+ return text.replace('\n', '\\par\n')
+
+ def format(self, tokensource, outfile):
+ outfile.write(r'{\rtf1\ansi\deff0'
+ r'{\fonttbl{\f0\fmodern\fprq1\fcharset0%s;}}{\colortbl;' %
+ (self.fontface and ' ' + self._escape(self.fontface) or ''))
+
+ # convert colors and save them in a mapping to access them later.
+ color_mapping = {}
+ offset = 1
+ for _, style in self.style:
+ for color in style['color'], style['bgcolor'], style['border']:
+ if not color or color in color_mapping:
+ continue
+ color_mapping[color] = offset
+ outfile.write(r'\red%d\green%d\blue%d;' % (
+ int(color[0:2], 16),
+ int(color[2:4], 16),
+ int(color[4:6], 16)
+ ))
+ offset += 1
+ outfile.write(r'}\f0')
+
+ # highlight stream
+ for ttype, value in tokensource:
+ try:
+ style = self.style.style_for_token(ttype)
+ except KeyError:
+ start = ''
+ else:
+ buf = []
+ if style['bgcolor']:
+ buf.append(r'\cb%d' % color_mapping[style['bgcolor']])
+ if style['color']:
+ buf.append(r'\cf%d' % color_mapping[style['color']])
+ if style['bold']:
+ buf.append(r'\b')
+ if style['italic']:
+ buf.append(r'\i')
+ if style['underline']:
+ buf.append(r'\ul')
+ if style['border']:
+ buf.append(r'\chbrdr\chcfpat%d' % color_mapping[style['border']])
+ start = ''.join(buf)
+ if start:
+ outfile.write('{%s ' % start)
+ outfile.write(self._escape_text(value))
+ if start:
+ outfile.write('}')
+
+ outfile.write('}')