Synopsis - Synopsis/Formatters/HTML/Markup/RST.py

File: Synopsis/Formatters/HTML/Markup/RST.py

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

Generated on Thu Apr 16 16:27:13 2009 by
synopsis (version devel)