pygmentize 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,136 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ pygments.formatters.rtf
4
+ ~~~~~~~~~~~~~~~~~~~~~~~
5
+
6
+ A formatter that generates RTF files.
7
+
8
+ :copyright: Copyright 2006-2010 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('}')
@@ -0,0 +1,154 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ pygments.formatters.svg
4
+ ~~~~~~~~~~~~~~~~~~~~~~~
5
+
6
+ Formatter for SVG output.
7
+
8
+ :copyright: Copyright 2006-2010 by the Pygments team, see AUTHORS.
9
+ :license: BSD, see LICENSE for details.
10
+ """
11
+
12
+ from pygments.formatter import Formatter
13
+ from pygments.util import get_bool_opt, get_int_opt
14
+
15
+ __all__ = ['SvgFormatter']
16
+
17
+
18
+ def escape_html(text):
19
+ """Escape &, <, > as well as single and double quotes for HTML."""
20
+ return text.replace('&', '&amp;'). \
21
+ replace('<', '&lt;'). \
22
+ replace('>', '&gt;'). \
23
+ replace('"', '&quot;'). \
24
+ replace("'", '&#39;')
25
+
26
+
27
+ class2style = {}
28
+
29
+ class SvgFormatter(Formatter):
30
+ """
31
+ Format tokens as an SVG graphics file. This formatter is still experimental.
32
+ Each line of code is a ``<text>`` element with explicit ``x`` and ``y``
33
+ coordinates containing ``<tspan>`` elements with the individual token styles.
34
+
35
+ By default, this formatter outputs a full SVG document including doctype
36
+ declaration and the ``<svg>`` root element.
37
+
38
+ *New in Pygments 0.9.*
39
+
40
+ Additional options accepted:
41
+
42
+ `nowrap`
43
+ Don't wrap the SVG ``<text>`` elements in ``<svg><g>`` elements and
44
+ don't add a XML declaration and a doctype. If true, the `fontfamily`
45
+ and `fontsize` options are ignored. Defaults to ``False``.
46
+
47
+ `fontfamily`
48
+ The value to give the wrapping ``<g>`` element's ``font-family``
49
+ attribute, defaults to ``"monospace"``.
50
+
51
+ `fontsize`
52
+ The value to give the wrapping ``<g>`` element's ``font-size``
53
+ attribute, defaults to ``"14px"``.
54
+
55
+ `xoffset`
56
+ Starting offset in X direction, defaults to ``0``.
57
+
58
+ `yoffset`
59
+ Starting offset in Y direction, defaults to the font size if it is given
60
+ in pixels, or ``20`` else. (This is necessary since text coordinates
61
+ refer to the text baseline, not the top edge.)
62
+
63
+ `ystep`
64
+ Offset to add to the Y coordinate for each subsequent line. This should
65
+ roughly be the text size plus 5. It defaults to that value if the text
66
+ size is given in pixels, or ``25`` else.
67
+
68
+ `spacehack`
69
+ Convert spaces in the source to ``&#160;``, which are non-breaking
70
+ spaces. SVG provides the ``xml:space`` attribute to control how
71
+ whitespace inside tags is handled, in theory, the ``preserve`` value
72
+ could be used to keep all whitespace as-is. However, many current SVG
73
+ viewers don't obey that rule, so this option is provided as a workaround
74
+ and defaults to ``True``.
75
+ """
76
+ name = 'SVG'
77
+ aliases = ['svg']
78
+ filenames = ['*.svg']
79
+
80
+ def __init__(self, **options):
81
+ # XXX outencoding
82
+ Formatter.__init__(self, **options)
83
+ self.nowrap = get_bool_opt(options, 'nowrap', False)
84
+ self.fontfamily = options.get('fontfamily', 'monospace')
85
+ self.fontsize = options.get('fontsize', '14px')
86
+ self.xoffset = get_int_opt(options, 'xoffset', 0)
87
+ fs = self.fontsize.strip()
88
+ if fs.endswith('px'): fs = fs[:-2].strip()
89
+ try:
90
+ int_fs = int(fs)
91
+ except:
92
+ int_fs = 20
93
+ self.yoffset = get_int_opt(options, 'yoffset', int_fs)
94
+ self.ystep = get_int_opt(options, 'ystep', int_fs + 5)
95
+ self.spacehack = get_bool_opt(options, 'spacehack', True)
96
+ self._stylecache = {}
97
+
98
+ def format_unencoded(self, tokensource, outfile):
99
+ """
100
+ Format ``tokensource``, an iterable of ``(tokentype, tokenstring)``
101
+ tuples and write it into ``outfile``.
102
+
103
+ For our implementation we put all lines in their own 'line group'.
104
+ """
105
+ x = self.xoffset
106
+ y = self.yoffset
107
+ if not self.nowrap:
108
+ if self.encoding:
109
+ outfile.write('<?xml version="1.0" encoding="%s"?>\n' %
110
+ self.encoding)
111
+ else:
112
+ outfile.write('<?xml version="1.0"?>\n')
113
+ outfile.write('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" '
114
+ '"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/'
115
+ 'svg10.dtd">\n')
116
+ outfile.write('<svg xmlns="http://www.w3.org/2000/svg">\n')
117
+ outfile.write('<g font-family="%s" font-size="%s">\n' %
118
+ (self.fontfamily, self.fontsize))
119
+ outfile.write('<text x="%s" y="%s" xml:space="preserve">' % (x, y))
120
+ for ttype, value in tokensource:
121
+ style = self._get_style(ttype)
122
+ tspan = style and '<tspan' + style + '>' or ''
123
+ tspanend = tspan and '</tspan>' or ''
124
+ value = escape_html(value)
125
+ if self.spacehack:
126
+ value = value.expandtabs().replace(' ', '&#160;')
127
+ parts = value.split('\n')
128
+ for part in parts[:-1]:
129
+ outfile.write(tspan + part + tspanend)
130
+ y += self.ystep
131
+ outfile.write('</text>\n<text x="%s" y="%s" '
132
+ 'xml:space="preserve">' % (x, y))
133
+ outfile.write(tspan + parts[-1] + tspanend)
134
+ outfile.write('</text>')
135
+
136
+ if not self.nowrap:
137
+ outfile.write('</g></svg>\n')
138
+
139
+ def _get_style(self, tokentype):
140
+ if tokentype in self._stylecache:
141
+ return self._stylecache[tokentype]
142
+ otokentype = tokentype
143
+ while not self.style.styles_token(tokentype):
144
+ tokentype = tokentype.parent
145
+ value = self.style.style_for_token(tokentype)
146
+ result = ''
147
+ if value['color']:
148
+ result = ' fill="#' + value['color'] + '"'
149
+ if value['bold']:
150
+ result += ' font-weight="bold"'
151
+ if value['italic']:
152
+ result += ' font-style="italic"'
153
+ self._stylecache[otokentype] = result
154
+ return result
@@ -0,0 +1,109 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ pygments.formatters.terminal
4
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
+
6
+ Formatter for terminal output with ANSI sequences.
7
+
8
+ :copyright: Copyright 2006-2010 by the Pygments team, see AUTHORS.
9
+ :license: BSD, see LICENSE for details.
10
+ """
11
+
12
+ from pygments.formatter import Formatter
13
+ from pygments.token import Keyword, Name, Comment, String, Error, \
14
+ Number, Operator, Generic, Token, Whitespace
15
+ from pygments.console import ansiformat
16
+ from pygments.util import get_choice_opt
17
+
18
+
19
+ __all__ = ['TerminalFormatter']
20
+
21
+
22
+ #: Map token types to a tuple of color values for light and dark
23
+ #: backgrounds.
24
+ TERMINAL_COLORS = {
25
+ Token: ('', ''),
26
+
27
+ Whitespace: ('lightgray', 'darkgray'),
28
+ Comment: ('lightgray', 'darkgray'),
29
+ Comment.Preproc: ('teal', 'turquoise'),
30
+ Keyword: ('darkblue', 'blue'),
31
+ Keyword.Type: ('teal', 'turquoise'),
32
+ Operator.Word: ('purple', 'fuchsia'),
33
+ Name.Builtin: ('teal', 'turquoise'),
34
+ Name.Function: ('darkgreen', 'green'),
35
+ Name.Namespace: ('_teal_', '_turquoise_'),
36
+ Name.Class: ('_darkgreen_', '_green_'),
37
+ Name.Exception: ('teal', 'turquoise'),
38
+ Name.Decorator: ('darkgray', 'lightgray'),
39
+ Name.Variable: ('darkred', 'red'),
40
+ Name.Constant: ('darkred', 'red'),
41
+ Name.Attribute: ('teal', 'turquoise'),
42
+ Name.Tag: ('blue', 'blue'),
43
+ String: ('brown', 'brown'),
44
+ Number: ('darkblue', 'blue'),
45
+
46
+ Generic.Deleted: ('red', 'red'),
47
+ Generic.Inserted: ('darkgreen', 'green'),
48
+ Generic.Heading: ('**', '**'),
49
+ Generic.Subheading: ('*purple*', '*fuchsia*'),
50
+ Generic.Error: ('red', 'red'),
51
+
52
+ Error: ('_red_', '_red_'),
53
+ }
54
+
55
+
56
+ class TerminalFormatter(Formatter):
57
+ r"""
58
+ Format tokens with ANSI color sequences, for output in a text console.
59
+ Color sequences are terminated at newlines, so that paging the output
60
+ works correctly.
61
+
62
+ The `get_style_defs()` method doesn't do anything special since there is
63
+ no support for common styles.
64
+
65
+ Options accepted:
66
+
67
+ `bg`
68
+ Set to ``"light"`` or ``"dark"`` depending on the terminal's background
69
+ (default: ``"light"``).
70
+
71
+ `colorscheme`
72
+ A dictionary mapping token types to (lightbg, darkbg) color names or
73
+ ``None`` (default: ``None`` = use builtin colorscheme).
74
+ """
75
+ name = 'Terminal'
76
+ aliases = ['terminal', 'console']
77
+ filenames = []
78
+
79
+ def __init__(self, **options):
80
+ Formatter.__init__(self, **options)
81
+ self.darkbg = get_choice_opt(options, 'bg',
82
+ ['light', 'dark'], 'light') == 'dark'
83
+ self.colorscheme = options.get('colorscheme', None) or TERMINAL_COLORS
84
+
85
+ def format(self, tokensource, outfile):
86
+ # hack: if the output is a terminal and has an encoding set,
87
+ # use that to avoid unicode encode problems
88
+ if not self.encoding and hasattr(outfile, "encoding") and \
89
+ hasattr(outfile, "isatty") and outfile.isatty():
90
+ self.encoding = outfile.encoding
91
+ return Formatter.format(self, tokensource, outfile)
92
+
93
+ def format_unencoded(self, tokensource, outfile):
94
+ for ttype, value in tokensource:
95
+ color = self.colorscheme.get(ttype)
96
+ while color is None:
97
+ ttype = ttype[:-1]
98
+ color = self.colorscheme.get(ttype)
99
+ if color:
100
+ color = color[self.darkbg]
101
+ spl = value.split('\n')
102
+ for line in spl[:-1]:
103
+ if line:
104
+ outfile.write(ansiformat(color, line))
105
+ outfile.write('\n')
106
+ if spl[-1]:
107
+ outfile.write(ansiformat(color, spl[-1]))
108
+ else:
109
+ outfile.write(value)
@@ -0,0 +1,219 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ pygments.formatters.terminal256
4
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
+
6
+ Formatter for 256-color terminal output with ANSI sequences.
7
+
8
+ RGB-to-XTERM color conversion routines adapted from xterm256-conv
9
+ tool (http://frexx.de/xterm-256-notes/data/xterm256-conv2.tar.bz2)
10
+ by Wolfgang Frisch.
11
+
12
+ Formatter version 1.
13
+
14
+ :copyright: Copyright 2006-2010 by the Pygments team, see AUTHORS.
15
+ :license: BSD, see LICENSE for details.
16
+ """
17
+
18
+ # TODO:
19
+ # - Options to map style's bold/underline/italic/border attributes
20
+ # to some ANSI attrbutes (something like 'italic=underline')
21
+ # - An option to output "style RGB to xterm RGB/index" conversion table
22
+ # - An option to indicate that we are running in "reverse background"
23
+ # xterm. This means that default colors are white-on-black, not
24
+ # black-on-while, so colors like "white background" need to be converted
25
+ # to "white background, black foreground", etc...
26
+
27
+ from pygments.formatter import Formatter
28
+
29
+
30
+ __all__ = ['Terminal256Formatter']
31
+
32
+
33
+ class EscapeSequence:
34
+ def __init__(self, fg=None, bg=None, bold=False, underline=False):
35
+ self.fg = fg
36
+ self.bg = bg
37
+ self.bold = bold
38
+ self.underline = underline
39
+
40
+ def escape(self, attrs):
41
+ if len(attrs):
42
+ return "\x1b[" + ";".join(attrs) + "m"
43
+ return ""
44
+
45
+ def color_string(self):
46
+ attrs = []
47
+ if self.fg is not None:
48
+ attrs.extend(("38", "5", "%i" % self.fg))
49
+ if self.bg is not None:
50
+ attrs.extend(("48", "5", "%i" % self.bg))
51
+ if self.bold:
52
+ attrs.append("01")
53
+ if self.underline:
54
+ attrs.append("04")
55
+ return self.escape(attrs)
56
+
57
+ def reset_string(self):
58
+ attrs = []
59
+ if self.fg is not None:
60
+ attrs.append("39")
61
+ if self.bg is not None:
62
+ attrs.append("49")
63
+ if self.bold or self.underline:
64
+ attrs.append("00")
65
+ return self.escape(attrs)
66
+
67
+ class Terminal256Formatter(Formatter):
68
+ r"""
69
+ Format tokens with ANSI color sequences, for output in a 256-color
70
+ terminal or console. Like in `TerminalFormatter` color sequences
71
+ are terminated at newlines, so that paging the output works correctly.
72
+
73
+ The formatter takes colors from a style defined by the `style` option
74
+ and converts them to nearest ANSI 256-color escape sequences. Bold and
75
+ underline attributes from the style are preserved (and displayed).
76
+
77
+ *New in Pygments 0.9.*
78
+
79
+ Options accepted:
80
+
81
+ `style`
82
+ The style to use, can be a string or a Style subclass (default:
83
+ ``'default'``).
84
+ """
85
+ name = 'Terminal256'
86
+ aliases = ['terminal256', 'console256', '256']
87
+ filenames = []
88
+
89
+ def __init__(self, **options):
90
+ Formatter.__init__(self, **options)
91
+
92
+ self.xterm_colors = []
93
+ self.best_match = {}
94
+ self.style_string = {}
95
+
96
+ self.usebold = 'nobold' not in options
97
+ self.useunderline = 'nounderline' not in options
98
+
99
+ self._build_color_table() # build an RGB-to-256 color conversion table
100
+ self._setup_styles() # convert selected style's colors to term. colors
101
+
102
+ def _build_color_table(self):
103
+ # colors 0..15: 16 basic colors
104
+
105
+ self.xterm_colors.append((0x00, 0x00, 0x00)) # 0
106
+ self.xterm_colors.append((0xcd, 0x00, 0x00)) # 1
107
+ self.xterm_colors.append((0x00, 0xcd, 0x00)) # 2
108
+ self.xterm_colors.append((0xcd, 0xcd, 0x00)) # 3
109
+ self.xterm_colors.append((0x00, 0x00, 0xee)) # 4
110
+ self.xterm_colors.append((0xcd, 0x00, 0xcd)) # 5
111
+ self.xterm_colors.append((0x00, 0xcd, 0xcd)) # 6
112
+ self.xterm_colors.append((0xe5, 0xe5, 0xe5)) # 7
113
+ self.xterm_colors.append((0x7f, 0x7f, 0x7f)) # 8
114
+ self.xterm_colors.append((0xff, 0x00, 0x00)) # 9
115
+ self.xterm_colors.append((0x00, 0xff, 0x00)) # 10
116
+ self.xterm_colors.append((0xff, 0xff, 0x00)) # 11
117
+ self.xterm_colors.append((0x5c, 0x5c, 0xff)) # 12
118
+ self.xterm_colors.append((0xff, 0x00, 0xff)) # 13
119
+ self.xterm_colors.append((0x00, 0xff, 0xff)) # 14
120
+ self.xterm_colors.append((0xff, 0xff, 0xff)) # 15
121
+
122
+ # colors 16..232: the 6x6x6 color cube
123
+
124
+ valuerange = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff)
125
+
126
+ for i in range(217):
127
+ r = valuerange[(i // 36) % 6]
128
+ g = valuerange[(i // 6) % 6]
129
+ b = valuerange[i % 6]
130
+ self.xterm_colors.append((r, g, b))
131
+
132
+ # colors 233..253: grayscale
133
+
134
+ for i in range(1, 22):
135
+ v = 8 + i * 10
136
+ self.xterm_colors.append((v, v, v))
137
+
138
+ def _closest_color(self, r, g, b):
139
+ distance = 257*257*3 # "infinity" (>distance from #000000 to #ffffff)
140
+ match = 0
141
+
142
+ for i in range(0, 254):
143
+ values = self.xterm_colors[i]
144
+
145
+ rd = r - values[0]
146
+ gd = g - values[1]
147
+ bd = b - values[2]
148
+ d = rd*rd + gd*gd + bd*bd
149
+
150
+ if d < distance:
151
+ match = i
152
+ distance = d
153
+ return match
154
+
155
+ def _color_index(self, color):
156
+ index = self.best_match.get(color, None)
157
+ if index is None:
158
+ try:
159
+ rgb = int(str(color), 16)
160
+ except ValueError:
161
+ rgb = 0
162
+
163
+ r = (rgb >> 16) & 0xff
164
+ g = (rgb >> 8) & 0xff
165
+ b = rgb & 0xff
166
+ index = self._closest_color(r, g, b)
167
+ self.best_match[color] = index
168
+ return index
169
+
170
+ def _setup_styles(self):
171
+ for ttype, ndef in self.style:
172
+ escape = EscapeSequence()
173
+ if ndef['color']:
174
+ escape.fg = self._color_index(ndef['color'])
175
+ if ndef['bgcolor']:
176
+ escape.bg = self._color_index(ndef['bgcolor'])
177
+ if self.usebold and ndef['bold']:
178
+ escape.bold = True
179
+ if self.useunderline and ndef['underline']:
180
+ escape.underline = True
181
+ self.style_string[str(ttype)] = (escape.color_string(),
182
+ escape.reset_string())
183
+
184
+ def format(self, tokensource, outfile):
185
+ # hack: if the output is a terminal and has an encoding set,
186
+ # use that to avoid unicode encode problems
187
+ if not self.encoding and hasattr(outfile, "encoding") and \
188
+ hasattr(outfile, "isatty") and outfile.isatty():
189
+ self.encoding = outfile.encoding
190
+ return Formatter.format(self, tokensource, outfile)
191
+
192
+ def format_unencoded(self, tokensource, outfile):
193
+ for ttype, value in tokensource:
194
+ not_found = True
195
+ while ttype and not_found:
196
+ try:
197
+ #outfile.write( "<" + str(ttype) + ">" )
198
+ on, off = self.style_string[str(ttype)]
199
+
200
+ # Like TerminalFormatter, add "reset colors" escape sequence
201
+ # on newline.
202
+ spl = value.split('\n')
203
+ for line in spl[:-1]:
204
+ if line:
205
+ outfile.write(on + line + off)
206
+ outfile.write('\n')
207
+ if spl[-1]:
208
+ outfile.write(on + spl[-1] + off)
209
+
210
+ not_found = False
211
+ #outfile.write( '#' + str(ttype) + '#' )
212
+
213
+ except KeyError:
214
+ #ottype = ttype
215
+ ttype = ttype[:-1]
216
+ #outfile.write( '!' + str(ottype) + '->' + str(ttype) + '!' )
217
+
218
+ if not_found:
219
+ outfile.write(value)