From: Guido Draheim Date: Sat, 24 Mar 2018 10:25:40 +0000 (+0100) Subject: allow dir2man to generate html, plus dir2index to complete the htmpages.tar #46 X-Git-Tag: v0.13.70~30 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=92c11598cb404d6f5a8f757d073942a6f6650ef6;p=zziplib allow dir2man to generate html, plus dir2index to complete the htmpages.tar #46 --- diff --git a/docs/Makefile.am b/docs/Makefile.am index 526b106..5050934 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -22,6 +22,7 @@ changelog = @top_srcdir@/ChangeLog EXTRA_DIST = make-doc.py $(doc_FILES) $(htm_FILES) $(SDL_RWOPS) \ make-doc.pl make-dbk.pl mksite.sh mksite.pl body.htm \ + dbk2man.py dir2index.py \ $(zzipdoc_FILES) sdocbook.css \ zziplib-manpages.dbk zziplib-master.dbk \ zziplib-manpages.tar @@ -193,6 +194,25 @@ htmpages.tar : zziplib.xml zzipmmapped.xml zzipfseeko.xml zziplib-manpages.dbk ; echo '$(DELETE); rm html/*.* ; rmdir html' \ ; $(DELETE); rm html/*.* ; rmdir html \ ; fi ; true + @ if test "$(XMLTO)" = ":" \ + ; then echo going to regenerate "$@" in subdir "'"html"'" \ + ; echo 'test ! -d html || rm /* ; test -d html || mkdir html' \ + ; test ! -d html || rm html/* ; test -d html || mkdir html \ + ; echo 'cp $(srcdir)/zziplib-manpages.dbk zziplib-manpages.xml' \ + ; cp $(srcdir)/zziplib-manpages.dbk zziplib-manpages.xml \ + ; echo '$(srcdir)/dbk2man.py -o html html zziplib.xml' \ + ; $(PYTHON) $(srcdir)/dbk2man.py -o html html zziplib.xml \ + ; echo '$(srcdir)/dbk2man.py -o html html zzipmmapped.xml' \ + ; $(PYTHON) $(srcdir)/dbk2man.py -o html html zzipmmapped.xml \ + ; echo '$(srcdir)/dbk2man.py -o html html zzipfseeko.xml' \ + ; $(PYTHON) $(srcdir)/dbk2man.py -o html html zzipfseeko.xml \ + ; echo '$(srcdir)/dir2index.py -o html html ' \ + ; $(PYTHON) $(srcdir)/dir2index.py -o html html \ + ; echo '$(PAX_TAR_CREATE) $@ html/*.*' \ + ; $(PAX_TAR_CREATE) $@ html/*.* \ + ; echo '$(DELETE); rm html/*.* ; rmdir html' \ + ; $(DELETE); rm html/*.* ; rmdir html \ + ; fi ; true @ if test -s $@ \ ; then echo cp $@ zziplib-$@ "(saved)"; cp $@ zziplib-$@ \ ; else echo cp $(srcdir)/zziplib-$@ $@; cp $(srcdir)/zziplib-$@ $@ \ diff --git a/docs/Makefile.in b/docs/Makefile.in index d04c677..219c5b3 100644 --- a/docs/Makefile.in +++ b/docs/Makefile.in @@ -325,6 +325,7 @@ SDL_RWOPS = $(SDL)/SDL_rwops_zzcat.c \ changelog = @top_srcdir@/ChangeLog EXTRA_DIST = make-doc.py $(doc_FILES) $(htm_FILES) $(SDL_RWOPS) \ make-doc.pl make-dbk.pl mksite.sh mksite.pl body.htm \ + dbk2man.py dir2index.py \ $(zzipdoc_FILES) sdocbook.css \ zziplib-manpages.dbk zziplib-master.dbk \ zziplib-manpages.tar @@ -699,6 +700,25 @@ htmpages.tar : zziplib.xml zzipmmapped.xml zzipfseeko.xml zziplib-manpages.dbk ; echo '$(DELETE); rm html/*.* ; rmdir html' \ ; $(DELETE); rm html/*.* ; rmdir html \ ; fi ; true + @ if test "$(XMLTO)" = ":" \ + ; then echo going to regenerate "$@" in subdir "'"html"'" \ + ; echo 'test ! -d html || rm /* ; test -d html || mkdir html' \ + ; test ! -d html || rm html/* ; test -d html || mkdir html \ + ; echo 'cp $(srcdir)/zziplib-manpages.dbk zziplib-manpages.xml' \ + ; cp $(srcdir)/zziplib-manpages.dbk zziplib-manpages.xml \ + ; echo '$(srcdir)/dbk2man.py -o html html zziplib.xml' \ + ; $(PYTHON) $(srcdir)/dbk2man.py -o html html zziplib.xml \ + ; echo '$(srcdir)/dbk2man.py -o html html zzipmmapped.xml' \ + ; $(PYTHON) $(srcdir)/dbk2man.py -o html html zzipmmapped.xml \ + ; echo '$(srcdir)/dbk2man.py -o html html zzipfseeko.xml' \ + ; $(PYTHON) $(srcdir)/dbk2man.py -o html html zzipfseeko.xml \ + ; echo '$(srcdir)/dir2index.py -o html html ' \ + ; $(PYTHON) $(srcdir)/dir2index.py -o html html \ + ; echo '$(PAX_TAR_CREATE) $@ html/*.*' \ + ; $(PAX_TAR_CREATE) $@ html/*.* \ + ; echo '$(DELETE); rm html/*.* ; rmdir html' \ + ; $(DELETE); rm html/*.* ; rmdir html \ + ; fi ; true @ if test -s $@ \ ; then echo cp $@ zziplib-$@ "(saved)"; cp $@ zziplib-$@ \ ; else echo cp $(srcdir)/zziplib-$@ $@; cp $(srcdir)/zziplib-$@ $@ \ diff --git a/docs/dbk2man.py b/docs/dbk2man.py index 83edef1..59a4b5f 100755 --- a/docs/dbk2man.py +++ b/docs/dbk2man.py @@ -1,4 +1,4 @@ -#! /usr/bin/python +#! /usr/bin/python> from __future__ import print_function """ Converts an xml-file with docbook elements into troff manual pages. @@ -15,6 +15,23 @@ import xml.etree.ElementTree as ET logg = logging.getLogger("dbk2man") +def esc(text): + text = text.replace(".", "\\&.") + text = text.replace("-", "\\-") + return text +def unescape(text): + text = text.replace('<', '<') + text = text.replace('>', '>') + text = text.replace('"', '"') + text = text.replace('&', '&') + return text +def htm(text): + text = text.replace('&', '&') + text = text.replace('<', '<') + text = text.replace('>', '>') + text = text.replace('"', '"') + return text + def parse_docbook(filename): tree = ET.parse(filename) return tree.getroot() @@ -47,16 +64,6 @@ def docbook2(man, root, subdirectory = "."): overview[refname] = refpurpose return overview -def esc(text): - text = text.replace(".", "\\&.") - text = text.replace("-", "\\-") - return text -def unescape(text): - text = text.replace('<', '<') - text = text.replace('>', '>') - text = text.replace('"', '"') - text = text.replace('&', '&') - return text def refentryinfo2(man, refentry, title): @@ -73,23 +80,36 @@ def refentryinfo2(man, refentry, title): if found is not None: refentrytitle = found.text found = section.find("manvolnum") if found is not None: manvolnum = found.text - header = [] - if refentrytitle: - header += [ refentrytitle ] - if manvolnum: - header += [ manvolnum ] - if date: - header += [ date ] - if productname: - header += [ productname ] - if title: - header += [ title ] - if header: + if man: + header = [] + if refentrytitle: + header += [ refentrytitle ] + if manvolnum: + header += [ manvolnum ] + if date: + header += [ date ] + if productname: + header += [ productname ] + if title: + header += [ title ] + if not header: + logg.warning("no found") + return "" text = '.TH ' + " ".join([ '"%s"' % esc(part) for part in header]) return text + "\n" else: - logg.warning("no found") - return "" + text = "" + if productname or title: + text += "%s: " % htm(productname or title) + text += htm(refentrytitle) + if manvolnum: + text += "(%s)" % htm(manvolnum) + text += "" + text += "\n" + '' % htm(productname or title) + text += "\n" + '' % htm(refentrytitle) + text += "\n" + '' % htm(manvolnum) + text += "\n" + '' % htm(date) + return text + "\n\n" def refentrytitle2(man, refentry, title = ""): refentrytitle = "" @@ -107,90 +127,166 @@ def refentrytitle2(man, refentry, title = ""): refname = found.text if refname not in refentries: refentries.append(refname) - if refentrytitle: + if not refentrytitle: + logg.warning("no found") + return "" + elif man: text = '.SH "NAME"' + "\n" text += "" + esc(", ".join(refentries)) text += " " + esc("-") text += " " + esc(refpurpose) return text + "\n" else: - logg.warning("no found") - return "" - + text = '

