pygmentize 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/LICENSE +19 -0
  2. data/lib/pygments.rb +23 -0
  3. data/pygmentize.gemspec +11 -0
  4. data/test/pygments.rb +19 -0
  5. data/vendor/pygmentize.py +7 -0
  6. data/vendor/pygments/AUTHORS +73 -0
  7. data/vendor/pygments/LICENSE +25 -0
  8. data/vendor/pygments/__init__.py +91 -0
  9. data/vendor/pygments/__init__.pyc +0 -0
  10. data/vendor/pygments/cmdline.py +430 -0
  11. data/vendor/pygments/cmdline.pyc +0 -0
  12. data/vendor/pygments/console.py +74 -0
  13. data/vendor/pygments/console.pyc +0 -0
  14. data/vendor/pygments/filter.py +74 -0
  15. data/vendor/pygments/filter.pyc +0 -0
  16. data/vendor/pygments/filters/__init__.py +357 -0
  17. data/vendor/pygments/filters/__init__.pyc +0 -0
  18. data/vendor/pygments/formatter.py +92 -0
  19. data/vendor/pygments/formatter.pyc +0 -0
  20. data/vendor/pygments/formatters/__init__.py +68 -0
  21. data/vendor/pygments/formatters/__init__.pyc +0 -0
  22. data/vendor/pygments/formatters/_mapping.py +92 -0
  23. data/vendor/pygments/formatters/_mapping.pyc +0 -0
  24. data/vendor/pygments/formatters/bbcode.py +109 -0
  25. data/vendor/pygments/formatters/bbcode.pyc +0 -0
  26. data/vendor/pygments/formatters/html.py +723 -0
  27. data/vendor/pygments/formatters/html.pyc +0 -0
  28. data/vendor/pygments/formatters/img.py +553 -0
  29. data/vendor/pygments/formatters/img.pyc +0 -0
  30. data/vendor/pygments/formatters/latex.py +354 -0
  31. data/vendor/pygments/formatters/latex.pyc +0 -0
  32. data/vendor/pygments/formatters/other.py +117 -0
  33. data/vendor/pygments/formatters/other.pyc +0 -0
  34. data/vendor/pygments/formatters/rtf.py +136 -0
  35. data/vendor/pygments/formatters/rtf.pyc +0 -0
  36. data/vendor/pygments/formatters/svg.py +154 -0
  37. data/vendor/pygments/formatters/svg.pyc +0 -0
  38. data/vendor/pygments/formatters/terminal.py +109 -0
  39. data/vendor/pygments/formatters/terminal.pyc +0 -0
  40. data/vendor/pygments/formatters/terminal256.py +219 -0
  41. data/vendor/pygments/formatters/terminal256.pyc +0 -0
  42. data/vendor/pygments/lexer.py +660 -0
  43. data/vendor/pygments/lexer.pyc +0 -0
  44. data/vendor/pygments/lexers/__init__.py +226 -0
  45. data/vendor/pygments/lexers/__init__.pyc +0 -0
  46. data/vendor/pygments/lexers/_asybuiltins.py +1645 -0
  47. data/vendor/pygments/lexers/_clbuiltins.py +232 -0
  48. data/vendor/pygments/lexers/_luabuiltins.py +256 -0
  49. data/vendor/pygments/lexers/_mapping.py +234 -0
  50. data/vendor/pygments/lexers/_mapping.pyc +0 -0
  51. data/vendor/pygments/lexers/_phpbuiltins.py +3389 -0
  52. data/vendor/pygments/lexers/_vimbuiltins.py +3 -0
  53. data/vendor/pygments/lexers/agile.py +1485 -0
  54. data/vendor/pygments/lexers/agile.pyc +0 -0
  55. data/vendor/pygments/lexers/asm.py +353 -0
  56. data/vendor/pygments/lexers/compiled.py +2365 -0
  57. data/vendor/pygments/lexers/dotnet.py +355 -0
  58. data/vendor/pygments/lexers/functional.py +756 -0
  59. data/vendor/pygments/lexers/functional.pyc +0 -0
  60. data/vendor/pygments/lexers/math.py +461 -0
  61. data/vendor/pygments/lexers/other.py +2297 -0
  62. data/vendor/pygments/lexers/parsers.py +695 -0
  63. data/vendor/pygments/lexers/special.py +100 -0
  64. data/vendor/pygments/lexers/special.pyc +0 -0
  65. data/vendor/pygments/lexers/templates.py +1387 -0
  66. data/vendor/pygments/lexers/text.py +1586 -0
  67. data/vendor/pygments/lexers/web.py +1619 -0
  68. data/vendor/pygments/lexers/web.pyc +0 -0
  69. data/vendor/pygments/plugin.py +74 -0
  70. data/vendor/pygments/plugin.pyc +0 -0
  71. data/vendor/pygments/scanner.py +104 -0
  72. data/vendor/pygments/style.py +117 -0
  73. data/vendor/pygments/style.pyc +0 -0
  74. data/vendor/pygments/styles/__init__.py +68 -0
  75. data/vendor/pygments/styles/__init__.pyc +0 -0
  76. data/vendor/pygments/styles/autumn.py +65 -0
  77. data/vendor/pygments/styles/borland.py +51 -0
  78. data/vendor/pygments/styles/bw.py +49 -0
  79. data/vendor/pygments/styles/colorful.py +81 -0
  80. data/vendor/pygments/styles/default.py +73 -0
  81. data/vendor/pygments/styles/default.pyc +0 -0
  82. data/vendor/pygments/styles/emacs.py +72 -0
  83. data/vendor/pygments/styles/friendly.py +72 -0
  84. data/vendor/pygments/styles/fruity.py +43 -0
  85. data/vendor/pygments/styles/manni.py +75 -0
  86. data/vendor/pygments/styles/monokai.py +106 -0
  87. data/vendor/pygments/styles/murphy.py +80 -0
  88. data/vendor/pygments/styles/native.py +65 -0
  89. data/vendor/pygments/styles/pastie.py +75 -0
  90. data/vendor/pygments/styles/perldoc.py +69 -0
  91. data/vendor/pygments/styles/tango.py +141 -0
  92. data/vendor/pygments/styles/trac.py +63 -0
  93. data/vendor/pygments/styles/vim.py +63 -0
  94. data/vendor/pygments/styles/vs.py +38 -0
  95. data/vendor/pygments/token.py +198 -0
  96. data/vendor/pygments/token.pyc +0 -0
  97. data/vendor/pygments/unistring.py +130 -0
  98. data/vendor/pygments/unistring.pyc +0 -0
  99. data/vendor/pygments/util.py +226 -0
  100. data/vendor/pygments/util.pyc +0 -0
  101. metadata +166 -0
