--- /dev/null
+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