Name

' + "\n" + text += "

" + htm(", ".join(refentries)) + text += " " + htm("-") + text += " " + htm(refpurpose) + text += "

" + return text + "\n" def refsynopsisdiv2(man, refentry, title = ""): - section = refentry.find("refsynopsisdiv") - if section is not None: - text = '.SH "SYNOPSIS"' + "\n" - text += ".sp\n" - text += ".nf\n" - for funcsynopsis in section.findall("funcsynopsis"): - funcsynopsisinfo = "" - found = funcsynopsis.find("funcsynopsisinfo") - if found is not None: funcsynopsisinfo = found.text - if funcsynopsisinfo: - for info in funcsynopsisinfo.split("\n"): - text += '.B "%s"' % esc(info) - text += "\n" - text += ".sp" + "\n" - else: - logg.debug("no found") - logg.debug("\n%s", ET.tostring(funcsynopsis)) - funcs = 0 - for funcprototype in funcsynopsis.findall("funcprototype"): - item = ET.tostring(funcprototype) - item = item.replace("","") - item = item.replace("","") - if False: - item = item.replace("\n", " ") - item = item.replace("","") - item = item.replace("","") - item = item.replace("",'') - item = item.replace("",'') - items = item.split("") - text += '.BI %s' % " ".join(['"%s"' % part for part in items if part]) - else: - item = item.replace("","") - item = re.sub(r"([_\w]+)", lambda x: "\\fI%s\\fR" % x.group(1), item) - item = item.replace("",'') - item = item.replace("",'') - text += item + refsynopsisdiv = refentry.find("refsynopsisdiv") + if refsynopsisdiv is None: + logg.warning("no found") + return "" + if man: + return refsynopsisdiv2man(refsynopsisdiv, title) + else: + return refsynopsisdiv2htm(refsynopsisdiv, title) + +def refsynopsisdiv2man(refsynopsisdiv, title = ""): + text = '.SH "SYNOPSIS"' + "\n" + text += ".sp\n" + text += ".nf\n" + for funcsynopsis in refsynopsisdiv.findall("funcsynopsis"): + funcsynopsisinfo = "" + found = funcsynopsis.find("funcsynopsisinfo") + if found is not None: funcsynopsisinfo = found.text + if funcsynopsisinfo: + for info in funcsynopsisinfo.split("\n"): + text += '.B "%s"' % esc(info) text += "\n" - funcs += 1 - if not funcs: - logg.warning("no found") - logg.warning("\n%s", ET.tostring(funcsynopsis)) - text += ".fi" + "\n" text += ".sp" + "\n" - return text - else: - logg.warning("no found") - return "" + else: + logg.debug("no found") + logg.debug("\n%s", ET.tostring(funcsynopsis)) + funcs = 0 + for funcprototype in funcsynopsis.findall("funcprototype"): + item = ET.tostring(funcprototype) + item = item.replace("","") + item = item.replace("","") + if False: + item = item.replace("\n", " ") + item = item.replace("","") + item = item.replace("","") + item = item.replace("",'') + item = item.replace("",'') + items = item.split("") + text += '.BI %s' % " ".join(['"%s"' % part for part in items if part]) + else: + item = item.replace("","") + item = re.sub(r"([_\w]+)", lambda x: "\\fI%s\\fR" % x.group(1), item) + item = item.replace("",'') + item = item.replace("",'') + text += item + text += "\n" + funcs += 1 + if not funcs: + logg.warning("no found") + logg.warning("\n%s", ET.tostring(funcsynopsis)) + text += ".fi" + "\n" + text += ".sp" + "\n" + return text + +def refsynopsisdiv2htm(refsynopsisdiv, title = ""): + text = '

