9 tool (http://frexx.de/xterm-256-notes/data/xterm256-conv2.tar.bz2) |
9 tool (http://frexx.de/xterm-256-notes/data/xterm256-conv2.tar.bz2) |
10 by Wolfgang Frisch. |
10 by Wolfgang Frisch. |
11 |
11 |
12 Formatter version 1. |
12 Formatter version 1. |
13 |
13 |
14 :copyright: Copyright 2006-2017 by the Pygments team, see AUTHORS. |
14 :copyright: Copyright 2006-2019 by the Pygments team, see AUTHORS. |
15 :license: BSD, see LICENSE for details. |
15 :license: BSD, see LICENSE for details. |
16 """ |
16 """ |
17 |
17 |
18 # TODO: |
18 # TODO: |
19 # - Options to map style's bold/underline/italic/border attributes |
19 # - Options to map style's bold/underline/italic/border attributes |
33 |
33 |
34 __all__ = ['Terminal256Formatter', 'TerminalTrueColorFormatter'] |
34 __all__ = ['Terminal256Formatter', 'TerminalTrueColorFormatter'] |
35 |
35 |
36 |
36 |
37 class EscapeSequence: |
37 class EscapeSequence: |
38 def __init__(self, fg=None, bg=None, bold=False, underline=False): |
38 def __init__(self, fg=None, bg=None, bold=False, underline=False, italic=False): |
39 self.fg = fg |
39 self.fg = fg |
40 self.bg = bg |
40 self.bg = bg |
41 self.bold = bold |
41 self.bold = bold |
42 self.underline = underline |
42 self.underline = underline |
|
43 self.italic = italic |
43 |
44 |
44 def escape(self, attrs): |
45 def escape(self, attrs): |
45 if len(attrs): |
46 if len(attrs): |
46 return "\x1b[" + ";".join(attrs) + "m" |
47 return "\x1b[" + ";".join(attrs) + "m" |
47 return "" |
48 return "" |
48 |
49 |
49 def color_string(self): |
50 def color_string(self): |
50 attrs = [] |
51 attrs = [] |
51 if self.fg is not None: |
52 if self.fg is not None: |
52 if self.fg in ansicolors: |
53 if self.fg in ansicolors: |
53 esc = codes[self.fg[5:]] |
54 esc = codes[self.fg.replace('ansi','')] |
54 if ';01m' in esc: |
55 if ';01m' in esc: |
55 self.bold = True |
56 self.bold = True |
56 # extract fg color code. |
57 # extract fg color code. |
57 attrs.append(esc[2:4]) |
58 attrs.append(esc[2:4]) |
58 else: |
59 else: |
59 attrs.extend(("38", "5", "%i" % self.fg)) |
60 attrs.extend(("38", "5", "%i" % self.fg)) |
60 if self.bg is not None: |
61 if self.bg is not None: |
61 if self.bg in ansicolors: |
62 if self.bg in ansicolors: |
62 esc = codes[self.bg[5:]] |
63 esc = codes[self.bg.replace('ansi','')] |
63 # extract fg color code, add 10 for bg. |
64 # extract fg color code, add 10 for bg. |
64 attrs.append(str(int(esc[2:4])+10)) |
65 attrs.append(str(int(esc[2:4])+10)) |
65 else: |
66 else: |
66 attrs.extend(("48", "5", "%i" % self.bg)) |
67 attrs.extend(("48", "5", "%i" % self.bg)) |
67 if self.bold: |
68 if self.bold: |
68 attrs.append("01") |
69 attrs.append("01") |
69 if self.underline: |
70 if self.underline: |
70 attrs.append("04") |
71 attrs.append("04") |
|
72 if self.italic: |
|
73 attrs.append("03") |
71 return self.escape(attrs) |
74 return self.escape(attrs) |
72 |
75 |
73 def true_color_string(self): |
76 def true_color_string(self): |
74 attrs = [] |
77 attrs = [] |
75 if self.fg: |
78 if self.fg: |
78 attrs.extend(("48", "2", str(self.bg[0]), str(self.bg[1]), str(self.bg[2]))) |
81 attrs.extend(("48", "2", str(self.bg[0]), str(self.bg[1]), str(self.bg[2]))) |
79 if self.bold: |
82 if self.bold: |
80 attrs.append("01") |
83 attrs.append("01") |
81 if self.underline: |
84 if self.underline: |
82 attrs.append("04") |
85 attrs.append("04") |
|
86 if self.italic: |
|
87 attrs.append("03") |
83 return self.escape(attrs) |
88 return self.escape(attrs) |
84 |
89 |
85 def reset_string(self): |
90 def reset_string(self): |
86 attrs = [] |
91 attrs = [] |
87 if self.fg is not None: |
92 if self.fg is not None: |
88 attrs.append("39") |
93 attrs.append("39") |
89 if self.bg is not None: |
94 if self.bg is not None: |
90 attrs.append("49") |
95 attrs.append("49") |
91 if self.bold or self.underline: |
96 if self.bold or self.underline or self.italic: |
92 attrs.append("00") |
97 attrs.append("00") |
93 return self.escape(attrs) |
98 return self.escape(attrs) |
94 |
99 |
95 |
100 |
96 class Terminal256Formatter(Formatter): |
101 class Terminal256Formatter(Formatter): |
107 |
112 |
108 .. versionchanged:: 2.2 |
113 .. versionchanged:: 2.2 |
109 If the used style defines foreground colors in the form ``#ansi*``, then |
114 If the used style defines foreground colors in the form ``#ansi*``, then |
110 `Terminal256Formatter` will map these to non extended foreground color. |
115 `Terminal256Formatter` will map these to non extended foreground color. |
111 See :ref:`AnsiTerminalStyle` for more information. |
116 See :ref:`AnsiTerminalStyle` for more information. |
|
117 |
|
118 .. versionchanged:: 2.4 |
|
119 The ANSI color names have been updated with names that are easier to |
|
120 understand and align with colornames of other projects and terminals. |
|
121 See :ref:`this table <new-ansi-color-names>` for more information. |
|
122 |
112 |
123 |
113 Options accepted: |
124 Options accepted: |
114 |
125 |
115 `style` |
126 `style` |
116 The style to use, can be a string or a Style subclass (default: |
127 The style to use, can be a string or a Style subclass (default: |
127 self.best_match = {} |
138 self.best_match = {} |
128 self.style_string = {} |
139 self.style_string = {} |
129 |
140 |
130 self.usebold = 'nobold' not in options |
141 self.usebold = 'nobold' not in options |
131 self.useunderline = 'nounderline' not in options |
142 self.useunderline = 'nounderline' not in options |
|
143 self.useitalic = 'noitalic' not in options |
132 |
144 |
133 self._build_color_table() # build an RGB-to-256 color conversion table |
145 self._build_color_table() # build an RGB-to-256 color conversion table |
134 self._setup_styles() # convert selected style's colors to term. colors |
146 self._setup_styles() # convert selected style's colors to term. colors |
135 |
147 |
136 def _build_color_table(self): |
148 def _build_color_table(self): |
187 return match |
199 return match |
188 |
200 |
189 def _color_index(self, color): |
201 def _color_index(self, color): |
190 index = self.best_match.get(color, None) |
202 index = self.best_match.get(color, None) |
191 if color in ansicolors: |
203 if color in ansicolors: |
192 # strip the `#ansi` part and look up code |
204 # strip the `ansi/#ansi` part and look up code |
193 index = color |
205 index = color |
194 self.best_match[color] = index |
206 self.best_match[color] = index |
195 if index is None: |
207 if index is None: |
196 try: |
208 try: |
197 rgb = int(str(color), 16) |
209 rgb = int(str(color), 16) |
219 escape.bg = self._color_index(ndef['bgcolor']) |
231 escape.bg = self._color_index(ndef['bgcolor']) |
220 if self.usebold and ndef['bold']: |
232 if self.usebold and ndef['bold']: |
221 escape.bold = True |
233 escape.bold = True |
222 if self.useunderline and ndef['underline']: |
234 if self.useunderline and ndef['underline']: |
223 escape.underline = True |
235 escape.underline = True |
|
236 if self.useitalic and ndef['italic']: |
|
237 escape.italic = True |
224 self.style_string[str(ttype)] = (escape.color_string(), |
238 self.style_string[str(ttype)] = (escape.color_string(), |
225 escape.reset_string()) |
239 escape.reset_string()) |
226 |
240 |
227 def format(self, tokensource, outfile): |
241 def format(self, tokensource, outfile): |
228 # hack: if the output is a terminal and has an encoding set, |
|
229 # use that to avoid unicode encode problems |
|
230 if not self.encoding and hasattr(outfile, "encoding") and \ |
|
231 hasattr(outfile, "isatty") and outfile.isatty() and \ |
|
232 sys.version_info < (3,): |
|
233 self.encoding = outfile.encoding |
|
234 return Formatter.format(self, tokensource, outfile) |
242 return Formatter.format(self, tokensource, outfile) |
235 |
243 |
236 def format_unencoded(self, tokensource, outfile): |
244 def format_unencoded(self, tokensource, outfile): |
237 for ttype, value in tokensource: |
245 for ttype, value in tokensource: |
238 not_found = True |
246 not_found = True |
303 escape.bg = self._color_tuple(ndef['bgcolor']) |
311 escape.bg = self._color_tuple(ndef['bgcolor']) |
304 if self.usebold and ndef['bold']: |
312 if self.usebold and ndef['bold']: |
305 escape.bold = True |
313 escape.bold = True |
306 if self.useunderline and ndef['underline']: |
314 if self.useunderline and ndef['underline']: |
307 escape.underline = True |
315 escape.underline = True |
|
316 if self.useitalic and ndef['italic']: |
|
317 escape.italic = True |
308 self.style_string[str(ttype)] = (escape.true_color_string(), |
318 self.style_string[str(ttype)] = (escape.true_color_string(), |
309 escape.reset_string()) |
319 escape.reset_string()) |