1#!/usr/local/bin/python3.8
2
3""" Searches through a directory and creates an index page for it
4"""
5
6__author__ = "Guido U. Draheim"
7
8import logging
9import os.path
10import re
11import xml.etree.ElementTree as ET
12
13logg = logging.getLogger("dir2index")
14
15def esc(text):
16    text = text.replace(".", "\\&.")
17    text = text.replace("-", "\\-")
18    return text
19def unescape(text):
20    text = text.replace('&lt;', '<')
21    text = text.replace('&gt;', '>')
22    text = text.replace('&quot;', '"')
23    text = text.replace('&amp;', '&')
24    return text
25def htm(text):
26    text = text.replace('&', '&amp;')
27    text = text.replace('<', '&lt;')
28    text = text.replace('>', '&gt;')
29    text = text.replace('"', '&quot;')
30    return text
31def splitname(filename):
32    base = os.path.basename(filename)
33    name, ext = os.path.splitext(base)
34    if name.endswith(".3"): name = name[:-2]
35    return name
36
37def parse_html(filename):
38    tree = ET.parse(filename)
39    return tree.getroot()
40
41def zzip_sorted(filenames):
42    for name in filenames:
43        if "zziplib" in name:
44            yield name
45    for name in filenames:
46        if "zziplib" not in name:
47            yield name
48
49def dir2(man, dirs, into):
50    text = "<html><body>" + "\n"
51    file2name = {}
52    file2text = {}
53    for dirname in dirs:
54        for filename in os.listdir(dirname):
55            filepath = os.path.join(dirname, filename)
56            file2name[filename] = splitname(filename)
57            file2text[filename] = open(filepath).read()
58    # find the overview filenames and generate the pages order
59    overviews = []
60    for filename in file2text:
61        if " overview</title>" in file2text[filename]:
62            overviews.append(filename)
63    logg.warning("overviews = %s", overviews)
64    logg.warning("overviews = %s", [file2name[f] for f in overviews])
65    file2item = {}
66    pages = []
67    for overview in zzip_sorted(overviews):
68        if overview not in pages:
69            pages.append(overview)
70        for line in file2text[overview].split("\n"):
71            m = re.match('<li><a href="([^"]*)".*</li>', line)
72            if m:
73                filename = m.group(1)
74                if filename not in file2item:
75                    file2item[filename] = line
76                if filename not in pages:
77                    pages.append(filename)
78    for filename in sorted(file2name):
79        if filename not in pages:
80            pages.append(filename)
81    text += "<ul>"
82    for page in pages:
83        if page in file2item:
84            text += file2item[page]
85        elif page in overviews:
86            name = file2name[page]
87            logg.warning("page %s = %s", page, name)
88            text += '<li><a href="%s"><h4>%s</h4></a></li>' % (page, name)
89        else:
90            name = file2name[page]
91            text += '<li><a href="%s">%s</a></li>' % (page, name)
92        text += "\n"
93    text += "</ul>"
94    text += "</body></html>" + "\n"
95    writefile("%s/index.html" % into, text)
96
97def writefile(filename, manpagetext):
98    dirname = os.path.dirname(filename)
99    if not os.path.isdir(dirname):
100        logg.debug("mkdir %s", dirname)
101        os.makedirs(dirname)
102    with open(filename, "w") as f:
103        f.write(manpagetext)
104    logg.debug("written %s [%s]", filename, manpagetext.split("\n", 1)[0])
105
106if __name__ == "__main__":
107    from optparse import OptionParser
108    _o = OptionParser("%prog [options] directories...")
109    _o.add_option("-o","--into", metavar="DIR", default=".",
110        help="specify base directory for output [%default]")
111    _o.add_option("-t","--make", metavar="DIR", default="man",
112        help="make 'man'/'html' output pages [%default]")
113    _o.add_option("-v","--verbose", action="count", default=0,
114        help="increase logging level [%default]")
115    opt, args = _o.parse_args()
116    logging.basicConfig(level = max(0, logging.WARNING - 10 * opt.verbose))
117    # ensure commandline is compatible with "xmlto -o DIR TYPE INPUTFILE"
118    make = opt.make
119    dir2(make == 'man', args, opt.into)
120