Synopsis

' + "\n" + text += '
' + "\n"
+    for funcsynopsis in refsynopsisdiv.findall("funcsynopsis"):
+        funcsynopsisinfo = ""
+        found = funcsynopsis.find("funcsynopsisinfo")
+        if found is not None: funcsynopsisinfo = found.text
+        if funcsynopsisinfo:
+            for info in funcsynopsisinfo.split("\n"):
+                text += '%s' % htm(info)
+                text += "\n"
+            text += "\n"
+        else:
+            logg.debug("no  found")
+            logg.debug("\n%s", ET.tostring(funcsynopsis))
+        funcs = 0
+        for funcprototype in funcsynopsis.findall("funcprototype"):
+            item = ET.tostring(funcprototype)
+            item = item.replace("","")
+            item = item.replace("","")
+            item = item.replace("","")
+            item = re.sub(r"([_\w]+)", lambda x: "%s" % x.group(1), item)
+            item = item.replace("",'')
+            item = item.replace("",'')
+            text += item 
+            text += "\n"
+            funcs += 1
+        if not funcs:
+            logg.warning("no  found")
+            logg.warning("\n%s", ET.tostring(funcsynopsis))
+        text += "
" + "\n" + return text def refsections2(man, refentry, title = ""): text = "" for refsect in refentry.findall("refsect1"): - head = refsect.find("title") - if head is not None: - text += '.SH "%s"' % (esc(head.text.upper())) - text += "\n" - for para in list(refsect): - if para.tag == 'title': - continue - if para.tag == 'para': - text += cleanpara(para) + "\n" + if man: + text += refsect2man(refsect, title) + text += ".sp\n" + else: + text += refsect2htm(refsect, title) + return text + + +def refsect2man(refsect, title = ""): + text = "" + head = refsect.find("title") + if head is not None: + text += '.SH "%s"' % (esc(head.text.upper())) + text += "\n" + for para in list(refsect): + if para.tag == 'title': + continue + if para.tag == 'para': + text += para2man(para) + "\n" + text += ".sp\n" + continue + if para.tag == 'itemizedlist': + for item in list(para): + text += para2man(item) + "\n" text += ".sp\n" - continue - if para.tag == 'itemizedlist': - for item in list(para): - text += cleanpara(item) + "\n" - text += ".sp\n" - continue - logg.warning("unknown para <%s>", para.tag) - text += ".sp\n" + continue + logg.warning("unknown para <%s>", para.tag) + return text + +def refsect2htm(refsect, title = ""): + text = "" + head = refsect.find("title") + if head is not None: + text += '

