File: Synopsis/Formatters/HTML/Markup/RST.py 1
2
3
4
5
6
7
8from Synopsis.Processor import Parameter
9from Synopsis.Formatters.HTML.Tags import *
10from Synopsis.Formatters.HTML.Markup import *
11from docutils.nodes import *
12from docutils.core import *
13from docutils.parsers.rst import roles
14import re, StringIO
15
16def span(name, rawtext, text, lineno, inliner, options={}, content=[]):
17 """Maps a rols to a <span class="role">...</span>."""
18
19 node = inline(rawtext, text)
20 node['classes'] = [name]
21 return [node], []
22
23
24class SummaryExtractor(NodeVisitor):
25 """A SummaryExtractor creates a document containing the first sentence of
26 a source document."""
27
28 def __init__(self, document):
29
30 NodeVisitor.__init__(self, document)
31 self.summary = None
32
33
34 def visit_paragraph(self, node):
35 """Copy the paragraph but only keep the first sentence."""
36
37 if self.summary is not None:
38 return
39
40 summary_pieces = []
41
42
43 for child in node:
44 if isinstance(child, Text):
45 m = re.match(r'(\s*[\w\W]*?\.)(\s|$)', child.astext())
46 if m:
47 summary_pieces.append(Text(m.group(1)))
48 break
49 else:
50 summary_pieces.append(Text(child))
51 else:
52 summary_pieces.append(child)
53
54 self.summary = self.document.copy()
55 para = node.copy()
56 para[:] = summary_pieces
57 self.summary[:] = [para]
58
59
60 def unknown_visit(self, node):
61 'Ignore all unknown nodes'
62
63 pass
64
65
66class RST(Formatter):
67 """Format summary and detail documentation according to restructured text markup.
68 """
69
70 roles = Parameter({'equation':span},
71 "A (name->function) mapping of custom ReST roles.")
72
73 def format(self, decl, view):
74
75 formatter = self
76
77 def ref(name, rawtext, text, lineno, inliner,
78 options={}, content=[]):
79
80
81
82 name = utils.unescape(text)
83 uri = formatter.lookup_symbol(name, decl.name[:-1])
84 if uri:
85 ref = rel(view.filename(), uri)
86 node = reference(rawtext, name, refuri=ref, **options)
87 else:
88 node = emphasis(rawtext, name)
89 return [node], []
90
91 for r in self.roles:
92 roles.register_local_role(r, self.roles[r])
93 roles.register_local_role('', ref)
94
95 errstream = StringIO.StringIO()
96 settings = {}
97 settings['halt_level'] = 2
98 settings['warning_stream'] = errstream
99 settings['traceback'] = True
100
101 doc = decl.annotations.get('doc')
102 if doc:
103 try:
104 doctree = publish_doctree(doc.text, settings_overrides=settings)
105
106 extractor = SummaryExtractor(doctree)
107 doctree.walk(extractor)
108
109 reader = docutils.readers.doctree.Reader(parser_name='null')
110
111
112 if extractor.summary:
113 pub = Publisher(reader, None, None,
114 source=io.DocTreeInput(extractor.summary),
115 destination_class=io.StringOutput)
116 pub.set_writer('html')
117 pub.process_programmatic_settings(None, None, None)
118 dummy = pub.publish(enable_exit_status=None)
119 summary = pub.writer.parts['html_body']
120
121
122 if (summary.startswith('<div class="document">\n') and
123 summary.endswith('</div>\n')):
124 summary=summary[23:-7]
125 else:
126 summary = ''
127
128
129 pub = Publisher(reader, None, None,
130 source=io.DocTreeInput(doctree),
131 destination_class=io.StringOutput)
132 pub.set_writer('html')
133 pub.process_programmatic_settings(None, None, None)
134 dummy = pub.publish(enable_exit_status=None)
135 details = pub.writer.parts['html_body']
136
137
138 if (details.startswith('<div class="document">\n') and
139 details.endswith('</div>\n')):
140 details=details[23:-7]
141
142 return Struct(summary, details)
143
144 except docutils.utils.SystemMessage, error:
145 xx, line, message = str(error).split(':', 2)
146 print 'In DocString attached to declaration at %s:%d:'%(decl.file.name,
147 decl.line)
148 print ' line %s:%s'%(line, message)
149
150 return Struct('', '')
151
Generated on Tue Jul 20 09:07:12 2010 by
synopsis (version devel)