From f16dae964a7a529803f044022d957a472d2bf070 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Fri, 12 Sep 2008 13:08:52 +0000 Subject: [PATCH] Restructure LaTeX file template: add new "latex_elements" config value allowing to customize each part of what is written to the tex file. --- doc/config.rst | 94 ++++++++++++++++++++--- sphinx/config.py | 10 ++- sphinx/highlighting.py | 22 ++++-- sphinx/latexwriter.py | 146 +++++++++++++++++++++--------------- sphinx/texinputs/howto.cls | 16 +--- sphinx/texinputs/manual.cls | 17 +---- sphinx/texinputs/sphinx.sty | 15 ++-- 7 files changed, 200 insertions(+), 120 deletions(-) diff --git a/doc/config.rst b/doc/config.rst index 176da06ef..5e85fcb1d 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -422,14 +422,6 @@ Options for LaTeX output These options influence LaTeX output. -.. confval:: latex_paper_size - - The output paper size (``'letter'`` or ``'a4'``). Default is ``'letter'``. - -.. confval:: latex_font_size - - The font size ('10pt', '11pt' or '12pt'). Default is ``'10pt'``. - .. confval:: latex_documents This value determines how to group the document tree into LaTeX source files. @@ -472,13 +464,91 @@ These options influence LaTeX output. A list of document names to append as an appendix to all manuals. -.. confval:: latex_preamble +.. confval:: latex_use_modindex - Additional LaTeX markup for the preamble. + If true, add a module index to LaTeX documents. Default is ``True``. + +.. confval:: latex_elements + + .. versionadded:: 0.5 + + A dictionary that contains LaTeX snippets that override those Sphinx usually + puts into the generated ``.tex`` files. Keep in mind that backslashes must be doubled in Python string literals to avoid interpretation as escape sequences. -.. confval:: latex_use_modindex + * Keys that you may want to override include: + + ``'papersize'`` + Paper size option of the document class (``'a4paper'`` or + ``'letterpaper'``), default ``'letterpaper'``. + ``'pointsize'`` + Point size option of the document class (``'10pt'``, ``'11pt'`` or + ``'12pt'``), default ``'10pt'``. + ``'babel'`` + "babel" package inclusion, default ``'\\usepackage{babel}'``. + ``'fontpkg'`` + Font package inclusion, default ``'\\usepackage{times}'`` (which uses + Times and Helvetica). You can set this to ``''`` to use the Computer + Modern fonts. + ``'fncychap'`` + Inclusion of the "fncychap" package (which makes fancy chapter titles), + default ``'\\usepackage[Bjarne]{fncychap}'`` for English documentation, + ``'\\usepackage[Sonny]{fncychap}'`` for internationalized docs (because + the "Bjarne" style uses numbers spelled out in English). Other + "fncychap" styles you can try include "Lenny", "Glenn", "Conny" and + "Rejne". You can also set this to ``''`` to disable fncychap. + ``'preamble'`` + Additional preamble content, default empty. + + * Keys that don't need be overridden unless in special cases are: + + ``'inputenc'`` + "inputenc" package inclusion, default ``'\\usepackage[utf8]{inputenc}'``. + ``'fontenc'`` + "fontenc" package inclusion, default ``'\\usepackage[T1]{fontenc}'``. + ``'maketitle'`` + "maketitle" call, default ``'\\maketitle'``. Override if you want to + generate a differently-styled title page. + ``'tableofcontents'`` + "tableofcontents" call, default ``'\\tableofcontents'``. Override if you + want to generate a different table of contents or put content between the + title page and the TOC. + + * Keys that are set by other options and therefore should not be overridden are: + + ``'docclass'`` + ``'classoptions'`` + ``'title'`` + ``'date'`` + ``'release'`` + ``'author'`` + ``'logo'`` + ``'releasename'`` + ``'makeindex'`` + ``'makemodindex'`` + ``'shorthandoff'`` + ``'printmodindex'`` + ``'printindex'`` + +.. confval:: latex_preamble - If true, add a module index to LaTeX documents. Default is ``True``. + Additional LaTeX markup for the preamble. + + .. deprecated:: 0.5 + Use the ``'preamble'`` key in the :confval:`latex_elements` value. + +.. confval:: latex_paper_size + + The output paper size (``'letter'`` or ``'a4'``). Default is ``'letter'``. + + .. deprecated:: 0.5 + Use the ``'papersize'`` key in the :confval:`latex_elements` value. + +.. confval:: latex_font_size + + The font size ('10pt', '11pt' or '12pt'). Default is ``'10pt'``. + + .. deprecated:: 0.5 + Use the ``'pointsize'`` key in the :confval:`latex_elements` value. diff --git a/sphinx/config.py b/sphinx/config.py index ac896424f..6be9c3af0 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -75,14 +75,18 @@ class Config(object): htmlhelp_basename = ('pydoc', False), # LaTeX options - latex_paper_size = ('letter', False), - latex_font_size = ('10pt', False), latex_documents = ([], False), latex_logo = (None, False), - latex_preamble = ('', False), latex_appendices = ([], False), latex_use_parts = (False, False), latex_use_modindex = (True, False), + # paper_size and font_size are still separate values + # so that you can give them easily on the command line + latex_paper_size = ('letter', False), + latex_font_size = ('10pt', False), + latex_elements = ({}, False), + # now deprecated - use latex_elements + latex_preamble = ('', False), ) def __init__(self, dirname, filename, overrides): diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py index 3ac19407d..b494b0725 100644 --- a/sphinx/highlighting.py +++ b/sphinx/highlighting.py @@ -61,15 +61,15 @@ else: _lexer.add_filter('raiseonerror') -escape_hl_chars = {ord(u'@'): u'@PYat[]', - ord(u'['): u'@PYlb[]', - ord(u']'): u'@PYrb[]'} +escape_hl_chars = {ord(u'@'): u'@PYGZat[]', + ord(u'['): u'@PYGZlb[]', + ord(u']'): u'@PYGZrb[]'} # used if Pygments is not available _LATEX_STYLES = r''' -\newcommand\PYat{@} -\newcommand\PYlb{[} -\newcommand\PYrb{]} +\newcommand\PYGZat{@} +\newcommand\PYGZlb{[} +\newcommand\PYGZrb{]} ''' @@ -180,5 +180,11 @@ class PygmentsBridge(object): return _LATEX_STYLES # no HTML styles needed return '' - fmter = (self.dest == 'html' and self.hfmter or self.lfmter)[0] - return fmter.get_style_defs() + if self.dest == 'html': + return self.hfmter[0].get_style_defs() + else: + styledefs = self.lfmter[0].get_style_defs() + # workaround for Pygments < 0.12 + if styledefs.startswith('\\newcommand\\at{@}'): + styledefs += _LATEX_STYLES + return styledefs diff --git a/sphinx/latexwriter.py b/sphinx/latexwriter.py index 86f6a256a..a35f89894 100644 --- a/sphinx/latexwriter.py +++ b/sphinx/latexwriter.py @@ -14,8 +14,8 @@ import re import sys -import time from os import path +from time import strftime from docutils import nodes, writers from docutils.writers.latex2e import Babel @@ -28,40 +28,38 @@ from sphinx.util.smartypants import educateQuotesLatex HEADER = r'''%% Generated by Sphinx. \documentclass[%(papersize)s,%(pointsize)s%(classoptions)s]{%(docclass)s} -\usepackage[utf8]{inputenc} -\usepackage[T1]{fontenc} -\usepackage{babel} +%(inputenc)s +%(fontenc)s +%(babel)s +%(fontpkg)s +%(fncychap)s +%(preamble)s + \title{%(title)s} \date{%(date)s} \release{%(release)s} \author{%(author)s} \newcommand{\sphinxlogo}{%(logo)s} \renewcommand{\releasename}{%(releasename)s} -%(preamble)s -\makeindex +%(makeindex)s +%(makemodindex)s ''' BEGIN_DOC = r''' \begin{document} %(shorthandoff)s -\maketitle -\tableofcontents +%(maketitle)s +%(tableofcontents)s ''' FOOTER = r''' -\printindex +\renewcommand{\indexname}{%(modindexname)s} +%(printmodindex)s +\renewcommand{\indexname}{%(indexname)s} +%(printindex)s \end{document} ''' -GRAPHICX = r''' -%% Check if we are compiling under latex or pdflatex. -\ifx\pdftexversion\undefined - \usepackage{graphicx} -\else - \usepackage[pdftex]{graphicx} -\fi -''' - class LaTeXWriter(writers.Writer): @@ -118,38 +116,73 @@ class LaTeXTranslator(nodes.NodeVisitor): ignore_missing_images = False + default_elements = { + 'docclass': 'manual', + 'papersize': 'letterpaper', + 'pointsize': '10pt', + 'classoptions': '', + 'inputenc': '\\usepackage[utf8]{inputenc}', + 'fontenc': '\\usepackage[T1]{fontenc}', + 'babel': '\\usepackage{babel}', + 'fontpkg': '\\usepackage{times}', + 'fncychap': '\\usepackage[Bjarne]{fncychap}', + 'preamble': '', + 'title': '', + 'date': '', + 'release': '', + 'author': '', + 'logo': '', + 'releasename': 'Release', + 'makeindex': '\\makeindex', + 'makemodindex': '\\makemodindex', + 'shorthandoff': '', + 'maketitle': '\\maketitle', + 'tableofcontents': '\\tableofcontents', + 'printmodindex': '\\printmodindex', + 'printindex': '\\printindex', + } + def __init__(self, document, builder): nodes.NodeVisitor.__init__(self, document) self.builder = builder self.body = [] - docclass = document.settings.docclass - paper = builder.config.latex_paper_size + 'paper' - if paper == 'paper': # e.g. command line "-D latex_paper_size=" - paper = 'letterpaper' - date = time.strftime(builder.config.today_fmt or _('%B %d, %Y')) - logo = (builder.config.latex_logo and - '\\includegraphics{%s}\\par' % path.basename(builder.config.latex_logo) - or '') - self.options = {'docclass': docclass, - 'papersize': paper, - 'pointsize': builder.config.latex_font_size, - 'preamble': builder.config.latex_preamble, - 'modindex': builder.config.latex_use_modindex, - 'author': document.settings.author, - 'docname': document.settings.docname, - # if empty, the title is set to the first section title - 'title': document.settings.title, - 'release': builder.config.release, - 'releasename': _('Release'), - 'logo': logo, - 'date': date, - 'classoptions': ',english', - 'shorthandoff': '', - } + + # sort out some elements + papersize = builder.config.latex_paper_size + 'paper' + if papersize == 'paper': # e.g. command line "-D latex_paper_size=" + papersize = 'letterpaper' + + self.elements = self.default_elements.copy() + self.elements.update({ + 'docclass': document.settings.docclass, + 'papersize': papersize, + 'pointsize': builder.config.latex_font_size, + # if empty, the title is set to the first section title + 'title': document.settings.title, + 'date': strftime(builder.config.today_fmt or _('%B %d, %Y')), + 'release': builder.config.release, + 'author': document.settings.author, + 'releasename': _('Release'), + 'preamble': builder.config.latex_preamble, + 'modindexname': _('Module Index'), + 'indexname': _('Index'), + }) + if builder.config.latex_logo: + self.elements['logo'] = '\\includegraphics{%s}\\par' % \ + path.basename(builder.config.latex_logo) if builder.config.language: babel = ExtBabel(builder.config.language) - self.options['classoptions'] += ',' + babel.get_language() - self.shorthandoff = babel.get_shorthandoff() + self.elements['classoptions'] += ',' + babel.get_language() + self.elements['shorthandoff'] = babel.get_shorthandoff() + self.elements['fncychap'] = '\\usepackage[Sonny]{fncychap}' + else: + self.elements['classoptions'] += ',english' + if not builder.config.latex_use_modindex: + self.elements['makemodindex'] = '' + self.elements['printmodindex'] = '' + # allow the user to override them all + self.elements.update(builder.config.latex_elements) + self.highlighter = highlighting.PygmentsBridge( 'latex', builder.config.pygments_style) self.context = [] @@ -160,7 +193,7 @@ class LaTeXTranslator(nodes.NodeVisitor): self.highlightlang = builder.config.highlight_language self.highlightlinenothreshold = sys.maxint self.written_ids = set() - if docclass == 'manual': + if self.elements['docclass'] == 'manual': if builder.config.latex_use_parts: self.top_sectionlevel = 0 else: @@ -175,25 +208,15 @@ class LaTeXTranslator(nodes.NodeVisitor): self.first_document = 1 self.this_is_the_title = 1 self.literal_whitespace = 0 - self.need_graphicx = 0 def astext(self): - return (HEADER % self.options) + \ - (self.options['modindex'] and '\\makemodindex\n' or '') + \ - self.highlighter.get_stylesheet() + \ - (self.need_graphicx and GRAPHICX or '') + \ - '\n\n' + \ - u''.join(self.body) + \ - (self.options['modindex'] and - ('\\renewcommand{\\indexname}{%s}' % _('Module Index') + - '\\printmodindex' + - '\\renewcommand{\\indexname}{%s}\n' % _('Index')) or '') + \ - (FOOTER % self.options) + return (HEADER % self.elements + self.highlighter.get_stylesheet() + + u''.join(self.body) + FOOTER % self.elements) def visit_document(self, node): if self.first_document == 1: # the first document is all the regular content ... - self.body.append(BEGIN_DOC) + self.body.append(BEGIN_DOC % self.elements) self.first_document = 0 elif self.first_document == 0: # ... and all others are the appendices @@ -288,8 +311,8 @@ class LaTeXTranslator(nodes.NodeVisitor): elif self.this_is_the_title: if len(node.children) != 1 and not isinstance(node.children[0], nodes.Text): self.builder.warn('document title is not a single Text node') - if not self.options['title']: - self.options['title'] = node.astext() + if not self.elements['title']: + self.elements['title'] = node.astext() self.this_is_the_title = 0 raise nodes.SkipNode elif isinstance(node.parent, nodes.section): @@ -649,7 +672,6 @@ class LaTeXTranslator(nodes.NodeVisitor): return res def visit_image(self, node): - self.need_graphicx = 1 attrs = node.attributes pre = [] # in reverse order post = [] @@ -825,7 +847,7 @@ class LaTeXTranslator(nodes.NodeVisitor): if self.in_title or not uri: self.context.append('') elif uri.startswith('mailto:') or uri.startswith('http:') or \ - uri.startswith('ftp:'): + uri.startswith('https:') or uri.startswith('ftp:'): self.body.append('\\href{%s}{' % self.encode(uri)) self.context.append('}') elif uri.startswith('#'): diff --git a/sphinx/texinputs/howto.cls b/sphinx/texinputs/howto.cls index 43cbc31e7..c58bff4c3 100644 --- a/sphinx/texinputs/howto.cls +++ b/sphinx/texinputs/howto.cls @@ -3,7 +3,7 @@ % \NeedsTeXFormat{LaTeX2e}[1995/12/01] -\ProvidesClass{howto}[2008/05/01 Document class (Sphinx HOWTO)] +\ProvidesClass{howto}[2008/09/12 Document class (Sphinx HOWTO)] \RequirePackage{fancybox} @@ -12,18 +12,11 @@ \ProcessOptions\relax \LoadClass[twoside]{article} - % Set some sane defaults for section numbering depth and TOC depth. You can % reset these counters in your preamble. % \setcounter{secnumdepth}{2} - -% The "fancyhdr" package makes nicer page footers reasonable to implement, and -% is used to put the chapter and section information in the footers. -% -\RequirePackage{fancyhdr} - % This gives us all the Python-specific markup that we really want. This should % come last. Do not change this. % @@ -34,15 +27,12 @@ % \RequirePackage{makeidx} -% Need to do one of these.... -\newcommand{\py@doHorizontalRule}{\rule{\textwidth}{1pt}} - % Change the title page to look a bit better, and fit in with the fncychap % ``Bjarne'' style a bit better. % \renewcommand{\maketitle}{ - \py@doHorizontalRule + \rule{\textwidth}{1pt} \ifpdf \begingroup % This \def is required to deal with multi-line authors; it @@ -78,7 +68,7 @@ \parskip = 0mm \py@OldTableofcontents \endgroup - \py@doHorizontalRule + \rule{\textwidth}{1pt} \vspace{12pt} } diff --git a/sphinx/texinputs/manual.cls b/sphinx/texinputs/manual.cls index 021f4f3a0..8c99228ae 100644 --- a/sphinx/texinputs/manual.cls +++ b/sphinx/texinputs/manual.cls @@ -3,7 +3,7 @@ % \NeedsTeXFormat{LaTeX2e}[1995/12/01] -\ProvidesClass{manual}[2008/05/01 Document class (Sphinx manual)] +\ProvidesClass{manual}[2008/09/12 Document class (Sphinx manual)] \RequirePackage{fancybox} @@ -12,25 +12,12 @@ \ProcessOptions\relax \LoadClass[twoside,openright]{report} - % Set some sane defaults for section numbering depth and TOC depth. You can % reset these counters in your preamble. % \setcounter{secnumdepth}{2} \setcounter{tocdepth}{1} - -% The "fancyhdr" package makes nicer page footers reasonable to implement, and -% is used to put the chapter and section information in the footers. -% -\RequirePackage{fancyhdr} - -% The "fncychap" package is used to get the nice chapter headers. -% -\RequirePackage[Bjarne]{fncychap} -% Do horizontal rules it this way to match: -\newcommand{\py@doHorizontalRule}{\mghrulefill{\RW}} - % This gives us all the Sphinx-specific markup that we really want. This should % come last. Do not change this. % @@ -49,7 +36,7 @@ \begin{titlepage}% \let\footnotesize\small \let\footnoterule\relax - \py@doHorizontalRule% + \rule{\textwidth}{1pt}% \ifpdf \begingroup % This \def is required to deal with multi-line authors; it diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 4f776ca19..cec477ca3 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -9,8 +9,8 @@ \ProvidesPackage{sphinx}[2008/05/01 LaTeX package (Sphinx markup)] \RequirePackage{textcomp} -\RequirePackage{times} \RequirePackage{fancyvrb} +\RequirePackage{fancyhdr} \RequirePackage{titlesec} \RequirePackage{tabulary} \RequirePackage{amsmath} % for \text @@ -36,18 +36,19 @@ \RequirePackage{framed} -\ifx\pdftexversion\undefined - \RequirePackage{graphicx} -\else - \RequirePackage[pdftex]{graphicx} -\fi - % Uncomment these two lines to ignore the paper size and make the page % size more like a typical published manual. %\renewcommand{\paperheight}{9in} %\renewcommand{\paperwidth}{8.5in} % typical squarish manual %\renewcommand{\paperwidth}{7in} % O'Reilly ``Programmming Python'' +% For graphicx, check if we are compiling under latex or pdflatex. +\ifx\pdftexversion\undefined + \usepackage{graphicx} +\else + \usepackage[pdftex]{graphicx} +\fi + % for PDF output, use maximal compression \newif\ifpdf\pdffalse \ifx\pdfoutput\undefined\else\ifcase\pdfoutput