shithub: riscv

ref: 1e8eb61a3715b12d8bc1cfd866f5bb180f2941f2
dir: /sys/src/cmd/python/Doc/tools/mkmodindex/

View raw version
#! /usr/bin/env python
#  -*- Python -*-

"""usage: %(program)s [options] file...

Supported options:

    --address addr
    -a addr         Set the address text to include at the end of the generated
                    HTML; this should be used for contact information.
    --columns cols
    -c cols         Set the number of columns each index section should be
                    displayed in.  The default is 1.
    --help
    -h              Display this help message.
    --letters
    -l              Split the output into sections by letter.
    --output file
    -o file         Write output to 'file' instead of standard out.
    --iconserver is Use 'is' as the directory containing icons for the
                    navigation bar.  The default is 'icons'.
    --title str     Set the page title to 'str'.  The default is 'Global
                    Module Index'.
    --uplink url    Set the upward link URL.  The default is './'.
    --uptitle str   Set the upward link title.  The default is 'Python
                    Documentation Index'.
"""
import os
import re
import sys

from xml.sax.saxutils import quoteattr

import buildindex
import support


class IndexOptions(support.Options):
    aesop_type = "links"

    def __init__(self):
        support.Options.__init__(self)
        self.add_args("l", ["letters"])
        self.letters = 0

    def handle_option(self, opt, val):
        if opt in ("-l", "--letters"):
            self.letters = 1

    def usage(self):
        program = os.path.basename(sys.argv[0])
        print __doc__ % {"program": program}

    links = [
        ('author', 'acks.html',  'Acknowledgements'),
        ('help',   'about.html', 'About the Python Documentation'),
        ]

    def get_header(self):
        header = support.Options.get_header(self)
        s = ''
        for rel, href, title in self.links:
            s += '<link rel="%s" href="%s"' % (rel, href)
            if title:
                s += ' title=' + quoteattr(title)
            s += '>\n  '
        return header.replace("<link ", s + "<link ", 1)


class Node(buildindex.Node):
    def __init__(self, link, str, seqno, platinfo):
        self.annotation = platinfo or None
        if str[0][-5:] == "</tt>":
            str = str[:-5]
        self.modname = str
        buildindex.Node.__init__(self, link, self.modname, seqno)
        if platinfo:
            s = '<tt class="module">%s</tt> %s' \
                % (self.modname, self.annotation)
        else:
            s = '<tt class="module">%s</tt>' % str
        self.text = [s]

    def __str__(self):
        if self.annotation:
            return '<tt class="module">%s</tt> %s' \
                   % (self.modname, self.annotation)
        else:
            return '<tt class="module">%s</tt>' % self.modname

_rx = re.compile(
    "<dt><a href=['\"](module-.*\.html)(?:#l2h-\d+)?['\"]>"
    "<tt class=['\"]module['\"]>([a-zA-Z_][a-zA-Z0-9_.]*)</tt>\s*(<em>"
    "\(<span class=['\"]platform['\"]>.*</span>\)</em>)?</a>")

def main():
    options = IndexOptions()
    options.variables["title"] = "Global Module Index"
    options.parse(sys.argv[1:])
    args = options.args
    if not args:
        args = ["-"]
    #
    # Collect the input data:
    #
    nodes = []
    has_plat_flag = 0
    for ifn in args:
        if ifn == "-":
            ifp = sys.stdin
            dirname = ''
        else:
            ifp = open(ifn)
            dirname = os.path.dirname(ifn)
        while 1:
            line = ifp.readline()
            if not line:
                break
            m = _rx.match(line)
            if m:
                # This line specifies a module!
                basename, modname, platinfo = m.group(1, 2, 3)
                has_plat_flag = has_plat_flag or platinfo
                linkfile = os.path.join(dirname, basename)
                nodes.append(Node('<a href="%s">' % linkfile, modname,
                                  len(nodes), platinfo))
        ifp.close()
    #
    # Generate all output:
    #
    num_nodes = len(nodes)
    # Here's the HTML generation:
    parts = [options.get_header(),
             buildindex.process_nodes(nodes, options.columns, options.letters),
             options.get_footer(),
             ]
    if has_plat_flag:
        parts.insert(1, PLAT_DISCUSS)
    html = ''.join(parts)
    program = os.path.basename(sys.argv[0])
    fp = options.get_output_file()
    fp.write(html.rstrip() + "\n")
    if options.outputfile == "-":
        sys.stderr.write("%s: %d index nodes\n" % (program, num_nodes))
    else:
        print
        print "%s: %d index nodes" % (program, num_nodes)


PLAT_DISCUSS = """
<p> Some module names are followed by an annotation indicating what
platform they are available on.</p>

"""


if __name__ == "__main__":
    main()