Rev 4008: (Colin D Bennett) Generate PDF version of the User Guide. in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Sat Feb 14 16:54:11 GMT 2009
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 4008
revision-id: pqm at pqm.ubuntu.com-20090214165408-vlwzj9x1qax0i1b0
parent: pqm at pqm.ubuntu.com-20090213220525-f4o6y76g5mjtxb7k
parent: colin at gibibit.com-20090212172102-0t7xufywds9l1g33
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Sat 2009-02-14 16:54:08 +0000
message:
(Colin D Bennett) Generate PDF version of the User Guide.
added:
tools/prepare_for_latex.py prepare_for_latex.py-20090212165735-79tn1t4dhnxyz7m9-1
tools/rst2pdf.py rst2pdf.py-20090212165735-79tn1t4dhnxyz7m9-2
modified:
.bzrignore bzrignore-20050311232317-81f7b71efa2db11a
Makefile Makefile-20050805140406-d96e3498bb61c5bb
------------------------------------------------------------
revno: 4000.4.5
revision-id: colin at gibibit.com-20090212172102-0t7xufywds9l1g33
parent: colin at gibibit.com-20090212171833-s8k62ifqy4uf4cxc
committer: Colin D Bennett <colin at gibibit.com>
branch nick: pdf-docs
timestamp: Thu 2009-02-12 09:21:02 -0800
message:
Strip trailing whitespace.
modified:
Makefile Makefile-20050805140406-d96e3498bb61c5bb
tools/prepare_for_latex.py prepare_for_latex.py-20090212165735-79tn1t4dhnxyz7m9-1
------------------------------------------------------------
revno: 4000.4.4
revision-id: colin at gibibit.com-20090212171833-s8k62ifqy4uf4cxc
parent: colin at gibibit.com-20090212171141-bq8gllubhwyfgr52
committer: Colin D Bennett <colin at gibibit.com>
branch nick: pdf-docs
timestamp: Thu 2009-02-12 09:18:33 -0800
message:
Put PDF cleanup in clean-docs target; added note on Inkscape requirement.
modified:
Makefile Makefile-20050805140406-d96e3498bb61c5bb
------------------------------------------------------------
revno: 4000.4.3
revision-id: colin at gibibit.com-20090212171141-bq8gllubhwyfgr52
parent: colin at gibibit.com-20090212170752-roshfon2ckj8atyg
committer: Colin D Bennett <colin at gibibit.com>
branch nick: pdf-docs
timestamp: Thu 2009-02-12 09:11:41 -0800
message:
Ignore all generated PDFs, not just the A4 size document.
modified:
.bzrignore bzrignore-20050311232317-81f7b71efa2db11a
------------------------------------------------------------
revno: 4000.4.2
revision-id: colin at gibibit.com-20090212170752-roshfon2ckj8atyg
parent: colin at gibibit.com-20090212165739-02xv63odccfmxomw
committer: Colin D Bennett <colin at gibibit.com>
branch nick: pdf-docs
timestamp: Thu 2009-02-12 09:07:52 -0800
message:
Made PDF documents a separate target for people who don't have LaTeX installed.
modified:
Makefile Makefile-20050805140406-d96e3498bb61c5bb
------------------------------------------------------------
revno: 4000.4.1
revision-id: colin at gibibit.com-20090212165739-02xv63odccfmxomw
parent: pqm at pqm.ubuntu.com-20090211011240-gv0zdxmwomt3ndtn
committer: Colin D Bennett <colin at gibibit.com>
branch nick: pdf-docs
timestamp: Thu 2009-02-12 08:57:39 -0800
message:
Generate PDF version of the User Guide.
added:
tools/prepare_for_latex.py prepare_for_latex.py-20090212165735-79tn1t4dhnxyz7m9-1
tools/rst2pdf.py rst2pdf.py-20090212165735-79tn1t4dhnxyz7m9-2
modified:
.bzrignore bzrignore-20050311232317-81f7b71efa2db11a
Makefile Makefile-20050805140406-d96e3498bb61c5bb
=== modified file '.bzrignore'
--- a/.bzrignore 2008-12-11 02:18:59 +0000
+++ b/.bzrignore 2009-02-12 17:11:41 +0000
@@ -53,3 +53,5 @@
bzrlib/_*.pyd
# generated help topics
doc/en/user-reference/*.txt
+./doc/en/user-guide/latex_prepared
+./doc/en/user-guide/*.pdf
=== modified file 'Makefile'
--- a/Makefile 2008-12-15 04:37:10 +0000
+++ b/Makefile 2009-02-12 17:21:02 +0000
@@ -111,6 +111,26 @@
doc/en/user-guide/index.html: $(wildcard $(addsuffix /*.txt, doc/en/user-guide))
$(rst2html) --stylesheet=../../default.css doc/en/user-guide/index.txt $@
+# Set the paper size for PDF files.
+# Options: 'a4' (ISO A4 size), 'letter' (US Letter size)
+PAPERSIZE = a4
+PDF_DOCS := doc/en/user-guide/user-guide.$(PAPERSIZE).pdf
+
+# Copy and modify the RST sources, and convert SVG images to PDF
+# files for use a images in the LaTeX-generated PDF.
+# Then generate the PDF output from the modified RST sources.
+doc/en/user-guide/user-guide.$(PAPERSIZE).pdf: $(wildcard $(addsuffix /*.txt, doc/en/user-guide))
+ mkdir -p doc/en/user-guide/latex_prepared
+ $(PYTHON) tools/prepare_for_latex.py \
+ --out-dir=doc/en/user-guide/latex_prepared \
+ --in-dir=doc/en/user-guide
+ cd doc/en/user-guide/latex_prepared && \
+ $(PYTHON) ../../../../tools/rst2pdf.py \
+ --documentoptions=10pt,$(PAPERSIZE)paper \
+ --input-encoding=UTF-8:strict --output-encoding=UTF-8:strict \
+ --strict --title="Bazaar User Guide" \
+ index.txt ../user-guide.$(PAPERSIZE).pdf
+
doc/developers/%.html: doc/developers/%.txt
$(rst2html) --stylesheet=../default.css $< $@
@@ -163,10 +183,15 @@
html-docs: docs
$(PYTHON) tools/win32/ostools.py copytree $(WEB_DOCS) $(HTMLDIR)
+# Produce PDF documents. Requires pdfLaTeX, rubber, and Inkscape.
+pdf-docs: $(PDF_DOCS)
+
# clean produced docs
clean-docs:
$(PYTHON) tools/win32/ostools.py remove $(ALL_DOCS) \
- $(HTMLDIR) $(derived_txt_files)
+ $(HTMLDIR) $(derived_txt_files)
+ rm -f doc/en/user-guide/*.pdf
+ rm -rf doc/en/user-guide/latex_prepared
### Windows Support ###
=== added file 'tools/prepare_for_latex.py'
--- a/tools/prepare_for_latex.py 1970-01-01 00:00:00 +0000
+++ b/tools/prepare_for_latex.py 2009-02-12 17:21:02 +0000
@@ -0,0 +1,173 @@
+#!/usr/bin/python
+#
+# Modify reStructuredText 'image' directives by adding a percentage 'width'
+# attribute so that the images are scaled to fit on the page when the document
+# is renderd to LaTeX, and add a center alignment.
+#
+# Also convert references to PNG images to use PDF files generated from SVG
+# files if available.
+#
+# Without the explicit size specification, the images are ridiculously huge and
+# most extend far off the right side of the page.
+#
+# Copyright (C) 2009 Colin D Bennett
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import os
+import re
+import shutil
+import sys
+from sys import argv
+from subprocess import call
+
+verbose = False
+
+IMAGE_DIRECTIVE_PATTERN = re.compile(ur'^..\s+image::\s+(.*)\s+$')
+DIRECTIVE_ELEMENT_PATTERN = re.compile(ur'^\s+:[^:]+:\s+')
+
+class Converter(object):
+ def __init__(self, srcdir, destdir):
+ self.srcdir = srcdir
+ self.destdir = destdir
+
+ # Process .txt files in sourcedir, generating output in destdir.
+ def process_files(self):
+ for filename in os.listdir(self.srcdir):
+ # Process all text files in the current directory.
+ if filename.endswith('.txt'):
+ inpath = os.path.join(self.srcdir, filename)
+ outpath = os.path.join(self.destdir, filename)
+ self._process_file(inpath, outpath)
+
+ def _process_file(self, inpath, outpath):
+ infile = open(inpath, 'r')
+ outfile = open(outpath, 'w')
+ foundimg = False
+ for line in infile:
+ if foundimg and DIRECTIVE_ELEMENT_PATTERN.match(line) is None:
+ if verbose:
+ print('Fixing image directive')
+ # The preceding image directive has no elements.
+ outfile.write(' :width: 85%\n')
+ outfile.write(' :align: center\n')
+ foundimg = False
+
+ image_fixer = ImageFixer(self.srcdir, self.destdir)
+ image_fixer_lambda = lambda match: image_fixer.substitute_pdf_image(match)
+ line = IMAGE_DIRECTIVE_PATTERN.sub(image_fixer_lambda, line)
+ directive_match = IMAGE_DIRECTIVE_PATTERN.match(line)
+ if directive_match is not None:
+ image_src = directive_match.group(1)
+ if verbose:
+ print('Image ' + image_src + ' in ' + filename
+ + ': ' + line.strip())
+
+ foundimg = True
+ outfile.write(line)
+ outfile.close()
+ infile.close()
+
+class ImageFixer(object):
+ def __init__(self, srcdir, destdir):
+ self.srcdir = srcdir
+ self.destdir = destdir
+
+ def substitute_pdf_image(self, match):
+ prefix = match.string[:match.start(1)]
+ newname = self.convert_image_to_pdf(match.group(1))
+ suffix = match.string[match.end(1):]
+ return prefix + newname + suffix
+
+ def replace_extension(self, path, newext):
+ if path.endswith(newext):
+ raise Exception("File '" + path + "' already has extension '"
+ + newext +"'")
+ dot = path.rfind('.')
+ if dot == -1:
+ return path + newext
+ else:
+ return path[:dot] + newext
+
+ # Possibly use an SVG alternative to a PNG image, converting the SVG image
+ # to a PDF first. Whether or not a conversion is made, the image to use is
+ # written to the destination directory and the path to use in the RST #
+ # source is returned.
+ def convert_image_to_pdf(self, filename):
+ # Make the directory structure for the image in the destination dir.
+ image_dirname = os.path.dirname(filename)
+ if image_dirname:
+ image_dirpath = os.path.join(self.destdir, image_dirname)
+ if not os.path.exists(image_dirpath):
+ os.mkdir(image_dirpath)
+
+ # Decide how to handle this image.
+ if filename.endswith('.png'):
+ # See if there is a vector alternative.
+ svgfile = self.replace_extension(filename, '.svg')
+ svgpath = os.path.join(self.srcdir, svgfile)
+ if os.path.exists(svgpath):
+ if verbose:
+ print('Using SVG alternative to PNG')
+ # Convert SVG to PDF with Inkscape.
+ pdffile = self.replace_extension(filename, '.pdf')
+ pdfpath = os.path.join(self.destdir, pdffile)
+ if call(['/usr/bin/inkscape',
+ '--export-pdf=' + pdfpath, svgpath]) != 0:
+ raise Exception("Conversion to pdf failed")
+ return pdffile
+
+ # No conversion, just copy the file.
+ srcpath = os.path.join(self.srcdir, filename)
+ destpath = os.path.join(self.destdir, filename)
+ shutil.copyfile(srcpath, destpath)
+ return filename
+
+if __name__ == '__main__':
+ IN_DIR_OPT = '--in-dir='
+ OUT_DIR_OPT = '--out-dir='
+ srcdir = None
+ destdir = None
+
+ if len(argv) < 2:
+ print('Usage: ' + argv[0] + ' ' + IN_DIR_OPT + 'INDIR '
+ + OUT_DIR_OPT + 'OUTDIR')
+ print
+ print('This will convert all .txt files in INDIR into file in OUTDIR')
+ print('while adjusting the use of images and possibly converting SVG')
+ print('images to PDF files so LaTeX can include them.')
+ sys.exit(1)
+
+ for arg in argv[1:]:
+ if arg == '-v' or arg == '--verbose':
+ verbose = True
+ elif arg.startswith(IN_DIR_OPT):
+ srcdir = arg[len(IN_DIR_OPT):]
+ elif arg.startswith(OUT_DIR_OPT):
+ destdir = arg[len(OUT_DIR_OPT):]
+ else:
+ print('Invalid argument ' + arg)
+ sys.exit(1)
+
+ if srcdir is None or destdir is None:
+ print('Please specify the ' + IN_DIR_OPT + ' and '
+ + OUT_DIR_OPT + ' options.')
+ sys.exit(1)
+
+ if not os.path.exists(destdir):
+ os.mkdir(destdir)
+ Converter(srcdir, destdir).process_files()
+
+# vim: set ts=4 sw=4 et:
=== added file 'tools/rst2pdf.py'
--- a/tools/rst2pdf.py 1970-01-01 00:00:00 +0000
+++ b/tools/rst2pdf.py 2009-02-12 16:57:39 +0000
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+# -*- coding: utf8 -*-
+# $Id: rst2pdf.py 5560 2008-05-20 13:00:31Z milde $
+
+# rst2pdf.py
+# ==========
+# ::
+
+"""
+A front end to the Docutils Publisher, producing PDF.
+
+Produces a latex file with the "latex" writer and converts
+it to PDF with the "rubber" building system for LaTeX documents.
+"""
+
+# ``rst2pdf.py`` is a PDF front-end for docutils that is compatible
+# with the ``rst2*.py`` front ends of the docutils_ suite.
+# It enables the generation of PDF documents from a reStructuredText source in
+# one step.
+#
+# It is implemented as a combination of docutils' ``rst2latex.py``
+# by David Goodger and rubber_ by Emmanuel Beffara.
+#
+# Copyright: © 2008 Günter Milde
+# Licensed under the `Apache License, Version 2.0`_
+# Provided WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND
+#
+# Changelog
+# ---------
+#
+# ===== ========== =======================================================
+# 0.1 2008-05-20 first attempt
+# ===== ========== =======================================================
+#
+# ::
+
+_version = 0.1
+
+
+# Imports
+# =======
+# ::
+
+#from pprint import pprint # for debugging
+import os
+
+# Docutils::
+
+try:
+ import locale
+ locale.setlocale(locale.LC_ALL, '')
+except:
+ pass
+
+from docutils.core import default_usage, default_description, Publisher
+
+# Rubber (rubber is not installed in the PYTHONPATH)::
+
+import sys
+sys.path.append("/usr/share/rubber")
+
+try:
+ import rubber.cmdline
+ import rubber.cmd_pipe
+except ImportError:
+ print "Cannot find the rubber modules, rubber not installed correctly."
+ sys.exit(1)
+
+# Generate the latex file
+# =======================
+#
+# We need to replace the <destination> by a intermediate latex file path.
+# The most reliable way to get the value of <destination> is to
+# call the Publisher "by hand", and query its settings.
+#
+# Modeled on the publish_cmdline() function of docutils.core
+#
+# Default values::
+
+reader=None
+reader_name='standalone'
+parser=None
+parser_name='restructuredtext'
+writer=None
+writer_name='pseudoxml'
+settings=None
+settings_spec=None
+settings_overrides=None
+config_section=None
+enable_exit_status=1
+argv=None
+usage=default_usage
+description=default_description
+
+# Argument values given to publish_cmdline() in rst2latex.py::
+
+description = ('Generates PDF documents from standalone reStructuredText '
+ 'sources using the "latex" Writer and the "rubber" '
+ 'building system for LaTeX documents. ' + default_description)
+writer_name = 'latex'
+
+# Set up the publisher::
+
+pub = Publisher(reader, parser, writer, settings=settings)
+pub.set_components(reader_name, parser_name, writer_name)
+
+# Parse the command line args
+# (Publisher.publish does this in a try statement)::
+
+pub.process_command_line(argv, usage, description, settings_spec,
+ config_section, **(settings_overrides or {}))
+# pprint(pub.settings.__dict__)
+
+# Get source and destination path::
+
+source = pub.settings._source
+destination = pub.settings._destination
+# print source, destination
+
+# Generate names for the temporary files and set ``destination`` to temporary
+# latex file:
+#
+# make_name() from rubber.cmd_pipe checks that no existing file is
+# overwritten. If we are going to support rubbers ``--inplace`` and ``--into``
+# options, the chdir() must occure before this point to have the check in the
+# right directory. ::
+
+tmppath = rubber.cmd_pipe.make_name()
+texpath = tmppath + ".tex"
+pdfpath = tmppath + ".pdf"
+
+pub.settings._destination = texpath
+
+# Now do the rst -> latex conversion::
+
+pub.publish(argv, usage, description, settings_spec, settings_overrides,
+ config_section=config_section, enable_exit_status=enable_exit_status)
+
+
+# Generating the PDF document with rubber
+# =======================================
+#
+#
+# rubber_ has no documentet API for programmatic use. We simualate a command
+# line call and pass command line arguments (see man: rubber-pipe) in an array::
+
+rubber_argv = ["--pdf", # use pdflatex to produce PDF
+ "--short", # Display LaTeXâs error messages one error per line.
+ texpath
+ ]
+
+# Get a TeX processing class instance and do the latex->pdf conversion::
+
+tex_processor = rubber.cmdline.Main()
+tex_processor(rubber_argv)
+
+# Rename output to _destination or print to stdout::
+
+if destination is None:
+ pdffile = file(pdfpath)
+ print pdffile.read()
+ pdffile.close()
+else:
+ os.rename(pdfpath, destination)
+
+# Clean up (remove intermediate files)
+#
+# ::
+
+tex_processor(["--clean"] + rubber_argv)
+os.remove(texpath)
+
+
+# .. References
+#
+# .. _docutils: http://docutils.sourceforge.net/
+# .. _rubber: http://www.pps.jussieu.fr/~beffara/soft/rubber/
+# .. _Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
+#
More information about the bazaar-commits
mailing list