[PATCH v3 3/5] doc/rst-man2any.py: Adjust to handle any output format, not just man pages

Subject: [PATCH v3 3/5] doc/rst-man2any.py: Adjust to handle any output format, not just man pages

Date: Sat, 12 Jul 2014 20:10:35 -0700

To: notmuch@notmuchmail.org

Cc: Tomi Ollila

From: W. Trevor King


For example, with these changes we can build HTML output using:

  $ rst-man2any.py -c rst2html -i ${SRCDIR} -o ${OUTDIR} -e html

The extension adjustment ensures that the output filenames from the
above command match what we currently generate with sphinx-html.

Adding argparse handling at the top of the script tipped this over
into "complicated enough to refactor" for me, so I've shifted the
single-file-conversion logic into a new convert() function and
streamlined things a bit.
---
 doc/Makefile.local |   4 +-
 doc/prerst2man.py  |  66 ---------------------------------
 doc/rst-man2any.py | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 107 insertions(+), 68 deletions(-)
 delete mode 100644 doc/prerst2man.py
 create mode 100755 doc/rst-man2any.py

diff --git a/doc/Makefile.local b/doc/Makefile.local
index d96cdd5..045f823 100644
--- a/doc/Makefile.local
+++ b/doc/Makefile.local
@@ -7,7 +7,7 @@ SPHINXOPTS    := -q
 SPHINXBUILD   = sphinx-build
 DOCBUILDDIR      := $(dir)/_build
 
-prerst2man := python $(srcdir)/$(dir)/prerst2man.py
+rstman2any := python $(srcdir)/$(dir)/rst-man2any.py
 mkdocdeps := python $(srcdir)/$(dir)/mkdocdeps.py
 
 # Internal variables.