@@ -0,0 +1,92 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ pygments.formatter
4
+ ~~~~~~~~~~~~~~~~~~
5
+
6
+ Base formatter class.
7
+
8
+ :copyright: Copyright 2006-2010 by the Pygments team, see AUTHORS.
9
+ :license: BSD, see LICENSE for details.
10
+ """
11
+
12
+ import codecs
13
+
14
+ from pygments.util import get_bool_opt
15
+ from pygments.styles import get_style_by_name
16
+
17
+ __all__ = ['Formatter']
18
+
19
+
20
+ def _lookup_style(style):
21
+ if isinstance(style, basestring):
22
+ return get_style_by_name(style)
23
+ return style
24
+
25
+
26
+ class Formatter(object):
27
+ """
28
+ Converts a token stream to text.
29
+
30
+ Options accepted:
31
+
32
+ ``style``
33
+ The style to use, can be a string or a Style subclass
34
+ (default: "default"). Not used by e.g. the
35
+ TerminalFormatter.
36
+ ``full``
37
+ Tells the formatter to output a "full" document, i.e.
38
+ a complete self-contained document. This doesn't have
39
+ any effect for some formatters (default: false).
40
+ ``title``
41
+ If ``full`` is true, the title that should be used to
42
+ caption the document (default: '').
43
+ ``encoding``
44
+ If given, must be an encoding name. This will be used to
45
+ convert the Unicode token strings to byte strings in the
46
+ output. If it is "" or None, Unicode strings will be written
47
+ to the output file, which most file-like objects do not
48
+ support (default: None).
49
+ ``outencoding``
50
+ Overrides ``encoding`` if given.
51
+ """
52
+
53
+ #: Name of the formatter
54
+ name = None
55
+
56
+ #: Shortcuts for the formatter
57
+ aliases = []
58
+
59
+ #: fn match rules
60
+ filenames = []
61
+
62
+ #: If True, this formatter outputs Unicode strings when no encoding
63
+ #: option is given.
64
+ unicodeoutput = True
65
+
66
+ def __init__(self, **options):
67
+ self.style = _lookup_style(options.get('style', 'default'))
68
+ self.full = get_bool_opt(options, 'full', False)
69
+ self.title = options.get('title', '')
70
+ self.encoding = options.get('encoding', None) or None
71
+ self.encoding = options.get('outencoding', None) or self.encoding
72
+ self.options = options
73
+
74
+ def get_style_defs(self, arg=''):
75
+ """
76
+ Return the style definitions for the current style as a string.
77
+
78
+ ``arg`` is an additional argument whose meaning depends on the
79
+ formatter used. Note that ``arg`` can also be a list or tuple
80
+ for some formatters like the html formatter.
81
+ """
82
+ return ''
83
+
84
+ def format(self, tokensource, outfile):
85
+ """
86
+ Format ``tokensource``, an iterable of ``(tokentype, tokenstring)``
87
+ tuples and write it into ``outfile``.
88
+ """
89
+ if self.encoding:
90
+ # wrap the outfile in a StreamWriter
91
+ outfile = codecs.lookup(self.encoding)[3](outfile)
92
+ return self.format_unencoded(tokensource, outfile)
@@ -0,0 +1,68 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ pygments.formatters
4
+ ~~~~~~~~~~~~~~~~~~~
5
+
6
+ Pygments formatters.
7
+
8
+ :copyright: Copyright 2006-2010 by the Pygments team, see AUTHORS.
9
+ :license: BSD, see LICENSE for details.
10
+ """
11
+ import os.path
12
+ import fnmatch
13
+
14
+ from pygments.formatters._mapping import FORMATTERS
15
+ from pygments.plugin import find_plugin_formatters
16
+ from pygments.util import ClassNotFound
17
+
18
+ ns = globals()
19
+ for fcls in FORMATTERS:
20
+ ns[fcls.__name__] = fcls
21
+ del fcls
22
+
23
+ __all__ = ['get_formatter_by_name', 'get_formatter_for_filename',
24
+ 'get_all_formatters'] + [cls.__name__ for cls in FORMATTERS]
25
+
26
+
27
+ _formatter_alias_cache = {}
28
+ _formatter_filename_cache = []
29
+
30
+ def _init_formatter_cache():
31
+ if _formatter_alias_cache:
32
+ return
33
+ for cls in get_all_formatters():
34
+ for alias in cls.aliases:
35
+ _formatter_alias_cache[alias] = cls
36
+ for fn in cls.filenames:
37
+ _formatter_filename_cache.append((fn, cls))
38
+
39
+
40
+ def find_formatter_class(name):
41
+ _init_formatter_cache()
42
+ cls = _formatter_alias_cache.get(name, None)
43
+ return cls
44
+
45
+
46
+ def get_formatter_by_name(name, **options):
47
+ _init_formatter_cache()
48
+ cls = _formatter_alias_cache.get(name, None)
49
+ if not cls:
50
+ raise ClassNotFound("No formatter found for name %r" % name)
51
+ return cls(**options)
52
+
53
+
54
+ def get_formatter_for_filename(fn, **options):
55
+ _init_formatter_cache()
56
+ fn = os.path.basename(fn)
57
+ for pattern, cls in _formatter_filename_cache:
58
+ if fnmatch.fnmatch(fn, pattern):
59
+ return cls(**options)
60
+ raise ClassNotFound("No formatter found for file name %r" % fn)
61
+
62
+
63
+ def get_all_formatters():
64
+ """Return a generator for all formatters."""
65
+ for formatter in FORMATTERS:
66
+ yield formatter
67
+ for _, formatter in find_plugin_formatters():
68
+ yield formatter
@@ -0,0 +1,92 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ pygments.formatters._mapping
4
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
+
6
+ Formatter mapping defintions. This file is generated by itself. Everytime
7
+ you change something on a builtin formatter defintion, run this script from
8
+ the formatters folder to update it.
9
+
10
+ Do not alter the FORMATTERS dictionary by hand.
11
+
12
+ :copyright: Copyright 2006-2010 by the Pygments team, see AUTHORS.
13
+ :license: BSD, see LICENSE for details.
14
+ """
15
+
16
+ from pygments.util import docstring_headline
17
+
18
+ # start
19
+ from pygments.formatters.bbcode import BBCodeFormatter
20
+ from pygments.formatters.html import HtmlFormatter
21
+ from pygments.formatters.img import BmpImageFormatter
22
+ from pygments.formatters.img import GifImageFormatter
23
+ from pygments.formatters.img import ImageFormatter
24
+ from pygments.formatters.img import JpgImageFormatter
25
+ from pygments.formatters.latex import LatexFormatter
26
+ from pygments.formatters.other import NullFormatter
27
+ from pygments.formatters.other import RawTokenFormatter
28
+ from pygments.formatters.rtf import RtfFormatter
29
+ from pygments.formatters.svg import SvgFormatter
30
+ from pygments.formatters.terminal import TerminalFormatter
31
+ from pygments.formatters.terminal256 import Terminal256Formatter
32
+
33
+ FORMATTERS = {
34
+ BBCodeFormatter: ('BBCode', ('bbcode', 'bb'), (), 'Format tokens with BBcodes. These formatting codes are used by many bulletin boards, so you can highlight your sourcecode with pygments before posting it there.'),
35
+ BmpImageFormatter: ('img_bmp', ('bmp', 'bitmap'), ('*.bmp',), 'Create a bitmap image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'),
36
+ GifImageFormatter: ('img_gif', ('gif',), ('*.gif',), 'Create a GIF image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'),
37
+ HtmlFormatter: ('HTML', ('html',), ('*.html', '*.htm'), "Format tokens as HTML 4 ``<span>`` tags within a ``<pre>`` tag, wrapped in a ``<div>`` tag. The ``<div>``'s CSS class can be set by the `cssclass` option."),
38
+ ImageFormatter: ('img', ('img', 'IMG', 'png'), ('*.png',), 'Create a PNG image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'),
39
+ JpgImageFormatter: ('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.'),
40
+ LatexFormatter: ('LaTeX', ('latex', 'tex'), ('*.tex',), 'Format tokens as LaTeX code. This needs the `fancyvrb` and `color` standard packages.'),
41
+ NullFormatter: ('Text only', ('text', 'null'), ('*.txt',), 'Output the text unchanged without any formatting.'),
42
+ RawTokenFormatter: ('Raw tokens', ('raw', 'tokens'), ('*.raw',), 'Format tokens as a raw representation for storing token streams.'),
43
+ RtfFormatter: ('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\xc2\xae Word\xc2\xae documents.'),
44
+ SvgFormatter: ('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.'),
45
+ Terminal256Formatter: ('Terminal256', ('terminal256', 'console256', '256'), (), 'Format tokens with ANSI color sequences, for output in a 256-color terminal or console. Like in `TerminalFormatter` color sequences are terminated at newlines, so that paging the output works correctly.'),
46
+ TerminalFormatter: ('Terminal', ('terminal', 'console'), (), 'Format tokens with ANSI color sequences, for output in a text console. Color sequences are terminated at newlines, so that paging the output works correctly.')
47
+ }
48
+
49
+ if __name__ == '__main__':
50
+ import sys
51
+ import os
52
+
53
+ # lookup formatters
54
+ found_formatters = []
55
+ imports = []
56
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..'))
57
+ for filename in os.listdir('.'):
58
+ if filename.endswith('.py') and not filename.startswith('_'):
59
+ module_name = 'pygments.formatters.%s' % filename[:-3]
60
+ print module_name
61
+ module = __import__(module_name, None, None, [''])
62
+ for formatter_name in module.__all__:
63
+ imports.append((module_name, formatter_name))
64
+ formatter = getattr(module, formatter_name)
65
+ found_formatters.append(
66
+ '%s: %r' % (formatter_name,
67
+ (formatter.name,
68
+ tuple(formatter.aliases),
69
+ tuple(formatter.filenames),
70
+ docstring_headline(formatter))))
71
+ # sort them, that should make the diff files for svn smaller
72
+ found_formatters.sort()
73
+ imports.sort()
74
+
75
+ # extract useful sourcecode from this file
76
+ f = open(__file__)
77
+ try:
78
+ content = f.read()
79
+ finally:
80
+ f.close()
81
+ header = content[:content.find('# start')]
82
+ footer = content[content.find("if __name__ == '__main__':"):]
83
+
84
+ # write new file
85
+ f = open(__file__, 'w')
86
+ f.write(header)
87
+ f.write('# start\n')
88
+ f.write('\n'.join(['from %s import %s' % imp for imp in imports]))
89
+ f.write('\n\n')
90
+ f.write('FORMATTERS = {\n %s\n}\n\n' % ',\n '.join(found_formatters))
91
+ f.write(footer)
92
+ f.close()
@@ -0,0 +1,109 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ pygments.formatters.bbcode
4
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
5
+
6
+ BBcode formatter.
7
+
8
+ :copyright: Copyright 2006-2010 by the Pygments team, see AUTHORS.
9
+ :license: BSD, see LICENSE for details.
10
+ """
11
+
12
+
13
+ from pygments.formatter import Formatter
14
+ from pygments.util import get_bool_opt
15
+
16
+ __all__ = ['BBCodeFormatter']
17
+
18
+
19
+ class BBCodeFormatter(Formatter):
20
+ """
21
+ Format tokens with BBcodes. These formatting codes are used by many
22
+ bulletin boards, so you can highlight your sourcecode with pygments before
23
+ posting it there.
24
+
25
+ This formatter has no support for background colors and borders, as there
26
+ are no common BBcode tags for that.
27
+
28
+ Some board systems (e.g. phpBB) don't support colors in their [code] tag,
29
+ so you can't use the highlighting together with that tag.
30
+ Text in a [code] tag usually is shown with a monospace font (which this
31
+ formatter can do with the ``monofont`` option) and no spaces (which you
32
+ need for indentation) are removed.
33
+
34
+ Additional options accepted:
35
+
36
+ `style`
37
+ The style to use, can be a string or a Style subclass (default:
38
+ ``'default'``).
39
+
40
+ `codetag`
41
+ If set to true, put the output into ``[code]`` tags (default:
42
+ ``false``)
43
+
44
+ `monofont`
45
+ If set to true, add a tag to show the code with a monospace font
46
+ (default: ``false``).
47
+ """
48
+ name = 'BBCode'
49
+ aliases = ['bbcode', 'bb']
50
+ filenames = []
51
+
52
+ def __init__(self, **options):
53
+ Formatter.__init__(self, **options)
54
+ self._code = get_bool_opt(options, 'codetag', False)
55
+ self._mono = get_bool_opt(options, 'monofont', False)
56
+
57
+ self.styles = {}
58
+ self._make_styles()
59
+
60
+ def _make_styles(self):
61
+ for ttype, ndef in self.style:
62
+ start = end = ''
63
+ if ndef['color']:
64
+ start += '[color=#%s]' % ndef['color']
65
+ end = '[/color]' + end
66
+ if ndef['bold']:
67
+ start += '[b]'
68
+ end = '[/b]' + end
69
+ if ndef['italic']:
70
+ start += '[i]'
71
+ end = '[/i]' + end
72
+ if ndef['underline']:
73
+ start += '[u]'
74
+ end = '[/u]' + end
75
+ # there are no common BBcodes for background-color and border
76
+
77
+ self.styles[ttype] = start, end
78
+
79
+ def format_unencoded(self, tokensource, outfile):
80
+ if self._code:
81
+ outfile.write('[code]')
82
+ if self._mono:
83
+ outfile.write('[font=monospace]')
84
+
85
+ lastval = ''
86
+ lasttype = None
87
+
88
+ for ttype, value in tokensource:
89
+ while ttype not in self.styles:
90
+ ttype = ttype.parent
91
+ if ttype == lasttype:
92
+ lastval += value
93
+ else:
94
+ if lastval:
95
+ start, end = self.styles[lasttype]
96
+ outfile.write(''.join((start, lastval, end)))
97
+ lastval = value
98
+ lasttype = ttype
99
+
100
+ if lastval:
101
+ start, end = self.styles[lasttype]
102
+ outfile.write(''.join((start, lastval, end)))
103
+
104
+ if self._mono:
105
+ outfile.write('[/font]')
106
+ if self._code:
107
+ outfile.write('[/code]')
108
+ if self._code or self._mono:
109
+ outfile.write('\n')
@@ -0,0 +1,723 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ pygments.formatters.html
4
+ ~~~~~~~~~~~~~~~~~~~~~~~~
5
+
6
+ Formatter for HTML output.
7
+
8
+ :copyright: Copyright 2006-2010 by the Pygments team, see AUTHORS.
9
+ :license: BSD, see LICENSE for details.
10
+ """
11
+
12
+ import os
13
+ import sys
14
+ import StringIO
15
+
16
+ from pygments.formatter import Formatter
17
+ from pygments.token import Token, Text, STANDARD_TYPES
18
+ from pygments.util import get_bool_opt, get_int_opt, get_list_opt, bytes
19
+
20
+
21
+ __all__ = ['HtmlFormatter']
22
+
23
+
24
+ def escape_html(text):
25
+ """Escape &, <, > as well as single and double quotes for HTML."""
26
+ return text.replace('&', '&amp;'). \
27
+ replace('<', '&lt;'). \
28
+ replace('>', '&gt;'). \
29
+ replace('"', '&quot;'). \
30
+ replace("'", '&#39;')
31
+
32
+
33
+ def get_random_id():
34
+ """Return a random id for javascript fields."""
35
+ from random import random
36
+ from time import time
37
+ try:
38
+ from hashlib import sha1 as sha
39
+ except ImportError:
40
+ import sha
41
+ sha = sha.new
42
+ return sha('%s|%s' % (random(), time())).hexdigest()
43
+
44
+
45
+ def _get_ttype_class(ttype):
46
+ fname = STANDARD_TYPES.get(ttype)
47
+ if fname:
48
+ return fname
49
+ aname = ''
50
+ while fname is None:
51
+ aname = '-' + ttype[-1] + aname
52
+ ttype = ttype.parent
53
+ fname = STANDARD_TYPES.get(ttype)
54
+ return fname + aname
55
+
56
+
57
+ CSSFILE_TEMPLATE = '''\
58
+ td.linenos { background-color: #f0f0f0; padding-right: 10px; }
59
+ span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
60
+ pre { line-height: 125%%; }
61
+ %(styledefs)s
62
+ '''
63
+
64
+ DOC_HEADER = '''\
65
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
66
+ "http://www.w3.org/TR/html4/strict.dtd">
67
+
68
+ <html>
69
+ <head>
70
+ <title>%(title)s</title>
71
+ <meta http-equiv="content-type" content="text/html; charset=%(encoding)s">
72
+ <style type="text/css">
73
+ ''' + CSSFILE_TEMPLATE + '''
74
+ </style>
75
+ </head>
76
+ <body>
77
+ <h2>%(title)s</h2>
78
+
79
+ '''
80
+
81
+ DOC_HEADER_EXTERNALCSS = '''\
82
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
83
+ "http://www.w3.org/TR/html4/strict.dtd">
84
+
85
+ <html>
86
+ <head>
87
+ <title>%(title)s</title>
88
+ <meta http-equiv="content-type" content="text/html; charset=%(encoding)s">
89
+ <link rel="stylesheet" href="%(cssfile)s" type="text/css">
90
+ </head>
91
+ <body>
92
+ <h2>%(title)s</h2>
93
+
94
+ '''
95
+
96
+ DOC_FOOTER = '''\
97
+ </body>
98
+ </html>
99
+ '''
100
+
101
+
102
+ class HtmlFormatter(Formatter):
103
+ r"""
104
+ Format tokens as HTML 4 ``<span>`` tags within a ``<pre>`` tag, wrapped
105
+ in a ``<div>`` tag. The ``<div>``'s CSS class can be set by the `cssclass`
106
+ option.
107
+
108
+ If the `linenos` option is set to ``"table"``, the ``<pre>`` is
109
+ additionally wrapped inside a ``<table>`` which has one row and two
110
+ cells: one containing the line numbers and one containing the code.
111
+ Example:
112
+
113
+ .. sourcecode:: html
114
+
115
+ <div class="highlight" >
116
+ <table><tr>
117
+ <td class="linenos" title="click to toggle"
118
+ onclick="with (this.firstChild.style)
119
+ { display = (display == '') ? 'none' : '' }">
120
+ <pre>1
121
+ 2</pre>
122
+ </td>
123
+ <td class="code">
124
+ <pre><span class="Ke">def </span><span class="NaFu">foo</span>(bar):
125
+ <span class="Ke">pass</span>
126
+ </pre>
127
+ </td>
128
+ </tr></table></div>
129
+
130
+ (whitespace added to improve clarity).
131
+
132
+ Wrapping can be disabled using the `nowrap` option.
133
+
134
+ A list of lines can be specified using the `hl_lines` option to make these
135
+ lines highlighted (as of Pygments 0.11).
136
+
137
+ With the `full` option, a complete HTML 4 document is output, including
138
+ the style definitions inside a ``<style>`` tag, or in a separate file if
139
+ the `cssfile` option is given.
140
+
141
+ The `get_style_defs(arg='')` method of a `HtmlFormatter` returns a string
142
+ containing CSS rules for the CSS classes used by the formatter. The
143
+ argument `arg` can be used to specify additional CSS selectors that
144
+ are prepended to the classes. A call `fmter.get_style_defs('td .code')`
145
+ would result in the following CSS classes:
146
+
147
+ .. sourcecode:: css
148
+
149
+ td .code .kw { font-weight: bold; color: #00FF00 }
150
+ td .code .cm { color: #999999 }
151
+ ...
152
+
153
+ If you have Pygments 0.6 or higher, you can also pass a list or tuple to the
154
+ `get_style_defs()` method to request multiple prefixes for the tokens:
155
+
156
+ .. sourcecode:: python
157
+
158
+ formatter.get_style_defs(['div.syntax pre', 'pre.syntax'])
159
+
160
+ The output would then look like this:
161
+
162
+ .. sourcecode:: css
163
+
164
+ div.syntax pre .kw,
165
+ pre.syntax .kw { font-weight: bold; color: #00FF00 }
166
+ div.syntax pre .cm,
167
+ pre.syntax .cm { color: #999999 }
168
+ ...
169
+
170
+ Additional options accepted:
171
+
172
+ `nowrap`
173
+ If set to ``True``, don't wrap the tokens at all, not even inside a ``<pre>``
174
+ tag. This disables most other options (default: ``False``).
175
+
176
+ `full`
177
+ Tells the formatter to output a "full" document, i.e. a complete
178
+ self-contained document (default: ``False``).
179
+
180
+ `title`
181
+ If `full` is true, the title that should be used to caption the
182
+ document (default: ``''``).
183
+
184
+ `style`
185
+ The style to use, can be a string or a Style subclass (default:
186
+ ``'default'``). This option has no effect if the `cssfile`
187
+ and `noclobber_cssfile` option are given and the file specified in
188
+ `cssfile` exists.
189
+
190
+ `noclasses`
191
+ If set to true, token ``<span>`` tags will not use CSS classes, but
192
+ inline styles. This is not recommended for larger pieces of code since
193
+ it increases output size by quite a bit (default: ``False``).
194
+
195
+ `classprefix`
196
+ Since the token types use relatively short class names, they may clash
197
+ with some of your own class names. In this case you can use the
198
+ `classprefix` option to give a string to prepend to all Pygments-generated
199
+ CSS class names for token types.
200
+ Note that this option also affects the output of `get_style_defs()`.
201
+
202
+ `cssclass`
203
+ CSS class for the wrapping ``<div>`` tag (default: ``'highlight'``).
204
+ If you set this option, the default selector for `get_style_defs()`
205
+ will be this class.
206
+
207
+ *New in Pygments 0.9:* If you select the ``'table'`` line numbers, the
208
+ wrapping table will have a CSS class of this string plus ``'table'``,
209
+ the default is accordingly ``'highlighttable'``.
210
+
211
+ `cssstyles`
212
+ Inline CSS styles for the wrapping ``<div>`` tag (default: ``''``).
213
+
214
+ `prestyles`
215
+ Inline CSS styles for the ``<pre>`` tag (default: ``''``). *New in
216
+ Pygments 0.11.*
217
+
218
+ `cssfile`
219
+ If the `full` option is true and this option is given, it must be the
220
+ name of an external file. If the filename does not include an absolute
221
+ path, the file's path will be assumed to be relative to the main output
222
+ file's path, if the latter can be found. The stylesheet is then written
223
+ to this file instead of the HTML file. *New in Pygments 0.6.*
224
+
225
+ `noclobber_cssfile`
226
+ If `cssfile` is given and the specified file exists, the css file will
227
+ not be overwritten. This allows the use of the `full` option in
228
+ combination with a user specified css file. Default is ``False``.
229
+ *New in Pygments 1.1.*
230
+
231
+ `linenos`
232
+ If set to ``'table'``, output line numbers as a table with two cells,
233
+ one containing the line numbers, the other the whole code. This is
234
+ copy-and-paste-friendly, but may cause alignment problems with some
235
+ browsers or fonts. If set to ``'inline'``, the line numbers will be
236
+ integrated in the ``<pre>`` tag that contains the code (that setting
237
+ is *new in Pygments 0.8*).
238
+
239
+ For compatibility with Pygments 0.7 and earlier, every true value
240
+ except ``'inline'`` means the same as ``'table'`` (in particular, that
241
+ means also ``True``).
242
+
243
+ The default value is ``False``, which means no line numbers at all.
244
+
245
+ **Note:** with the default ("table") line number mechanism, the line
246
+ numbers and code can have different line heights in Internet Explorer
247
+ unless you give the enclosing ``<pre>`` tags an explicit ``line-height``
248
+ CSS property (you get the default line spacing with ``line-height:
249
+ 125%``).
250
+
251
+ `hl_lines`
252
+ Specify a list of lines to be highlighted. *New in Pygments 0.11.*
253
+
254
+ `linenostart`
255
+ The line number for the first line (default: ``1``).
256
+
257
+ `linenostep`
258
+ If set to a number n > 1, only every nth line number is printed.
259
+
260
+ `linenospecial`
261
+ If set to a number n > 0, every nth line number is given the CSS
262
+ class ``"special"`` (default: ``0``).
263
+
264
+ `nobackground`
265
+ If set to ``True``, the formatter won't output the background color
266
+ for the wrapping element (this automatically defaults to ``False``
267
+ when there is no wrapping element [eg: no argument for the
268
+ `get_syntax_defs` method given]) (default: ``False``). *New in
269
+ Pygments 0.6.*
270
+
271
+ `lineseparator`
272
+ This string is output between lines of code. It defaults to ``"\n"``,
273
+ which is enough to break a line inside ``<pre>`` tags, but you can
274
+ e.g. set it to ``"<br>"`` to get HTML line breaks. *New in Pygments
275
+ 0.7.*
276
+
277
+ `lineanchors`
278
+ If set to a nonempty string, e.g. ``foo``, the formatter will wrap each
279
+ output line in an anchor tag with a ``name`` of ``foo-linenumber``.
280
+ This allows easy linking to certain lines. *New in Pygments 0.9.*
281
+
282
+ `anchorlinenos`
283
+ If set to `True`, will wrap line numbers in <a> tags. Used in
284
+ combination with `linenos` and `lineanchors`.
285
+
286
+
287
+ **Subclassing the HTML formatter**
288
+
289
+ *New in Pygments 0.7.*
290
+
291
+ The HTML formatter is now built in a way that allows easy subclassing, thus
292
+ customizing the output HTML code. The `format()` method calls
293
+ `self._format_lines()` which returns a generator that yields tuples of ``(1,
294
+ line)``, where the ``1`` indicates that the ``line`` is a line of the
295
+ formatted source code.
296
+
297
+ If the `nowrap` option is set, the generator is the iterated over and the
298
+ resulting HTML is output.
299
+
300
+ Otherwise, `format()` calls `self.wrap()`, which wraps the generator with
301
+ other generators. These may add some HTML code to the one generated by
302
+ `_format_lines()`, either by modifying the lines generated by the latter,
303
+ then yielding them again with ``(1, line)``, and/or by yielding other HTML
304
+ code before or after the lines, with ``(0, html)``. The distinction between
305
+ source lines and other code makes it possible to wrap the generator multiple
306
+ times.
307
+
308
+ The default `wrap()` implementation adds a ``<div>`` and a ``<pre>`` tag.
309
+
310
+ A custom `HtmlFormatter` subclass could look like this:
311
+
312
+ .. sourcecode:: python
313
+
314
+ class CodeHtmlFormatter(HtmlFormatter):
315
+
316
+ def wrap(self, source, outfile):
317
+ return self._wrap_code(source)
318
+
319
+ def _wrap_code(self, source):
320
+ yield 0, '<code>'
321
+ for i, t in source:
322
+ if i == 1:
323
+ # it's a line of formatted code
324
+ t += '<br>'
325
+ yield i, t
326
+ yield 0, '</code>'
327
+
328
+ This results in wrapping the formatted lines with a ``<code>`` tag, where the
329
+ source lines are broken using ``<br>`` tags.
330
+
331
+ After calling `wrap()`, the `format()` method also adds the "line numbers"
332
+ and/or "full document" wrappers if the respective options are set. Then, all
333
+ HTML yielded by the wrapped generator is output.
334
+ """
335
+
336
+ name = 'HTML'
337
+ aliases = ['html']
338
+ filenames = ['*.html', '*.htm']
339
+
340
+ def __init__(self, **options):
341
+ Formatter.__init__(self, **options)
342
+ self.title = self._decodeifneeded(self.title)
343
+ self.nowrap = get_bool_opt(options, 'nowrap', False)
344
+ self.noclasses = get_bool_opt(options, 'noclasses', False)
345
+ self.classprefix = options.get('classprefix', '')
346
+ self.cssclass = self._decodeifneeded(options.get('cssclass', 'highlight'))
347
+ self.cssstyles = self._decodeifneeded(options.get('cssstyles', ''))
348
+ self.prestyles = self._decodeifneeded(options.get('prestyles', ''))
349
+ self.cssfile = self._decodeifneeded(options.get('cssfile', ''))
350
+ self.noclobber_cssfile = get_bool_opt(options, 'noclobber_cssfile', False)
351
+
352
+ linenos = options.get('linenos', False)
353
+ if linenos == 'inline':
354
+ self.linenos = 2
355
+ elif linenos:
356
+ # compatibility with <= 0.7
357
+ self.linenos = 1
358
+ else:
359
+ self.linenos = 0
360
+ self.linenostart = abs(get_int_opt(options, 'linenostart', 1))
361
+ self.linenostep = abs(get_int_opt(options, 'linenostep', 1))
362
+ self.linenospecial = abs(get_int_opt(options, 'linenospecial', 0))
363
+ self.nobackground = get_bool_opt(options, 'nobackground', False)
364
+ self.lineseparator = options.get('lineseparator', '\n')
365
+ self.lineanchors = options.get('lineanchors', '')
366
+ self.anchorlinenos = options.get('anchorlinenos', False)
367
+ self.hl_lines = set()
368
+ for lineno in get_list_opt(options, 'hl_lines', []):
369
+ try:
370
+ self.hl_lines.add(int(lineno))
371
+ except ValueError:
372
+ pass
373
+
374
+ self._class_cache = {}
375
+ self._create_stylesheet()
376
+
377
+ def _get_css_class(self, ttype):
378
+ """Return the css class of this token type prefixed with
379
+ the classprefix option."""
380
+ if ttype in self._class_cache:
381
+ return self._class_cache[ttype]
382
+ return self.classprefix + _get_ttype_class(ttype)
383
+
384
+ def _create_stylesheet(self):
385
+ t2c = self.ttype2class = {Token: ''}
386
+ c2s = self.class2style = {}
387
+ cp = self.classprefix
388
+ for ttype, ndef in self.style:
389
+ name = cp + _get_ttype_class(ttype)
390
+ style = ''
391
+ if ndef['color']:
392
+ style += 'color: #%s; ' % ndef['color']
393
+ if ndef['bold']:
394
+ style += 'font-weight: bold; '
395
+ if ndef['italic']:
396
+ style += 'font-style: italic; '
397
+ if ndef['underline']:
398
+ style += 'text-decoration: underline; '
399
+ if ndef['bgcolor']:
400
+ style += 'background-color: #%s; ' % ndef['bgcolor']
401
+ if ndef['border']:
402
+ style += 'border: 1px solid #%s; ' % ndef['border']
403
+ if style:
404
+ t2c[ttype] = name
405
+ # save len(ttype) to enable ordering the styles by
406
+ # hierarchy (necessary for CSS cascading rules!)
407
+ c2s[name] = (style[:-2], ttype, len(ttype))
408
+
409
+ def get_style_defs(self, arg=None):
410
+ """
411
+ Return CSS style definitions for the classes produced by the current
412
+ highlighting style. ``arg`` can be a string or list of selectors to
413
+ insert before the token type classes.
414
+ """
415
+ if arg is None:
416
+ arg = ('cssclass' in self.options and '.'+self.cssclass or '')
417
+ if isinstance(arg, basestring):
418
+ args = [arg]
419
+ else:
420
+ args = list(arg)
421
+
422
+ def prefix(cls):
423
+ if cls:
424
+ cls = '.' + cls
425
+ tmp = []
426
+ for arg in args:
427
+ tmp.append((arg and arg + ' ' or '') + cls)
428
+ return ', '.join(tmp)
429
+
430
+ styles = [(level, ttype, cls, style)
431
+ for cls, (style, ttype, level) in self.class2style.iteritems()
432
+ if cls and style]
433
+ styles.sort()
434
+ lines = ['%s { %s } /* %s */' % (prefix(cls), style, repr(ttype)[6:])
435
+ for (level, ttype, cls, style) in styles]
436
+ if arg and not self.nobackground and \
437
+ self.style.background_color is not None:
438
+ text_style = ''
439
+ if Text in self.ttype2class:
440
+ text_style = ' ' + self.class2style[self.ttype2class[Text]][0]
441
+ lines.insert(0, '%s { background: %s;%s }' %
442
+ (prefix(''), self.style.background_color, text_style))
443
+ if self.style.highlight_color is not None:
444
+ lines.insert(0, '%s.hll { background-color: %s }' %
445
+ (prefix(''), self.style.highlight_color))
446
+ return '\n'.join(lines)
447
+
448
+ def _decodeifneeded(self, value):
449
+ if isinstance(value, bytes):
450
+ if self.encoding:
451
+ return value.decode(self.encoding)
452
+ return value.decode()
453
+ return value
454
+
455
+ def _wrap_full(self, inner, outfile):
456
+ if self.cssfile:
457
+ if os.path.isabs(self.cssfile):
458
+ # it's an absolute filename
459
+ cssfilename = self.cssfile
460
+ else:
461
+ try:
462
+ filename = outfile.name
463
+ if not filename or filename[0] == '<':
464
+ # pseudo files, e.g. name == '<fdopen>'
465
+ raise AttributeError
466
+ cssfilename = os.path.join(os.path.dirname(filename),
467
+ self.cssfile)
468
+ except AttributeError:
469
+ print >>sys.stderr, 'Note: Cannot determine output file name, ' \
470
+ 'using current directory as base for the CSS file name'
471
+ cssfilename = self.cssfile
472
+ # write CSS file only if noclobber_cssfile isn't given as an option.
473
+ try:
474
+ if not os.path.exists(cssfilename) or not self.noclobber_cssfile:
475
+ cf = open(cssfilename, "w")
476
+ cf.write(CSSFILE_TEMPLATE %
477
+ {'styledefs': self.get_style_defs('body')})
478
+ cf.close()
479
+ except IOError, err:
480
+ err.strerror = 'Error writing CSS file: ' + err.strerror
481
+ raise
482
+
483
+ yield 0, (DOC_HEADER_EXTERNALCSS %
484
+ dict(title = self.title,
485
+ cssfile = self.cssfile,
486
+ encoding = self.encoding))
487
+ else:
488
+ yield 0, (DOC_HEADER %
489
+ dict(title = self.title,
490
+ styledefs = self.get_style_defs('body'),
491
+ encoding = self.encoding))
492
+
493
+ for t, line in inner:
494
+ yield t, line
495
+ yield 0, DOC_FOOTER
496
+
497
+ def _wrap_tablelinenos(self, inner):
498
+ dummyoutfile = StringIO.StringIO()
499
+ lncount = 0
500
+ for t, line in inner:
501
+ if t:
502
+ lncount += 1
503
+ dummyoutfile.write(line)
504
+
505
+ fl = self.linenostart
506
+ mw = len(str(lncount + fl - 1))
507
+ sp = self.linenospecial
508
+ st = self.linenostep
509
+ la = self.lineanchors
510
+ aln = self.anchorlinenos
511
+ if sp:
512
+ lines = []
513
+
514
+ for i in range(fl, fl+lncount):
515
+ if i % st == 0:
516
+ if i % sp == 0:
517
+ if aln:
518
+ lines.append('<a href="#%s-%d" class="special">%*d</a>' %
519
+ (la, i, mw, i))
520
+ else:
521
+ lines.append('<span class="special">%*d</span>' % (mw, i))
522
+ else:
523
+ if aln:
524
+ lines.append('<a href="#%s-%d">%*d</a>' % (la, i, mw, i))
525
+ else:
526
+ lines.append('%*d' % (mw, i))
527
+ else:
528
+ lines.append('')
529
+ ls = '\n'.join(lines)
530
+ else:
531
+ lines = []
532
+ for i in range(fl, fl+lncount):
533
+ if i % st == 0:
534
+ if aln:
535
+ lines.append('<a href="#%s-%d">%*d</a>' % (la, i, mw, i))
536
+ else:
537
+ lines.append('%*d' % (mw, i))
538
+ else:
539
+ lines.append('')
540
+ ls = '\n'.join(lines)
541
+
542
+ # in case you wonder about the seemingly redundant <div> here: since the
543
+ # content in the other cell also is wrapped in a div, some browsers in
544
+ # some configurations seem to mess up the formatting...
545
+ yield 0, ('<table class="%stable">' % self.cssclass +
546
+ '<tr><td class="linenos"><div class="linenodiv"><pre>' +
547
+ ls + '</pre></div></td><td class="code">')
548
+ yield 0, dummyoutfile.getvalue()
549
+ yield 0, '</td></tr></table>'
550
+
551
+ def _wrap_inlinelinenos(self, inner):
552
+ # need a list of lines since we need the width of a single number :(
553
+ lines = list(inner)
554
+ sp = self.linenospecial
555
+ st = self.linenostep
556
+ num = self.linenostart
557
+ mw = len(str(len(lines) + num - 1))
558
+
559
+ if sp:
560
+ for t, line in lines:
561
+ yield 1, '<span class="lineno%s">%*s</span> ' % (
562
+ num%sp == 0 and ' special' or '', mw,
563
+ (num%st and ' ' or num)) + line
564
+ num += 1
565
+ else:
566
+ for t, line in lines:
567
+ yield 1, '<span class="lineno">%*s</span> ' % (
568
+ mw, (num%st and ' ' or num)) + line
569
+ num += 1
570
+
571
+ def _wrap_lineanchors(self, inner):
572
+ s = self.lineanchors
573
+ i = 0
574
+ for t, line in inner:
575
+ if t:
576
+ i += 1
577
+ yield 1, '<a name="%s-%d"></a>' % (s, i) + line
578
+ else:
579
+ yield 0, line
580
+
581
+ def _wrap_div(self, inner):
582
+ style = []
583
+ if (self.noclasses and not self.nobackground and
584
+ self.style.background_color is not None):
585
+ style.append('background: %s' % (self.style.background_color,))
586
+ if self.cssstyles:
587
+ style.append(self.cssstyles)
588
+ style = '; '.join(style)
589
+
590
+ yield 0, ('<div' + (self.cssclass and ' class="%s"' % self.cssclass)
591
+ + (style and (' style="%s"' % style)) + '>')
592
+ for tup in inner:
593
+ yield tup
594
+ yield 0, '</div>\n'
595
+
596
+ def _wrap_pre(self, inner):
597
+ style = []
598
+ if self.prestyles:
599
+ style.append(self.prestyles)
600
+ if self.noclasses:
601
+ style.append('line-height: 125%')
602
+ style = '; '.join(style)
603
+
604
+ yield 0, ('<pre' + (style and ' style="%s"' % style) + '>')
605
+ for tup in inner:
606
+ yield tup
607
+ yield 0, '</pre>'
608
+
609
+ def _format_lines(self, tokensource):
610
+ """
611
+ Just format the tokens, without any wrapping tags.
612
+ Yield individual lines.
613
+ """
614
+ nocls = self.noclasses
615
+ lsep = self.lineseparator
616
+ # for <span style=""> lookup only
617
+ getcls = self.ttype2class.get
618
+ c2s = self.class2style
619
+
620
+ lspan = ''
621
+ line = ''
622
+ for ttype, value in tokensource:
623
+ if nocls:
624
+ cclass = getcls(ttype)
625
+ while cclass is None:
626
+ ttype = ttype.parent
627
+ cclass = getcls(ttype)
628
+ cspan = cclass and '<span style="%s">' % c2s[cclass][0] or ''
629
+ else:
630
+ cls = self._get_css_class(ttype)
631
+ cspan = cls and '<span class="%s">' % cls or ''
632
+
633
+ parts = escape_html(value).split('\n')
634
+
635
+ # for all but the last line
636
+ for part in parts[:-1]:
637
+ if line:
638
+ if lspan != cspan:
639
+ line += (lspan and '</span>') + cspan + part + \
640
+ (cspan and '</span>') + lsep
641
+ else: # both are the same
642
+ line += part + (lspan and '</span>') + lsep
643
+ yield 1, line
644
+ line = ''
645
+ elif part:
646
+ yield 1, cspan + part + (cspan and '</span>') + lsep
647
+ else:
648
+ yield 1, lsep
649
+ # for the last line
650
+ if line and parts[-1]:
651
+ if lspan != cspan:
652
+ line += (lspan and '</span>') + cspan + parts[-1]
653
+ lspan = cspan
654
+ else:
655
+ line += parts[-1]
656
+ elif parts[-1]:
657
+ line = cspan + parts[-1]
658
+ lspan = cspan
659
+ # else we neither have to open a new span nor set lspan
660
+
661
+ if line:
662
+ yield 1, line + (lspan and '</span>') + lsep
663
+
664
+ def _highlight_lines(self, tokensource):
665
+ """
666
+ Highlighted the lines specified in the `hl_lines` option by
667
+ post-processing the token stream coming from `_format_lines`.
668
+ """
669
+ hls = self.hl_lines
670
+
671
+ for i, (t, value) in enumerate(tokensource):
672
+ if t != 1:
673
+ yield t, value
674
+ if i + 1 in hls: # i + 1 because Python indexes start at 0
675
+ if self.noclasses:
676
+ style = ''
677
+ if self.style.highlight_color is not None:
678
+ style = (' style="background-color: %s"' %
679
+ (self.style.highlight_color,))
680
+ yield 1, '<span%s>%s</span>' % (style, value)
681
+ else:
682
+ yield 1, '<span class="hll">%s</span>' % value
683
+ else:
684
+ yield 1, value
685
+
686
+ def wrap(self, source, outfile):
687
+ """
688
+ Wrap the ``source``, which is a generator yielding
689
+ individual lines, in custom generators. See docstring
690
+ for `format`. Can be overridden.
691
+ """
692
+ return self._wrap_div(self._wrap_pre(source))
693
+
694
+ def format_unencoded(self, tokensource, outfile):
695
+ """
696
+ The formatting process uses several nested generators; which of
697
+ them are used is determined by the user's options.
698
+
699
+ Each generator should take at least one argument, ``inner``,
700
+ and wrap the pieces of text generated by this.
701
+
702
+ Always yield 2-tuples: (code, text). If "code" is 1, the text
703
+ is part of the original tokensource being highlighted, if it's
704
+ 0, the text is some piece of wrapping. This makes it possible to
705
+ use several different wrappers that process the original source
706
+ linewise, e.g. line number generators.
707
+ """
708
+ source = self._format_lines(tokensource)
709
+ if self.hl_lines:
710
+ source = self._highlight_lines(source)
711
+ if not self.nowrap:
712
+ if self.linenos == 2:
713
+ source = self._wrap_inlinelinenos(source)
714
+ if self.lineanchors:
715
+ source = self._wrap_lineanchors(source)
716
+ source = self.wrap(source, outfile)
717
+ if self.linenos == 1:
718
+ source = self._wrap_tablelinenos(source)
719
+ if self.full:
720
+ source = self._wrap_full(source, outfile)
721
+
722
+ for t, piece in source:
723
+ outfile.write(piece)