[PATCH v3 3/5] doc/rst-man2any.py: Adjust to handle any output format, not just man...
authorW. Trevor King <wking@tremily.us>
Sun, 13 Jul 2014 03:10:35 +0000 (20:10 +1700)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 18:03:32 +0000 (10:03 -0800)
a1/f44de8442f7ba881bae89b718ff81f9f085b5c [new file with mode: 0644]

diff --git a/a1/f44de8442f7ba881bae89b718ff81f9f085b5c b/a1/f44de8442f7ba881bae89b718ff81f9f085b5c
new file mode 100644 (file)
index 0000000..74450f1
--- /dev/null
@@ -0,0 +1,298 @@
+Return-Path: <wking@tremily.us>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+       by olra.theworths.org (Postfix) with ESMTP id 78B29431FC0\r
+       for <notmuch@notmuchmail.org>; Sat, 12 Jul 2014 20:12:19 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References"\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0 tagged_above=-999 required=5\r
+       tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001]\r
+       autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+       by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+       with ESMTP id SpCliUMAQKww for <notmuch@notmuchmail.org>;\r
+       Sat, 12 Jul 2014 20:12:12 -0700 (PDT)\r
+Received: from qmta12.emeryville.ca.mail.comcast.net\r
+       (qmta12.emeryville.ca.mail.comcast.net [76.96.27.227])\r
+       by olra.theworths.org (Postfix) with ESMTP id 6D29B431FBD\r
+       for <notmuch@notmuchmail.org>; Sat, 12 Jul 2014 20:11:48 -0700 (PDT)\r
+Received: from omta01.emeryville.ca.mail.comcast.net ([76.96.30.11])\r
+       by qmta12.emeryville.ca.mail.comcast.net with comcast\r
+       id RfAY1o0030EPcho01fBndl; Sun, 13 Jul 2014 03:11:48 +0000\r
+Received: from odin.tremily.us ([24.18.63.50])\r
+       by omta01.emeryville.ca.mail.comcast.net with comcast\r
+       id RfBU1o00n152l3L8MfBlCe; Sun, 13 Jul 2014 03:11:47 +0000\r
+Received: from mjolnir.tremily.us (unknown [192.168.0.150])\r
+       by odin.tremily.us (Postfix) with ESMTPS id 48C551286F05;\r
+       Sat, 12 Jul 2014 20:11:27 -0700 (PDT)\r
+Received: (nullmailer pid 31452 invoked by uid 1000);\r
+       Sun, 13 Jul 2014 03:10:44 -0000\r
+From: "W. Trevor King" <wking@tremily.us>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH v3 3/5] doc/rst-man2any.py: Adjust to handle any output\r
+ format,       not just man pages\r
+Date: Sat, 12 Jul 2014 20:10:35 -0700\r
+Message-Id:\r
+ <bb3c2c35d9332fd062717baa6f15a464cb04eda1.1405220724.git.wking@tremily.us>\r
+X-Mailer: git-send-email 1.9.1.353.gc66d89d\r
+In-Reply-To: <cover.1405220724.git.wking@tremily.us>\r
+References: <cover.1405220724.git.wking@tremily.us>\r
+In-Reply-To: <cover.1405220724.git.wking@tremily.us>\r
+References: <cover.1405220724.git.wking@tremily.us>\r
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcast.net;\r
+       s=q20140121; t=1405221108;\r
+       bh=3WWFZti79msppoZ960v8bCxxX9vSsferWsk0hyU7J+A=;\r
+       h=Received:Received:Received:Received:From:To:Subject:Date:\r
+       Message-Id;\r
+       b=DaOUAM/puyCay51B44Rg51PGxWdR1gh75+H1swojVHSlsAaVWrN+PbiE7L2JPS/yz\r
+       85HpQfMpTiGM6sTqteZ/rLUq711z5pGYepkQy/KidT86cyF3POdl8ZVAcbTfn/i4Ph\r
+       vX8wEmOvCsHphx8dA/pTdHHYBGgWprdin5eSSj0WP/SAWR8KA1aj4w+GoMVq+RSlO4\r
+       ECmCoNsYjlEJ+p7qLEMIeHSQzqCSnXH1vGJlCt+KWsT7b5XBDUnh7ReubYXG4r/2o5\r
+       OFOXBZ8oXW/3tSYUjYN+UJR4sO/2UJjZOqF+W/C/e4hk4WHKQkrsCggqOPMTUhuQ0Q\r
+       0vzQmyNJEiydw==\r
+Cc: Tomi Ollila <tomi.ollila@iki.fi>\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+       <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Sun, 13 Jul 2014 03:12:19 -0000\r
+\r
+For example, with these changes we can build HTML output using:\r
+\r
+  $ rst-man2any.py -c rst2html -i ${SRCDIR} -o ${OUTDIR} -e html\r
+\r
+The extension adjustment ensures that the output filenames from the\r
+above command match what we currently generate with sphinx-html.\r
+\r
+Adding argparse handling at the top of the script tipped this over\r
+into "complicated enough to refactor" for me, so I've shifted the\r
+single-file-conversion logic into a new convert() function and\r
+streamlined things a bit.\r
+---\r
+ doc/Makefile.local |   4 +-\r
+ doc/prerst2man.py  |  66 ---------------------------------\r
+ doc/rst-man2any.py | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+ 3 files changed, 107 insertions(+), 68 deletions(-)\r
+ delete mode 100644 doc/prerst2man.py\r
+ create mode 100755 doc/rst-man2any.py\r
+\r
+diff --git a/doc/Makefile.local b/doc/Makefile.local\r
+index d96cdd5..045f823 100644\r
+--- a/doc/Makefile.local\r
++++ b/doc/Makefile.local\r
+@@ -7,7 +7,7 @@ SPHINXOPTS    := -q\r
+ SPHINXBUILD   = sphinx-build\r
+ DOCBUILDDIR      := $(dir)/_build\r
\r
+-prerst2man := python $(srcdir)/$(dir)/prerst2man.py\r
++rstman2any := python $(srcdir)/$(dir)/rst-man2any.py\r
+ mkdocdeps := python $(srcdir)/$(dir)/mkdocdeps.py\r
\r
+ # Internal variables.\r
+@@ -49,7 +49,7 @@ ifeq ($(HAVE_SPHINX),1)\r
+           mv $(DOCBUILDDIR)/man/*.$${section} $(DOCBUILDDIR)/man/man$${section}; \\r
+       done\r
+ else ifeq ($(HAVE_RST2MAN),1)\r
+-      $(prerst2man) "$(RST2MAN)" $(srcdir)/doc $(DOCBUILDDIR)/man\r
++      $(rstman2any) --converter "$(RST2MAN)" --input $(srcdir)/doc --output $(DOCBUILDDIR)/man\r
+ else\r
+       @echo "Fatal: build dependency fail."\r
+       @false\r
+diff --git a/doc/prerst2man.py b/doc/prerst2man.py\r
+deleted file mode 100644\r
+index 7d78e9b..0000000\r
+--- a/doc/prerst2man.py\r
++++ /dev/null\r
+@@ -1,66 +0,0 @@\r
+-import sys\r
+-from datetime import date\r
+-from os.path import dirname, isdir\r
+-from os import makedirs, system\r
+-import re\r
+-\r
+-rst2man = sys.argv[1]\r
+-sourcedir = sys.argv[2]\r
+-outdir = sys.argv[3]\r
+-\r
+-sys.path.insert(0, sourcedir)\r
+-import conf\r
+-\r
+-\r
+-if not isdir(outdir):\r
+-    makedirs(outdir, 0o755)\r
+-\r
+-\r
+-def header(file, startdocname, command, description, authors, section):\r
+-    file.write("""\r
+-{0:s}\r
+-{1:s}\r
+-{2:s}\r
+-\r
+-:Date:   {3:s}\r
+-:Version: {4:s}\r
+-:Manual section: {5:d}\r
+-:Manual group: {6:s}\r
+-\r
+-""".format(\r
+-'-' * len(description),\r
+-description,\r
+-'-' * len(description),\r
+-date.today().isoformat(), conf.release, section, conf.project))\r
+-\r
+-blankre = re.compile("^\s*$")\r
+-for page in conf.man_pages:\r
+-    outdirname = outdir + '/' + dirname(page[0])\r
+-    if not isdir(outdirname):\r
+-        makedirs(outdirname, 0o755)\r
+-    filename = outdir + '/' + page[0] + '.rst'\r
+-    outfile = open(filename, 'w')\r
+-    infile = open(sourcedir + '/' + page[0] + '.rst', 'r')\r
+-\r
+-    # this is a crude hack. We look for the first blank line, and\r
+-    # insert the rst2man header there.\r
+-    #\r
+-    # XXX consider really parsing input\r
+-\r
+-    count = 0\r
+-    lines = infile.readlines()\r
+-    for line in lines:\r
+-        outfile.write(line)\r
+-        if (blankre.match(line)):\r
+-            break\r
+-        count = count + 1\r
+-\r
+-    del lines[0:count + 1]\r
+-\r
+-    header(outfile, *page)\r
+-\r
+-    outfile.write("".join(lines))\r
+-    outfile.close()\r
+-\r
+-    system('set -x; {0} {1} {2}/{3}.{4}'\r
+-           .format(rst2man, filename, outdir, page[0], page[4]))\r
+diff --git a/doc/rst-man2any.py b/doc/rst-man2any.py\r
+new file mode 100755\r
+index 0000000..52a4f9e\r
+--- /dev/null\r
++++ b/doc/rst-man2any.py\r
+@@ -0,0 +1,105 @@\r
++#!/usr/bin/python\r
++\r
++import argparse\r
++import datetime\r
++import os\r
++import sys\r
++\r
++\r
++def header(stream, description, authors, section, group, version):\r
++    "Write a man-page's ReST headers to 'stream'."\r
++    if len(authors) != 1:\r
++        raise NotImplementedError(\r
++            'cannot handle {count} authors ({authors}'.format(\r
++                count=len(authors), authors=authors))\r
++    stream.write('\n'.join([\r
++        '{description_rule}',\r
++        '{description}',\r
++        '{description_rule}',\r
++        '',\r
++        ':Author: {author}',\r
++        ':Date: {date}',\r
++        ':Version: {version}',\r
++        ':Manual section: {section:d}',\r
++        ':Manual group: {group}',\r
++        '',\r
++        '']).format(\r
++            description=description,\r
++            description_rule='-' * len(description),\r
++            author=authors[0],\r
++            date=datetime.date.today().isoformat(),\r
++            version=version,\r
++            section=section,\r
++            group=group))\r
++\r
++\r
++def convert(startdocname, description, authors, section,\r
++            group, version, source_dir, output_dir, command, extension=None):\r
++    """Convert the ReST source at path to the target format in 'output_dir'.\r
++\r
++    The initial arguments (startdocname through section) follow\r
++    Sphinx's man_pages option [1].\r
++\r
++    [1]: http://sphinx-doc.org/config.html#confval-man_pages\r
++    """\r
++    source_path = os.path.join(source_dir, startdocname) + '.rst'\r
++    output_base = os.path.join(output_dir, startdocname)\r
++    temp_path = output_base + '.rst'\r
++    if extension:\r
++        ext = extension\r
++    else:\r
++        ext = str(section)\r
++    output_path = '{base}.{ext}'.format(base=output_base, ext=ext)\r
++    dirname = os.path.dirname(output_path)\r
++    if not os.path.isdir(dirname):\r
++        os.makedirs(dirname, 0o755)\r
++    with open(source_path, 'r') as source:\r
++        with open(temp_path, 'w') as temp:\r
++            # this is a crude hack. We look for the first blank line, and\r
++            # insert the man-page headers there.\r
++            #\r
++            # XXX consider really parsing input\r
++            need_header = True\r
++            for line in source:\r
++                temp.write(line)\r
++                if need_header and not line.strip():\r
++                    header(\r
++                        stream=temp, description=description, authors=authors,\r
++                        section=section, group=group, version=version)\r
++                    need_header = False\r
++    os.system('set -x; {command} {source_path} {output_path}'.format(\r
++        command=command,\r
++        source_path=temp_path,\r
++        output_path=output_path))\r
++\r
++\r
++if __name__ == '__main__':\r
++    import argparse\r
++\r
++    parser = argparse.ArgumentParser(\r
++        description='Convert reStructuredText man pages to other formats.')\r
++    parser.add_argument(\r
++        '-i', '--input', default='_build',\r
++        help='Input directory')\r
++    parser.add_argument(\r
++        '-o', '--output', default='.',\r
++        help='Output directory')\r
++    parser.add_argument(\r
++        '-c', '--converter', default='rst2man',\r
++        help='ReST converter for your target output')\r
++    parser.add_argument(\r
++        '-e', '--extension',\r
++        help='Optional extension for the output files')\r
++\r
++    args = parser.parse_args()\r
++\r
++    sys.path.insert(0, args.input)\r
++    import conf\r
++\r
++    for startdocname, name, description, authors, section in conf.man_pages:\r
++        convert(\r
++            startdocname=startdocname, description=description,\r
++            authors=authors, section=section, group=conf.project,\r
++            version=conf.release, source_dir=args.input,\r
++            output_dir=args.output, command=args.converter,\r
++            extension=args.extension)\r
+-- \r
+1.9.1.353.gc66d89d\r
+\r