'''Generate one page API document from rustdoc.
This script parses HTML files generated by rustoc and generates a single page API
document.
'''
from html.parser import HTMLParser
pages = ['index.html',
'struct.BlazeSymbolizer.html',
'struct.SymbolizedResult.html',
'enum.SymbolSrcCfg.html',
'enum.SymbolizerFeature.html',
'fn.blazesym_new.html',
'fn.blazesym_free.html',
'fn.blazesym_symbolize.html',
'fn.blazesym_result_free.html',
'struct.blazesym.html',
'struct.sym_src_cfg.html',
'enum.blazesym_src_type.html',
'union.ssc_params.html',
'struct.ssc_elf.html',
'struct.ssc_kernel.html',
'struct.ssc_process.html',
'struct.blazesym_result.html',
'struct.blazesym_entry.html',
'struct.blazesym_csym.html',
]
def replace_text(src, replace, start, stop):
lines = src.split('\n')
if start[0] == stop[0]:
lineno = start[0]
lines[lineno] = lines[lineno][:start[1]] + replace + lines[lineno][stop[1]:]
else:
lines[start[0]] = lines[start[0]][:start[1]]
lines[stop[0]] = lines[stop[0]][stop[1]:]
lines[start[0] + 1: stop[0]] = [replace]
pass
return '\n'.join(lines)
class MyParser(HTMLParser):
def get_doc_range(self, start, end):
lines = self.raw_data.split('\n')
lines = lines[start[0] - 1: end[0]]
lines[-1] = lines[-1][:end[1]]
lines[0] = lines[0][start[1]:]
content = '\n'.join(lines)
if hasattr(self, 'replaces'):
for replace, rstart, rstop in reversed(self.replaces):
rstart = list(rstart)
rstop = list(rstop)
rstart[0] -= start[0]
rstop[0] -= start[0]
if rstart[0] == 0:
rstart[1] -= start[1]
pass
if rstop[0] == 0:
rstop[1] -= start[1]
pass
content = replace_text(content, replace, rstart, rstop)
pass
pass
return content
def get_pos_end_tag(self):
pos = self.getpos()
lines = self.raw_data.split('\n')
line = lines[pos[0] - 1]
col = line.find('>', pos[1]) + 1
return (pos[0], col)
def handle_starttag(self, tag, attrs):
attrs = dict(attrs)
if tag == 'body':
self.doc_type = attrs['class'].split()[-1]
elif tag == 'section' and 'id' in attrs and attrs['id'] == 'main-content':
if self.doc_type == 'crate':
self.start_pos = self.getpos()
elif self.doc_type in ('struct', 'enum', 'union'):
if not hasattr(self, 'start_pos'):
self.start_pos = self.getpos()
pass
pass
elif self.doc_type == 'fn':
if not hasattr(self, 'start_pos'):
self.start_pos = self.getpos()
pass
pass
pass
elif 'class' in attrs and 'example-wrap' in attrs['class'].split():
self.replacing = ' ......<<EXAMPLE>>......
'
self.replace_depth = 0
self.replace_start = self.getpos();
elif 'class' in attrs and 'item-decl' in attrs['class'].split():
self.replacing = ' ......<<DECLARATION>>......
'
self.replace_depth = 0
self.replace_start = self.getpos()
elif hasattr(self, 'replace_depth'):
self.replace_depth += 1
elif hasattr(self, 'depth'):
self.depth += 1
pass
elif hasattr(self, 'start_pos'):
if self.doc_type in ('struct', 'enum', 'union'):
if 'id' in attrs and attrs['id'].endswith('implementations'):
print('%s\n' % self.get_doc_range(self.start_pos, self.getpos()))
self.doc_type = ''
pass
elif self.doc_type == 'fn' and not hasattr(self, 'depth'):
self.depth = 0
pass
elif self.doc_type == 'crate' and 'class' in attrs and attrs['class'].endswith('top-doc'):
self.depth = 0
pass
pass
pass
def handle_endtag(self, tag):
if hasattr(self, 'replace_depth'):
if self.replace_depth > 0:
self.replace_depth -= 1
else:
del self.replace_depth
if not hasattr(self, 'replaces'):
self.replaces = []
pass
self.replaces.append((self.replacing, self.replace_start, self.get_pos_end_tag()))
pass
elif hasattr(self, 'depth'):
if self.depth > 0:
self.depth -= 1
pass
else:
del self.depth
if self.doc_type == 'crate':
content = self.get_doc_range(self.start_pos, self.get_pos_end_tag())
print('%s\n' % content)
pass
elif self.doc_type == 'fn':
print('%s\n' % self.get_doc_range(self.start_pos, self.get_pos_end_tag()))
self.doc_type = ''
pass
pass
pass
pass
pass
print('')
print('