@@ -49,7 +49,7 @@ ifeq ($(HAVE_SPHINX),1)
 	    mv $(DOCBUILDDIR)/man/*.$${section} $(DOCBUILDDIR)/man/man$${section}; \
 	done
 else ifeq ($(HAVE_RST2MAN),1)
-	$(prerst2man) "$(RST2MAN)" $(srcdir)/doc $(DOCBUILDDIR)/man
+	$(rstman2any) --converter "$(RST2MAN)" --input $(srcdir)/doc --output $(DOCBUILDDIR)/man
 else
 	@echo "Fatal: build dependency fail."
 	@false
diff --git a/doc/prerst2man.py b/doc/prerst2man.py
deleted file mode 100644
index 7d78e9b..0000000
--- a/doc/prerst2man.py
+++ /dev/null
@@ -1,66 +0,0 @@
-import sys
-from datetime import date
-from os.path import dirname, isdir
-from os import makedirs, system
-import re
-
-rst2man = sys.argv[1]
-sourcedir = sys.argv[2]
-outdir = sys.argv[3]
-
-sys.path.insert(0, sourcedir)
-import conf
-
-
-if not isdir(outdir):
-    makedirs(outdir, 0o755)
-
-
-def header(file, startdocname, command, description, authors, section):
-    file.write("""
-{0:s}
-{1:s}
-{2:s}
-
-:Date:   {3:s}
-:Version: {4:s}
-:Manual section: {5:d}
-:Manual group: {6:s}
-
-""".format(
-'-' * len(description),
-description,
-'-' * len(description),
-date.today().isoformat(), conf.release, section, conf.project))
-
-blankre = re.compile("^\s*$")
-for page in conf.man_pages:
-    outdirname = outdir + '/' + dirname(page[0])
-    if not isdir(outdirname):
-        makedirs(outdirname, 0o755)
-    filename = outdir + '/' + page[0] + '.rst'
-    outfile = open(filename, 'w')
-    infile = open(sourcedir + '/' + page[0] + '.rst', 'r')
-
-    # this is a crude hack. We look for the first blank line, and
-    # insert the rst2man header there.
-    #
-    # XXX consider really parsing input
-
-    count = 0
-    lines = infile.readlines()
-    for line in lines:
-        outfile.write(line)
-        if (blankre.match(line)):
-            break
-        count = count + 1
-
-    del lines[0:count + 1]
-
-    header(outfile, *page)
-
-    outfile.write("".join(lines))
-    outfile.close()
-
-    system('set -x; {0} {1} {2}/{3}.{4}'
-           .format(rst2man, filename, outdir, page[0], page[4]))
diff --git a/doc/rst-man2any.py b/doc/rst-man2any.py
new file mode 100755
index 0000000..52a4f9e
--- /dev/null
+++ b/doc/rst-man2any.py
@@ -0,0 +1,105 @@
+#!/usr/bin/python
+
+import argparse
+import datetime
+import os
+import sys
+
+
+def header(stream, description, authors, section, group, version):
+    "Write a man-page's ReST headers to 'stream'."
+    if len(authors) != 1:
+        raise NotImplementedError(
+            'cannot handle {count} authors ({authors}'.format(
+                count=len(authors), authors=authors))
+    stream.write('\n'.join([
+        '{description_rule}',
+        '{description}',
+        '{description_rule}',
+        '',
+        ':Author: {author}',
+        ':Date: {date}',
+        ':Version: {version}',
+        ':Manual section: {section:d}',
+        ':Manual group: {group}',
+        '',
+        '']).format(
+            description=description,
+            description_rule='-' * len(description),
+            author=authors[0],
+            date=datetime.date.today().isoformat(),
+            version=version,
+            section=section,
+            group=group))
+
+
+def convert(startdocname, description, authors, section,
+            group, version, source_dir, output_dir, command, extension=None):
+    """Convert the ReST source at path to the target format in 'output_dir'.
+
+    The initial arguments (startdocname through section) follow
+    Sphinx's man_pages option [1].
+
+    [1]: http://sphinx-doc.org/config.html#confval-man_pages
+    """
+    source_path = os.path.join(source_dir, startdocname) + '.rst'
+    output_base = os.path.join(output_dir, startdocname)
+    temp_path = output_base + '.rst'
+    if extension:
+        ext = extension
+    else:
+        ext = str(section)
+    output_path = '{base}.{ext}'.format(base=output_base, ext=ext)
+    dirname = os.path.dirname(output_path)
+    if not os.path.isdir(dirname):
+        os.makedirs(dirname, 0o755)
+    with open(source_path, 'r') as source:
+        with open(temp_path, 'w') as temp:
+            # this is a crude hack. We look for the first blank line, and
+            # insert the man-page headers there.
+            #
+            # XXX consider really parsing input
+            need_header = True
+            for line in source:
+                temp.write(line)
+                if need_header and not line.strip():
+                    header(
+                        stream=temp, description=description, authors=authors,
+                        section=section, group=group, version=version)
+                    need_header = False
+    os.system('set -x; {command} {source_path} {output_path}'.format(
+        command=command,
+        source_path=temp_path,
+        output_path=output_path))
+
+
+if __name__ == '__main__':
+    import argparse
+
+    parser = argparse.ArgumentParser(
+        description='Convert reStructuredText man pages to other formats.')
+    parser.add_argument(
+        '-i', '--input', default='_build',
+        help='Input directory')
+    parser.add_argument(
+        '-o', '--output', default='.',
+        help='Output directory')
+    parser.add_argument(
+        '-c', '--converter', default='rst2man',
+        help='ReST converter for your target output')
+    parser.add_argument(
+        '-e', '--extension',
+        help='Optional extension for the output files')
+
+    args = parser.parse_args()
+
+    sys.path.insert(0, args.input)
+    import conf
+
+    for startdocname, name, description, authors, section in conf.man_pages:
+        convert(
+            startdocname=startdocname, description=description,
+            authors=authors, section=section, group=conf.project,
+            version=conf.release, source_dir=args.input,
+            output_dir=args.output, command=args.converter,
+            extension=args.extension)
-- 
1.9.1.353.gc66d89d


Thread: