Get rid of the non-extensible Python-specific description environments in sphinx.sty.

This commit is contained in:
Georg Brandl 2010-01-17 23:25:14 +01:00
parent 52698469ac
commit 54f35838ee
2 changed files with 76 additions and 348 deletions

View File

@ -6,7 +6,7 @@
%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesPackage{sphinx}[2008/05/01 LaTeX package (Sphinx markup)]
\ProvidesPackage{sphinx}[2010/01/15 LaTeX package (Sphinx markup)]
\RequirePackage{textcomp}
\RequirePackage{fancyhdr}
@ -193,7 +193,9 @@
\index{#4!#1 #2 #3}
}
% support for the module index
% Support for the module index.
%
\newif\ifpy@UseModuleIndex
\py@UseModuleIndexfalse
@ -207,7 +209,7 @@
\@input@{mod\jobname.ind}
}
% Add the defining entry for a module
% Add the defining entry for a module.
\newcommand{\py@modindex}[2]{%
\renewcommand{\py@thismodule}{#1}
\ifpy@UseModuleIndex%
@ -220,7 +222,6 @@
}
% "Current" keys
\newcommand{\py@thisclass}{}
\newcommand{\py@thismodule}{}
\newcommand{\py@thismodulekey}{}
\newcommand{\py@thismoduletype}{}
@ -238,7 +239,7 @@
%\label{module-\py@thismodulekey}
}
% Record module platforms for the Module Index
% Record module platforms for the Module Index.
\newif\ifpy@ModPlatformFileIsOpen \py@ModPlatformFileIsOpenfalse
\long\def\py@writeModPlatformFile#1{%
\protected@write\py@ModPlatformFile%
@ -270,7 +271,6 @@
% Reset "current" objects.
\newcommand{\resetcurrentobjects}{
\renewcommand{\py@thisclass}{}
\renewcommand{\py@thismodule}{}
\renewcommand{\py@thismodulekey}{}
\renewcommand{\py@thismoduletype}{}
@ -287,14 +287,7 @@
\titleformat{\paragraph}{\large\py@HeaderFamily}%
{\py@TitleColor}{0em}{\py@TitleColor}{\py@NormalColor}
% Now for a lot of semantically-loaded environments that do a ton of magical
% things to get the right formatting and index entries for the stuff in
% Python modules and C API.
% {fulllineitems} is used in one place in libregex.tex, but is really for
% internal use in this file.
% {fulllineitems} is the main environment for object descriptions.
%
\newcommand{\py@itemnewline}[1]{%
\@tempdima\linewidth%
@ -308,223 +301,22 @@
\let\makelabel=\py@itemnewline}
}{\end{list}}
% \optional is mostly for use in the arguments parameters to the various
% {*desc} environments defined below, but may be used elsewhere. Known to
% be used in the debugger chapter.
%
% Typical usage:
%
% \begin{funcdesc}{myfunc}{reqparm\optional{, optparm}}
% ^^^ ^^^
% No space here No space here
%
% When a function has multiple optional parameters, \optional should be
% nested, not chained. This is right:
%
% \begin{funcdesc}{myfunc}{\optional{parm1\optional{, parm2}}}
%
\let\py@badkey=\@undefined
% \optional is used for ``[, arg]``, i.e. desc_optional nodes.
\newcommand{\optional}[1]{%
{\textnormal{\Large[}}{#1}\hspace{0.5mm}{\textnormal{\Large]}}}
% This can be used when a function or method accepts an varying number
% of arguments, such as by using the *args syntax in the parameter list.
\newcommand{\py@moreargs}{...}
% This can be used when you don't want to document the parameters to a
% function or method, but simply state that it's an alias for
% something else.
\newcommand{\py@unspecified}{...}
\newcommand{\py@varvars}[1]{{%
{\let\unspecified=\py@unspecified%
\let\moreargs=\py@moreargs%
\emph{#1}}}}
\newlength{\py@argswidth}
\newcommand{\py@sigparams}[1]{%
\parbox[t]{\py@argswidth}{\py@varvars{#1}\code{)}}}
\newcommand{\py@sigline}[2]{%
\parbox[t]{\py@argswidth}{#1\code{)}}}
\newcommand{\pysigline}[1]{\item[#1]\nopagebreak}
\newcommand{\pysiglinewithargs}[2]{%
\settowidth{\py@argswidth}{#1\code{(}}%
\addtolength{\py@argswidth}{-2\py@argswidth}%
\addtolength{\py@argswidth}{\textwidth}%
\item[#1\code{(}\py@sigparams{#2}]}
% C functions ------------------------------------------------------------
% \begin{cfuncdesc}[refcount]{type}{name}{arglist}
% Note that the [refcount] slot should only be filled in by
% tools/anno-api.py; it pulls the value from the refcounts database.
\newcommand{\cfuncline}[3]{
\py@sigline{\code{#1 \bfcode{#2}}}{#3}%
}
\newenvironment{cfuncdesc}[3]{
\begin{fulllineitems}
\cfuncline{#1}{#2}{#3}
}{\end{fulllineitems}}
% C variables ------------------------------------------------------------
% \begin{cvardesc}{type}{name}
\newenvironment{cvardesc}[2]{
\begin{fulllineitems}
\item[\code{#1 \bfcode{#2}}]
}{\end{fulllineitems}}
% C data types -----------------------------------------------------------
% \begin{ctypedesc}[index name]{typedef name}
\newenvironment{ctypedesc}[2][\py@badkey]{
\begin{fulllineitems}
\item[\bfcode{#2}]
}{\end{fulllineitems}}
% C type fields ----------------------------------------------------------
% \begin{cmemberdesc}{container type}{ctype}{membername}
\newcommand{\cmemberline}[3]{
\item[\code{#2 \bfcode{#3}}]
}
\newenvironment{cmemberdesc}[3]{
\begin{fulllineitems}
\cmemberline{#1}{#2}{#3}
}{\end{fulllineitems}}
% Funky macros -----------------------------------------------------------
% \begin{csimplemacrodesc}{name}
% -- "simple" because it has no args; NOT for constant definitions!
\newenvironment{csimplemacrodesc}[1]{
\begin{fulllineitems}
\item[\bfcode{#1}]
}{\end{fulllineitems}}
% simple functions (not methods) -----------------------------------------
% \begin{funcdesc}{name}{args}
\newcommand{\funcline}[2]{%
\py@sigline{\bfcode{#1}}{#2}}
\newenvironment{funcdesc}[2]{
\begin{fulllineitems}
\funcline{#1}{#2}
}{\end{fulllineitems}}
% classes ----------------------------------------------------------------
% \begin{classdesc}{name}{constructor args}
\newcommand{\classline}[2]{
\py@sigline{\strong{class }\bfcode{#1}}{#2}}
\newenvironment{classdesc}[2]{
% Using \renewcommand doesn't work for this, for unknown reasons:
\global\def\py@thisclass{#1}
\begin{fulllineitems}
\classline{#1}{#2}
}{\end{fulllineitems}}
% \begin{excclassdesc}{name}{constructor args}
% but indexes as an exception
\newenvironment{excclassdesc}[2]{
% Using \renewcommand doesn't work for this, for unknown reasons:
\global\def\py@thisclass{#1}
\begin{fulllineitems}
\py@sigline{\strong{exception }\bfcode{#1}}{#2}%
}{\end{fulllineitems}}
% There is no corresponding {excclassdesc*} environment. To describe
% a class exception without parameters, use the {excdesc} environment.
\let\py@classbadkey=\@undefined
% object method ----------------------------------------------------------
% \begin{methoddesc}[classname]{methodname}{args}
\newcommand{\methodline}[3][\@undefined]{
\py@sigline{\bfcode{#2}}{#3}}
\newenvironment{methoddesc}[3][\@undefined]{
\begin{fulllineitems}
\ifx\@undefined#1\relax
\methodline{#2}{#3}
\else
\def\py@thisclass{#1}
\methodline{#2}{#3}
\fi
}{\end{fulllineitems}}
% static method ----------------------------------------------------------
% \begin{staticmethoddesc}[classname]{methodname}{args}
\newcommand{\staticmethodline}[3][\@undefined]{
\py@sigline{static \bfcode{#2}}{#3}}
\newenvironment{staticmethoddesc}[3][\@undefined]{
\begin{fulllineitems}
\ifx\@undefined#1\relax
\staticmethodline{#2}{#3}
\else
\def\py@thisclass{#1}
\staticmethodline{#2}{#3}
\fi
}{\end{fulllineitems}}
% class method ----------------------------------------------------------
% \begin{classmethoddesc}[classname]{methodname}{args}
\newcommand{\classmethodline}[3][\@undefined]{
\py@sigline{class \bfcode{#2}}{#3}}
\newenvironment{classmethoddesc}[3][\@undefined]{
\begin{fulllineitems}
\ifx\@undefined#1\relax
\classmethodline{#2}{#3}
\else
\def\py@thisclass{#1}
\classmethodline{#2}{#3}
\fi
}{\end{fulllineitems}}
% object data attribute --------------------------------------------------
% \begin{memberdesc}[classname]{membername}
\newcommand{\memberline}[2][\py@classbadkey]{%
\ifx\@undefined#1\relax
\item[\bfcode{#2}]
\else
\item[\bfcode{#2}]
\fi
}
\newenvironment{memberdesc}[2][\py@classbadkey]{
\begin{fulllineitems}
\ifx\@undefined#1\relax
\memberline{#2}
\else
\def\py@thisclass{#1}
\memberline{#2}
\fi
}{\end{fulllineitems}}
% For exceptions: --------------------------------------------------------
% \begin{excdesc}{name}
% -- for constructor information, use excclassdesc instead
\newenvironment{excdesc}[1]{
\begin{fulllineitems}
\item[\strong{exception }\bfcode{#1}]
}{\end{fulllineitems}}
% Module data or constants: ----------------------------------------------
% \begin{datadesc}{name}
\newcommand{\dataline}[1]{%
\item[\bfcode{#1}]\nopagebreak}
\newenvironment{datadesc}[1]{
\begin{fulllineitems}
\dataline{#1}
}{\end{fulllineitems}}
% bytecode instruction ---------------------------------------------------
% \begin{opcodedesc}{name}{var}
% -- {var} may be {}
\newenvironment{opcodedesc}[2]{
\begin{fulllineitems}
\item[\bfcode{#1}\quad\emph{#2}]
}{\end{fulllineitems}}
% generic description ----------------------------------------------------
\newcommand{\descline}[1]{%
\item[\bfcode{#1}]\nopagebreak%
}
\newenvironment{describe}[1]{
\begin{fulllineitems}
\descline{#1}
}{\end{fulllineitems}}
% This version is being checked in for the historical record; it shows
% how I've managed to get some aspects of this to work. It will not
% be used in practice, so a subsequent revision will change things
@ -535,7 +327,8 @@
\newcommand{\grammartoken}[1]{\texttt{#1}}
\newenvironment{productionlist}[1][\py@badkey]{
\def\optional##1{{\Large[}##1{\Large]}}
\def\production##1##2{\code{##1}&::=&\code{##2}\\}
\def\production##1##2{\hypertarget{grammar-token-##1}{}%
\code{##1}&::=&\code{##2}\\}
\def\productioncont##1{& &\code{##1}\\}
\def\token##1{##1}
\let\grammartoken=\token

View File

@ -121,14 +121,6 @@ class Table(object):
self.longtable = False
class Desc(object):
def __init__(self, node):
self.env = LaTeXTranslator.desc_map.get(node['objtype'], 'describe')
self.type = self.cls = self.name = self.params = \
self.annotation = self.returns = ''
self.count = 0
class LaTeXTranslator(nodes.NodeVisitor):
sectionnames = ["part", "chapter", "section", "subsection",
"subsubsection", "paragraph", "subparagraph"]
@ -248,6 +240,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.literal_whitespace = 0
self.no_contractions = 0
self.compact_list = 0
self.first_param = 0
def astext(self):
return (HEADER % self.elements + self.highlighter.get_stylesheet() +
@ -434,139 +427,76 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_subtitle(self, node):
self.body.append(self.context.pop())
# XXX update this
desc_map = {
'function' : 'funcdesc',
'class': 'classdesc',
'method': 'methoddesc',
'classmethod': 'classmethoddesc',
'staticmethod': 'staticmethoddesc',
'exception': 'excdesc',
'data': 'datadesc',
'attribute': 'memberdesc',
'opcode': 'opcodedesc',
'cfunction': 'cfuncdesc',
'cmember': 'cmemberdesc',
'cmacro': 'csimplemacrodesc',
'ctype': 'ctypedesc',
'cvar': 'cvardesc',
'describe': 'describe',
# and all others are 'describe' too
}
def visit_desc(self, node):
self.descstack.append(Desc(node))
self.body.append('\n\n\\begin{fulllineitems}\n')
def depart_desc(self, node):
d = self.descstack.pop()
self.body.append("\\end{%s}\n" % d.env)
self.body.append('\n\\end{fulllineitems}\n\n')
def visit_desc_signature(self, node):
d = self.descstack[-1]
# reset these for every signature
d.type = d.cls = d.name = d.params = ''
def depart_desc_signature(self, node):
d = self.descstack[-1]
d.cls = d.cls.rstrip('.')
if node.parent['objtype'] != 'describe' and node['ids']:
hyper = '\\hypertarget{%s}{}' % self.idescape(node['ids'][0])
else:
hyper = ''
if d.count == 0:
t1 = "\n\n%s\\begin{%s}" % (hyper, d.env)
self.body.append(hyper)
for child in node:
if isinstance(child, addnodes.desc_parameterlist):
self.body.append(r'\pysiglinewithargs{')
break
else:
t1 = "\n%s\\%sline" % (hyper, d.env[:-4])
d.count += 1
if d.env in ('funcdesc', 'classdesc', 'excclassdesc'):
t2 = "{%s}{%s}" % (d.name, d.params)
elif d.env in ('datadesc', 'excdesc', 'csimplemacrodesc'):
t2 = "{%s}" % (d.name)
elif d.env in ('methoddesc', 'classmethoddesc', 'staticmethoddesc'):
if d.cls:
t2 = "[%s]{%s}{%s}" % (d.cls, d.name, d.params)
else:
t2 = "{%s}{%s}" % (d.name, d.params)
elif d.env == 'memberdesc':
if d.cls:
t2 = "[%s]{%s}" % (d.cls, d.name)
else:
t2 = "{%s}" % d.name
elif d.env == 'cfuncdesc':
if d.cls:
# C++ class names
d.name = '%s::%s' % (d.cls, d.name)
t2 = "{%s}{%s}{%s}" % (d.type, d.name, d.params)
elif d.env == 'cmemberdesc':
try:
type, container = d.type.rsplit(' ', 1)
container = container.rstrip('.')
except ValueError:
container = ''
type = d.type
t2 = "{%s}{%s}{%s}" % (container, type, d.name)
elif d.env == 'cvardesc':
t2 = "{%s}{%s}" % (d.type, d.name)
elif d.env == 'ctypedesc':
t2 = "{%s}" % (d.name)
elif d.env == 'opcodedesc':
t2 = "{%s}{%s}" % (d.name, d.params)
elif d.env == 'describe':
t2 = "{%s}" % d.name
self.body.append(t1 + t2)
def visit_desc_type(self, node):
d = self.descstack[-1]
if d.env == 'describe':
d.name += self.encode(node.astext())
else:
self.descstack[-1].type = self.encode(node.astext().strip())
raise nodes.SkipNode
def visit_desc_returns(self, node):
d = self.descstack[-1]
if d.env == 'describe':
d.name += ' $\\rightarrow$ ' + self.encode(node.astext())
else:
self.descstack[-1].returns = self.encode(node.astext().strip())
raise nodes.SkipNode
def visit_desc_name(self, node):
d = self.descstack[-1]
if d.env == 'describe':
d.name += self.encode(node.astext())
else:
self.descstack[-1].name = self.encode(node.astext().strip())
raise nodes.SkipNode
self.body.append(r'\pysigline{')
def depart_desc_signature(self, node):
self.body.append('}')
def visit_desc_addname(self, node):
d = self.descstack[-1]
if d.env == 'describe':
d.name += self.encode(node.astext())
else:
self.descstack[-1].cls = self.encode(node.astext().strip())
raise nodes.SkipNode
self.body.append(r'\code{')
self.literal_whitespace += 1
def depart_desc_addname(self, node):
self.body.append('}')
self.literal_whitespace -= 1
def visit_desc_type(self, node):
pass
def depart_desc_type(self, node):
pass
def visit_desc_returns(self, node):
self.body.append(r' $\rightarrow$ ')
def depart_desc_returns(self, node):
pass
def visit_desc_name(self, node):
self.body.append(r'\bfcode{')
self.literal_whitespace += 1
def depart_desc_name(self, node):
self.body.append('}')
self.literal_whitespace -= 1
def visit_desc_parameterlist(self, node):
d = self.descstack[-1]
if d.env == 'describe':
d.name += self.encode(node.astext())
self.body.append('}{')
self.first_param = 1
def depart_desc_parameterlist(self, node):
pass
def visit_desc_parameter(self, node):
if not self.first_param:
self.body.append(', ')
else:
self.descstack[-1].params = self.encode(node.astext().strip())
raise nodes.SkipNode
self.first_param = 0
if not node.hasattr('noemph'):
self.body.append(r'\emph{')
def depart_desc_parameter(self, node):
if not node.hasattr('noemph'):
self.body.append('}')
def visit_desc_optional(self, node):
self.body.append(r'\optional{')
def depart_desc_optional(self, node):
self.body.append('}')
def visit_desc_annotation(self, node):
d = self.descstack[-1]
if d.env == 'describe':
d.name += self.encode(node.astext())
else:
self.descstack[-1].annotation = self.encode(node.astext().strip())
raise nodes.SkipNode
def visit_refcount(self, node):
self.body.append("\\emph{")
def depart_refcount(self, node):
self.body.append("}\\\\")
self.body.append(r'\strong{')
def depart_desc_annotation(self, node):
self.body.append('}')
def visit_desc_content(self, node):
if node.children and not isinstance(node.children[0], nodes.paragraph):
@ -575,6 +505,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_desc_content(self, node):
pass
def visit_refcount(self, node):
self.body.append("\\emph{")
def depart_refcount(self, node):
self.body.append("}\\\\")
def visit_seealso(self, node):
self.body.append("\n\n\\strong{%s:}\n\n" % admonitionlabels['seealso'])
def depart_seealso(self, node):
@ -884,7 +819,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
pre.append(align_prepost[is_inline, attrs['align']][0])
post.append(align_prepost[is_inline, attrs['align']][1])
except KeyError:
pass # XXX complain here?
pass
if not is_inline:
pre.append('\n')
post.append('\n')
@ -1194,9 +1129,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
* serif typeface
"""
self.body.append('{\\raggedright{}')
self.literal_whitespace = 1
self.literal_whitespace += 1
def depart_line_block(self, node):
self.literal_whitespace = 0
self.literal_whitespace -= 1
# remove the last \\
del self.body[-1]
self.body.append('}\n')