1 # Note: Work in progress
6 from StringIO import StringIO
9 from Code import CCodeWriter
11 # need one-characters subsitutions (for now) so offsets aren't off
12 special_chars = [('<', '\xF0', '<'),
13 ('>', '\xF1', '>'),
14 ('&', '\xF2', '&')]
16 class AnnotationCCodeWriter(CCodeWriter):
18 def __init__(self, f):
19 CCodeWriter.__init__(self, self)
20 self.buffer = StringIO()
27 return self.real_f.getvalue()
33 def mark_pos(self, pos):
35 # CCodeWriter.mark_pos(self, pos)
39 code = self.code[self.last_pos[1]]
42 self.code[self.last_pos[1]] = code + self.buffer.getvalue()
43 self.buffer = StringIO()
46 def annotate(self, pos, item):
47 self.annotations.append((pos, item))
49 def save_annotation(self, filename):
53 for k in range(len(lines)):
55 for c, cc, html in special_chars:
56 line = line.replace(c, cc)
60 for pos, item in self.annotations:
61 if pos[0] == filename:
63 size, end = item.end()
65 all.append((pos, start))
66 all.append(((filename, pos[1], pos[2]+size), end))
68 all.append((pos, start+end))
77 lines[line_no] = line[:col] + item + line[col:]
79 f = open("%s.html" % filename, "w")
83 <style type="text/css">
85 body { font-family: courier; font-size: 12; }
87 .code { font-size: 9; color: #444444; display: none; margin-left: 20px; }
88 .py_api { color: red; }
89 .pyx_api { color: #FF3000; }
90 .py_macro_api { color: #FF8000; }
91 .error_goto { color: #FF8000; }
95 .coerce { color: #008000; border: 1px dotted #008000 }
97 .py_attr { color: #FF0000; font-weight: bold; }
98 .c_attr { color: #0000FF; }
100 .py_call { color: #FF0000; font-weight: bold; }
101 .c_call { color: #0000FF; }
103 .line { margin: 0em }
107 function toggleDiv(id) {
108 theDiv = document.getElementById(id);
109 if (theDiv.style.display == 'none') theDiv.style.display = 'block';
110 else theDiv.style.display = 'none';
116 f.write('<p>Generated by Cython %s on %s\n' % (Version.version, time.asctime()))
117 c_file = os.path.basename(filename)[:-3] + 'c'
118 f.write('<p>Raw output: <a href="%s">%s</a>\n' % (c_file, c_file))
121 py_c_api = re.compile('(Py[A-Z][a-z]+_[A-Z][a-z][A-Za-z_]+)')
122 pyx_api = re.compile('(__Pyx[A-Za-z_]+)\(')
123 py_marco_api = re.compile('(Py[A-Za-z]*_[A-Z][A-Z_]+)')
124 error_goto = re.compile(r'((; *if .*)? \{__pyx_filename = .*goto __pyx_L\w+;\})')
134 code, c_api_calls = py_c_api.subn(r"<span class='py_api'>\1</span>", code)
135 code, pyx_api_calls = pyx_api.subn(r"<span class='pyx_api'>\1</span>(", code)
136 code, macro_api_calls = py_marco_api.subn(r"<span class='py_macro_api'>\1</span>", code)
137 code, error_goto_calls = error_goto.subn(r"<span class='error_goto'>\1</span>", code)
139 code = code.replace("<span class='error_goto'>;", ";<span class='error_goto'>")
141 color = "FFFF%02x" % int(255/(1+(5*c_api_calls+2*pyx_api_calls+macro_api_calls)/10.0))
142 f.write("<pre class='line' style='background-color: #%s' onclick='toggleDiv(\"line%s\")'>" % (color, k))
145 for c, cc, html in special_chars:
146 line = line.replace(cc, html)
147 f.write(line.rstrip())
150 f.write("<pre id='line%s' class='code' style='background-color: #%s'>%s</pre>" % (k, color, code))
151 f.write('</body></html>\n')
155 # TODO: make this cleaner
156 def escape(raw_string):
157 raw_string = raw_string.replace("\'", r"’")
158 raw_string = raw_string.replace('\"', r'"')
159 raw_string = raw_string.replace('\n', r'<br>\n')
160 raw_string = raw_string.replace('\t', r'\t')
164 class AnnotationItem:
166 def __init__(self, style, text, tag="", size=0):
173 return "<span class='tag %s' title='%s'>%s" % (self.style, self.text, self.tag)
176 return self.size, "</span>"