##// END OF EJS Templates
Use int style instead of string....
Richard Everson -
Show More
@@ -1,177 +1,177
1 1 """Filters for processing ANSI colors within Jinja templates.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2013, the IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the Modified BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 import re
16 16 from IPython.utils import coloransi
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Classes and functions
20 20 #-----------------------------------------------------------------------------
21 21
22 22 __all__ = [
23 23 'strip_ansi',
24 24 'ansi2html',
25 25 'single_ansi2latex',
26 26 'ansi2latex'
27 27 ]
28 28
29 29 def strip_ansi(source):
30 30 """
31 31 Remove ansi from text
32 32
33 33 Parameters
34 34 ----------
35 35 source : str
36 36 Source to remove the ansi from
37 37 """
38 38
39 39 return re.sub(r'\033\[(\d|;)+?m', '', source)
40 40
41 41
42 42 def ansi2html(text):
43 43 """
44 44 Conver ansi colors to html colors.
45 45
46 46 Parameters
47 47 ----------
48 48 text : str
49 49 Text containing ansi colors to convert to html
50 50 """
51 51
52 52 ansi_colormap = {
53 53 '30': 'ansiblack',
54 54 '31': 'ansired',
55 55 '32': 'ansigreen',
56 56 '33': 'ansiyellow',
57 57 '34': 'ansiblue',
58 58 '35': 'ansipurple',
59 59 '36': 'ansicyan',
60 60 '37': 'ansigrey',
61 61 '01': 'ansibold',
62 62 }
63 63
64 64 # do ampersand first
65 65 text = text.replace('&', '&')
66 66 html_escapes = {
67 67 '<': '&lt;',
68 68 '>': '&gt;',
69 69 "'": '&apos;',
70 70 '"': '&quot;',
71 71 '`': '&#96;',
72 72 }
73 73
74 74 for c, escape in html_escapes.items():
75 75 text = text.replace(c, escape)
76 76
77 77 ansi_re = re.compile('\x1b' + r'\[([\dA-Fa-f;]*?)m')
78 78 m = ansi_re.search(text)
79 79 opened = False
80 80 cmds = []
81 81 opener = ''
82 82 closer = ''
83 83 while m:
84 84 cmds = m.groups()[0].split(';')
85 85 closer = '</span>' if opened else ''
86 86
87 87 # True if there is there more than one element in cmds, *or*
88 88 # if there is only one but it is not equal to a string of zeroes.
89 89 opened = len(cmds) > 1 or cmds[0] != '0' * len(cmds[0])
90 90 classes = []
91 91 for cmd in cmds:
92 92 if cmd in ansi_colormap:
93 93 classes.append(ansi_colormap.get(cmd))
94 94
95 95 if classes:
96 96 opener = '<span class="%s">' % (' '.join(classes))
97 97 else:
98 98 opener = ''
99 99 text = re.sub(ansi_re, closer + opener, text, 1)
100 100
101 101 m = ansi_re.search(text)
102 102
103 103 if opened:
104 104 text += '</span>'
105 105 return text
106 106
107 107
108 108 def single_ansi2latex(code):
109 109 """Converts single ansi markup to latex format.
110 110
111 111 Return latex code and number of open brackets.
112 112
113 113 Accepts codes like '\x1b[1;32m' (bold, red) and the short form '\x1b[32m' (red)
114 114
115 115 Colors are matched to those defined in coloransi, which defines colors
116 116 using the 0, 1 (bold) and 5 (blinking) styles. Styles 1 and 5 are
117 117 interpreted as bold. All other styles are mapped to 0. Note that in
118 118 coloransi, a style of 1 does not just mean bold; for example, Brown is
119 119 "0;33", but Yellow is "1;33". An empty string is returned for unrecognised
120 120 codes and the "reset" code '\x1b[m'.
121 121 """
122 122 components = code.split(';')
123 123 if len(components) > 1:
124 style = components[0][-1]
124 # Style is digits after '['
125 style = int(components[0].split('[')[-1])
125 126 color = components[1][:-1]
126 127 else:
127 style = '0'
128 style = 0
128 129 color = components[0][-3:-1]
129 130
130 131 # If the style is not normal (0), bold (1) or blinking (5) then treat it as normal
131 if style not in '015':
132 style = '0'
132 if style not in [0, 1, 5]:
133 style = 0
133 134
134 135 for name, tcode in coloransi.color_templates:
135 136 tstyle, tcolor = tcode.split(';')
137 tstyle = int(tstyle)
136 138 if tstyle == style and tcolor == color:
137 139 break
138 140 else:
139 141 return '', 0
140 142
141 if style == '5':
143 if style == 5:
142 144 name = name[5:] # BlinkRed -> Red, etc
143 145 name = name.lower()
144 146
145 if style in '15':
147 if style in [1, 5]:
146 148 return r'\textbf{\color{'+name+'}', 1
147 149 else:
148 150 return r'{\color{'+name+'}', 1
149 151
150 152 def ansi2latex(text):
151 153 """Converts ansi formated text to latex version
152 154
153 155 based on https://bitbucket.org/birkenfeld/sphinx-contrib/ansi.py
154 156 """
155 157 color_pattern = re.compile('\x1b\\[([^m]*)m')
156 158 last_end = 0
157 159 openbrack = 0
158 160 outstring = ''
159 161 for match in color_pattern.finditer(text):
160 162 head = text[last_end:match.start()]
161 163 outstring += head
162 164 if openbrack:
163 165 outstring += '}'*openbrack
164 166 openbrack = 0
165 167 code = match.group()
166 168 if not (code == coloransi.TermColors.Normal or openbrack):
167 169 texform, openbrack = single_ansi2latex(code)
168 170 outstring += texform
169 171 last_end = match.end()
170 172
171 173 # Add the remainer of the string and THEN close any remaining color brackets.
172 174 outstring += text[last_end:]
173 175 if openbrack:
174 176 outstring += '}'*openbrack
175 177 return outstring.strip()
176
177
@@ -1,87 +1,89
1 1 """
2 2 Module with tests for ansi filters
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (c) 2013, the IPython Development Team.
7 7 #
8 8 # Distributed under the terms of the Modified BSD License.
9 9 #
10 10 # The full license is in the file COPYING.txt, distributed with this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 from IPython.utils.coloransi import TermColors
18 18
19 19 from ...tests.base import TestsBase
20 20 from ..ansi import strip_ansi, ansi2html, ansi2latex
21 21
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Class
25 25 #-----------------------------------------------------------------------------
26 26
27 27 class TestAnsi(TestsBase):
28 28 """Contains test functions for ansi.py"""
29 29
30 30 def test_strip_ansi(self):
31 31 """strip_ansi test"""
32 32 correct_outputs = {
33 33 '%s%s%s' % (TermColors.Green, TermColors.White, TermColors.Red) : '',
34 34 'hello%s' % TermColors.Blue: 'hello',
35 35 'he%s%sllo' % (TermColors.Yellow, TermColors.Cyan) : 'hello',
36 36 '%shello' % TermColors.Blue : 'hello',
37 37 '{0}h{0}e{0}l{0}l{0}o{0}'.format(TermColors.Red) : 'hello',
38 38 'hel%slo' % TermColors.Green : 'hello',
39 39 'hello' : 'hello'}
40 40
41 41 for inval, outval in correct_outputs.items():
42 42 self._try_strip_ansi(inval, outval)
43 43
44 44
45 45 def _try_strip_ansi(self, inval, outval):
46 46 self.assertEqual(outval, strip_ansi(inval))
47 47
48 48
49 49 def test_ansi2html(self):
50 50 """ansi2html test"""
51 51 correct_outputs = {
52 52 '%s' % (TermColors.Red) : '<span class="ansired"></span>',
53 53 'hello%s' % TermColors.Blue: 'hello<span class="ansiblue"></span>',
54 54 'he%s%sllo' % (TermColors.Green, TermColors.Cyan) : 'he<span class="ansigreen"></span><span class="ansicyan">llo</span>',
55 55 '%shello' % TermColors.Yellow : '<span class="ansiyellow">hello</span>',
56 56 '{0}h{0}e{0}l{0}l{0}o{0}'.format(TermColors.White) : '<span class="ansigrey">h</span><span class="ansigrey">e</span><span class="ansigrey">l</span><span class="ansigrey">l</span><span class="ansigrey">o</span><span class="ansigrey"></span>',
57 57 'hel%slo' % TermColors.Green : 'hel<span class="ansigreen">lo</span>',
58 58 'hello' : 'hello'}
59 59
60 60 for inval, outval in correct_outputs.items():
61 61 self._try_ansi2html(inval, outval)
62 62
63 63
64 64 def _try_ansi2html(self, inval, outval):
65 65 self.fuzzy_compare(outval, ansi2html(inval))
66 66
67 67
68 68 def test_ansi2latex(self):
69 69 """ansi2latex test"""
70 70 correct_outputs = {
71 71 '%s' % (TermColors.Red) : r'{\color{red}}',
72 72 'hello%s' % TermColors.Blue: r'hello{\color{blue}}',
73 73 'he%s%sllo' % (TermColors.Green, TermColors.Cyan) : r'he{\color{green}}{\color{cyan}llo}',
74 74 '%shello' % TermColors.Yellow : r'\textbf{\color{yellow}hello}',
75 75 '{0}h{0}e{0}l{0}l{0}o{0}'.format(TermColors.White) : r'\textbf{\color{white}h}\textbf{\color{white}e}\textbf{\color{white}l}\textbf{\color{white}l}\textbf{\color{white}o}\textbf{\color{white}}',
76 76 'hel%slo' % TermColors.Green : r'hel{\color{green}lo}',
77 77 'hello' : 'hello',
78 78 u'hello\x1b[34mthere\x1b[mworld' : u'hello{\\color{blue}there}world',
79 u'hello\x1b[mthere': u'hellothere'
79 u'hello\x1b[mthere': u'hellothere',
80 u'hello\x1b[01;34mthere' : u"hello\\textbf{\\color{lightblue}there}",
81 u'hello\x1b[001;34mthere' : u"hello\\textbf{\\color{lightblue}there}"
80 82 }
81 83
82 84 for inval, outval in correct_outputs.items():
83 85 self._try_ansi2latex(inval, outval)
84 86
85 87
86 88 def _try_ansi2latex(self, inval, outval):
87 89 self.fuzzy_compare(outval, ansi2latex(inval), case_sensitive=True)
General Comments 0
You need to be logged in to leave comments. Login now