%s

' % htm(head.text) + text += "\n" + for para in list(refsect): + if para.tag == 'title': + continue + if para.tag == 'para': + text += "

" + para2htm(para) + text += "

" + "\n" + continue + if para.tag == 'itemizedlist': + text += "
    " + "\n" + for item in list(para): + text + "
  • " + para2htm(item) + text += "

  • " + "\n" + text += "
" + "\n" + continue + logg.warning("unknown para <%s>", para.tag) return text -def cleanpara(para): +def para2man(para): item = unescape(ET.tostring(para)) item = item.replace("\n", " ") item = item.replace(" ", " ") @@ -207,16 +303,39 @@ def cleanpara(para): item = item.replace("", "\\fP") return item +def para2htm(para): + item = unescape(ET.tostring(para)) + item = item.replace("\n", " ") + item = item.replace(" ", " ") + item = item.replace(" ", " ") + item = item.replace(" ", " ") + item = item.replace(" ", " ") + item = item.replace("", "") + item = item.replace("", "") + item = item.replace("", "") + item = item.replace("", "") + item = item.replace("", "") + item = item.replace("", "") + item = item.replace("", "") + item = item.replace("", "") + return item + def styleinfo2(man): - styles = [] - styles += [ ".ie \\n(.g .ds Aq \\(aq" ] - styles += [ ".el .ds Aq " ] # http://bugs.debian.org/507673 - styles += [ ".nh" ] # disable hyphenation - styles += [ ".ad l" ] # align left, no justification - return "".join([ "%s\n" % part for part in styles ]) + if man: + styles = [] + styles += [ ".ie \\n(.g .ds Aq \\(aq" ] + styles += [ ".el .ds Aq " ] # http://bugs.debian.org/507673 + styles += [ ".nh" ] # disable hyphenation + styles += [ ".ad l" ] # align left, no justification + return "".join([ "%s\n" % part for part in styles ]) + else: + return "" def refends2(man): - return "" + if man: + return "" + else: + return "" + "\n" def refentry2(man, refentry, subdirectory = ".", title = ""): if refentry.tag != "refentry": @@ -228,7 +347,7 @@ def refentry2(man, refentry, subdirectory = ".", title = ""): text += refentrytitle2(man, refentry, title) text += refsynopsisdiv2(man, refentry) text += refsections2(man, refentry) - text += refends2(man, refentry, title) + text += refends2(man) ### write the files refentrytitle = "" @@ -251,22 +370,27 @@ def refentry2(man, refentry, subdirectory = ".", title = ""): found = section.find("refpurpose") if found is not None: refpurpose = found.text # - written = 0 - for manpage in manpages: - if not refentrytitle: - refentrytitle = manpage - filename = "%s/man%s/%s.%s" % (subdirectory, manvolnum, manpage, manvolnum) - if manpage != refentrytitle: - manpagetext = ".so %s.%s\n" % (refentrytitle, manvolnum) - writefile(filename, manpagetext) - else: - manpagetext = text + if man: + written = 0 + for manpage in manpages: + if not refentrytitle: + refentrytitle = manpage + filename = "%s/man%s/%s.%s" % (subdirectory, manvolnum, manpage, manvolnum) + if manpage != refentrytitle: + manpagetext = ".so %s.%s\n" % (refentrytitle, manvolnum) + writefile(filename, manpagetext) + else: + manpagetext = text + writefile(filename, manpagetext) + written += 1 + if not written: + manpage = refentrytitle + filename = "%s/man%s/%s.%s" % (subdirectory, manvolnum, manpage, manvolnum) writefile(filename, manpagetext) - written += 1 - if not written: + else: manpage = refentrytitle - filename = "%s/man%s/%s.%s" % (subdirectory, manvolnum, manpage, manvolnum) - writefile(filename, manpagetext) + filename = "%s/%s.%s.%s" % (subdirectory, manpage, manvolnum, "html") + writefile(filename, text) # overview = {} for manpage in manpages: @@ -304,4 +428,4 @@ if __name__ == "__main__": if args and args[0] in ("man", "html"): make = args[0] args = args[1:] - dbk2(make, args, opt.into) + dbk2(make == 'man', args, opt.into) diff --git a/docs/dir2index.py b/docs/dir2index.py new file mode 100755 index 0000000..4bce424 --- /dev/null +++ b/docs/dir2index.py @@ -0,0 +1,74 @@ +#! /usr/bin/python> +from __future__ import print_function + +""" Searches through a directory and creates an index page for it +""" + +__author__ = "Guido U. Draheim" + +import logging +import os.path +import re +import xml.etree.ElementTree as ET + +logg = logging.getLogger("dir2index") + +def esc(text): + text = text.replace(".", "\\&.") + text = text.replace("-", "\\-") + return text +def unescape(text): + text = text.replace('<', '<') + text = text.replace('>', '>') + text = text.replace('"', '"') + text = text.replace('&', '&') + return text +def htm(text): + text = text.replace('&', '&') + text = text.replace('<', '<') + text = text.replace('>', '>') + text = text.replace('"', '"') + return text + +def parse_html(filename): + tree = ET.parse(filename) + return tree.getroot() + +def dir2(man, dirs, into): + text = "" + "\n" + for dirname in dirs: + text += "
    " + for filename in os.listdir(dirname): + name = filename + if name.endswith(".html"): name = name[:-5] + if name.endswith(".htm"): name = name[:-4] + if name.endswith(".3"): name = name[:-2] + text += '
  • %s
  • ' % (filename, name) + text += "\n" + text += "
" + text += "" + "\n" + writefile("%s/index.html" % into, text) + +def writefile(filename, manpagetext): + dirname = os.path.dirname(filename) + if not os.path.isdir(dirname): + logg.debug("mkdir %s", dirname) + os.makedirs(dirname) + with open(filename, "w") as f: + f.write(manpagetext) + logg.debug("written %s [%s]", filename, manpagetext.split("\n", 1)[0]) + +if __name__ == "__main__": + from optparse import OptionParser + _o = OptionParser("%prog [options] directories...") + _o.add_option("-o","--into", metavar="DIR", default=".", + help="specify base directory for output [%default]") + _o.add_option("-t","--make", metavar="DIR", default="man", + help="make 'man'/'html' output pages [%default]") + _o.add_option("-v","--verbose", action="count", default=0, + help="increase logging level [%default]") + opt, args = _o.parse_args() + logging.basicConfig(level = max(0, logging.WARNING - 10 * opt.verbose)) + # ensure commandline is compatible with "xmlto -o DIR TYPE INPUTFILE" + make = opt.make + dir2(make == 'man', args, opt.into)