diff options
author | blackbird <devnull@localhost> | 2006-12-16 00:54:28 +0100 |
---|---|---|
committer | blackbird <devnull@localhost> | 2006-12-16 00:54:28 +0100 |
commit | 8de4ac49b28dc5740cad1ff625ce7b413aaaeac7 (patch) | |
tree | 77691102bf3b5d5892d193fc23934eea1e4c488f /pygments/formatters/rtf.py | |
parent | 48b76b387fb567365f31b1cc1a1137af31abe67e (diff) | |
download | pygments-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.py | 121 |
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('}') |