ThirdParty/Pygments/pygments/formatters/rtf.py

changeset 0
de9c2efb9d02
child 684
2f29a0b6e1c7
equal deleted inserted replaced
-1:000000000000 0:de9c2efb9d02
1 # -*- coding: utf-8 -*-
2 """
3 pygments.formatters.rtf
4 ~~~~~~~~~~~~~~~~~~~~~~~
5
6 A formatter that generates RTF files.
7
8 :copyright: Copyright 2006-2009 by the Pygments team, see AUTHORS.
9 :license: BSD, see LICENSE for details.
10 """
11
12 from pygments.formatter import Formatter
13
14
15 __all__ = ['RtfFormatter']
16
17
18 class RtfFormatter(Formatter):
19 """
20 Format tokens as RTF markup. This formatter automatically outputs full RTF
21 documents with color information and other useful stuff. Perfect for Copy and
22 Paste into Microsoft® Word® documents.
23
24 *New in Pygments 0.6.*
25
26 Additional options accepted:
27
28 `style`
29 The style to use, can be a string or a Style subclass (default:
30 ``'default'``).
31
32 `fontface`
33 The used font famliy, for example ``Bitstream Vera Sans``. Defaults to
34 some generic font which is supposed to have fixed width.
35 """
36 name = 'RTF'
37 aliases = ['rtf']
38 filenames = ['*.rtf']
39
40 unicodeoutput = False
41
42 def __init__(self, **options):
43 """
44 Additional options accepted:
45
46 ``fontface``
47 Name of the font used. Could for example be ``'Courier New'``
48 to further specify the default which is ``'\fmodern'``. The RTF
49 specification claims that ``\fmodern`` are "Fixed-pitch serif
50 and sans serif fonts". Hope every RTF implementation thinks
51 the same about modern...
52 """
53 Formatter.__init__(self, **options)
54 self.fontface = options.get('fontface') or ''
55
56 def _escape(self, text):
57 return text.replace('\\', '\\\\') \
58 .replace('{', '\\{') \
59 .replace('}', '\\}')
60
61 def _escape_text(self, text):
62 # empty strings, should give a small performance improvment
63 if not text:
64 return ''
65
66 # escape text
67 text = self._escape(text)
68 if self.encoding in ('utf-8', 'utf-16', 'utf-32'):
69 encoding = 'iso-8859-15'
70 else:
71 encoding = self.encoding or 'iso-8859-15'
72
73 buf = []
74 for c in text:
75 if ord(c) > 128:
76 ansic = c.encode(encoding, 'ignore') or '?'
77 if ord(ansic) > 128:
78 ansic = '\\\'%x' % ord(ansic)
79 else:
80 ansic = c
81 buf.append(r'\ud{\u%d%s}' % (ord(c), ansic))
82 else:
83 buf.append(str(c))
84
85 return ''.join(buf).replace('\n', '\\par\n')
86
87 def format_unencoded(self, tokensource, outfile):
88 # rtf 1.8 header
89 outfile.write(r'{\rtf1\ansi\deff0'
90 r'{\fonttbl{\f0\fmodern\fprq1\fcharset0%s;}}'
91 r'{\colortbl;' % (self.fontface and
92 ' ' + self._escape(self.fontface) or
93 ''))
94
95 # convert colors and save them in a mapping to access them later.
96 color_mapping = {}
97 offset = 1
98 for _, style in self.style:
99 for color in style['color'], style['bgcolor'], style['border']:
100 if color and color not in color_mapping:
101 color_mapping[color] = offset
102 outfile.write(r'\red%d\green%d\blue%d;' % (
103 int(color[0:2], 16),
104 int(color[2:4], 16),
105 int(color[4:6], 16)
106 ))
107 offset += 1
108 outfile.write(r'}\f0')
109
110 # highlight stream
111 for ttype, value in tokensource:
112 while not self.style.styles_token(ttype) and ttype.parent:
113 ttype = ttype.parent
114 style = self.style.style_for_token(ttype)
115 buf = []
116 if style['bgcolor']:
117 buf.append(r'\cb%d' % color_mapping[style['bgcolor']])
118 if style['color']:
119 buf.append(r'\cf%d' % color_mapping[style['color']])
120 if style['bold']:
121 buf.append(r'\b')
122 if style['italic']:
123 buf.append(r'\i')
124 if style['underline']:
125 buf.append(r'\ul')
126 if style['border']:
127 buf.append(r'\chbrdr\chcfpat%d' %
128 color_mapping[style['border']])
129 start = ''.join(buf)
130 if start:
131 outfile.write('{%s ' % start)
132 outfile.write(self._escape_text(value))
133 if start:
134 outfile.write('}')
135
136 outfile.write('}')

eric ide

mercurial