Refactor: Add captioned_literal_block node to simplify LaTeX writer

This commit is contained in:
Takeshi KOMIYA 2018-05-23 22:50:46 +09:00
parent 51962c715c
commit 489d86d470
6 changed files with 95 additions and 56 deletions

View File

@ -64,9 +64,13 @@ Deprecated
* ``sphinx.writers.latex.Table.caption_footnotetexts`` is deprecated
* ``sphinx.writers.latex.Table.header_footnotetexts`` is deprecated
* ``sphinx.writers.latex.LaTeXWriter.footnotestack`` is deprecated
* ``sphinx.writers.latex.LaTeXWriter.in_container_literal_block`` is deprecated
* ``sphinx.writers.latex.LaTeXWriter.next_hyperlink_ids`` is deprecated
* ``sphinx.writers.latex.LaTeXWriter.restrict_footnote()`` is deprecated
* ``sphinx.writers.latex.LaTeXWriter.unrestrict_footnote()`` is deprecated
* ``LaTeXWriter.bibitems`` is deprecated
* ``sphinx.writers.latex.LaTeXWriter.push_hyperlink_ids()`` is deprecated
* ``sphinx.writers.latex.LaTeXWriter.pop_hyperlink_ids()`` is deprecated
* ``sphinx.writers.latex.LaTeXWriter.bibitems`` is deprecated
* ``BuildEnvironment.load()`` is deprecated
* ``BuildEnvironment.loads()`` is deprecated
* ``BuildEnvironment.frompickle()`` is deprecated

View File

@ -171,6 +171,16 @@ The following is a list of deprecated interface.
- 3.0
- N/A
* - ``sphinx.writers.latex.LaTeXWriter.in_container_literal_block``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.latex.LaTeXWriter.next_hyperlink_ids``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.latex.LaTeXWriter.restrict_footnote()``
- 1.8
- 3.0
@ -181,6 +191,16 @@ The following is a list of deprecated interface.
- 3.0
- N/A
* - ``sphinx.writers.latex.LaTeXWriter.push_hyperlink_ids()``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.latex.LaTeXWriter.pop_hyperlink_ids()``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.latex.LaTeXWriter.bibitems``
- 1.8
- 3.0

View File

@ -20,7 +20,8 @@ from sphinx import package_dir, addnodes, highlighting
from sphinx.builders import Builder
from sphinx.builders.latex.transforms import (
BibliographyTransform, CitationReferenceTransform, MathReferenceTransform,
FootnoteDocnameUpdater, LaTeXFootnoteTransform, ShowUrlsTransform
FootnoteDocnameUpdater, LaTeXFootnoteTransform, LiteralBlockTransform,
ShowUrlsTransform,
)
from sphinx.config import string_classes, ENUM
from sphinx.environment import NoUri
@ -223,7 +224,8 @@ class LaTeXBuilder(Builder):
transformer.set_environment(self.env)
transformer.add_transforms([BibliographyTransform,
ShowUrlsTransform,
LaTeXFootnoteTransform])
LaTeXFootnoteTransform,
LiteralBlockTransform])
transformer.apply_transforms()
def finish(self):

View File

@ -12,6 +12,11 @@
from docutils import nodes
class captioned_literal_block(nodes.container):
"""A node for a container of literal_block having a caption."""
pass
class footnotemark(nodes.Inline, nodes.Referential, nodes.TextElement):
"""A node represents ``\footnotemark``."""
pass

View File

@ -13,7 +13,7 @@ from docutils import nodes
from sphinx import addnodes
from sphinx.builders.latex.nodes import (
footnotemark, footnotetext, math_reference, thebibliography
captioned_literal_block, footnotemark, footnotetext, math_reference, thebibliography
)
from sphinx.transforms import SphinxTransform
@ -566,3 +566,18 @@ class MathReferenceTransform(SphinxTransform):
if docname:
refnode = math_reference('', docname=docname, target=node['reftarget'])
node.replace_self(refnode)
class LiteralBlockTransform(SphinxTransform):
"""Replace container nodes for literal_block by captioned_literal_block."""
default_priority = 400
def apply(self):
# type: () -> None
if self.app.builder.name != 'latex':
return
for node in self.document.traverse(nodes.container):
if node['literal_block'] is True:
newnode = captioned_literal_block('', *node.children, **node.attributes)
node.replace_self(newnode)

View File

@ -25,7 +25,7 @@ from six import itervalues, text_type
from sphinx import addnodes
from sphinx import highlighting
from sphinx.builders.latex.nodes import footnotetext
from sphinx.builders.latex.nodes import captioned_literal_block, footnotetext
from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.errors import SphinxError
from sphinx.locale import admonitionlabels, _, __
@ -58,6 +58,7 @@ HYPERLINK_SUPPORT_NODES = (
nodes.literal_block,
nodes.table,
nodes.section,
captioned_literal_block,
)
DEFAULT_SETTINGS = {
@ -465,7 +466,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.in_production_list = 0
self.in_footnote = 0
self.in_caption = 0
self.in_container_literal_block = 0
self.in_term = 0
self.needs_linetrimming = 0
self.in_minipage = 0
@ -691,7 +691,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.pending_footnotes = [] # type: List[nodes.footnote_reference]
self.curfilestack = [] # type: List[unicode]
self.handled_abbrs = set() # type: Set[unicode]
self.next_hyperlink_ids = {} # type: Dict[unicode, Set[unicode]]
self.next_section_ids = set() # type: Set[unicode]
def pushbody(self, newbody):
@ -705,15 +704,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body = self.bodystack.pop()
return body
def push_hyperlink_ids(self, figtype, ids):
# type: (unicode, Set[unicode]) -> None
hyperlink_ids = self.next_hyperlink_ids.setdefault(figtype, set())
hyperlink_ids.update(ids)
def pop_hyperlink_ids(self, figtype):
# type: (unicode) -> Set[unicode]
return self.next_hyperlink_ids.pop(figtype, set())
def check_latex_elements(self):
# type: () -> None
for key in self.builder.config.latex_elements:
@ -1790,7 +1780,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_caption(self, node):
# type: (nodes.Node) -> None
self.in_caption += 1
if self.in_container_literal_block:
if isinstance(node.parent, captioned_literal_block):
self.body.append('\\sphinxSetupCaptionForVerbatim{')
elif self.in_minipage and isinstance(node.parent, nodes.figure):
self.body.append('\\captionof{figure}{')
@ -1883,35 +1873,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append(self.hypertarget(id, anchor=anchor))
# skip if visitor for next node supports hyperlink
domain = self.builder.env.get_domain('std')
next_node = node.next_node(ascend=True)
if isinstance(next_node, HYPERLINK_SUPPORT_NODES):
return
elif domain.get_enumerable_node_type(next_node) and domain.get_numfig_title(next_node):
return
# postpone the labels until after the sectioning command
parindex = node.parent.index(node)
try:
try:
next = node.parent[parindex + 1]
except IndexError:
# last node in parent, look at next after parent
# (for section of equal level) if it exists
if node.parent.parent is not None:
next = node.parent.parent[
node.parent.parent.index(node.parent)]
else:
raise
domain = self.builder.env.get_domain('std')
figtype = domain.get_enumerable_node_type(next)
if figtype and domain.get_numfig_title(next):
ids = set()
# labels for figures go in the figure body, not before
if node.get('refid'):
ids.add(node['refid'])
ids.update(node['ids'])
self.push_hyperlink_ids(figtype, ids)
return
except IndexError:
pass
if 'refuri' in node:
return
if node.get('refid'):
@ -2221,6 +2189,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
# the \ignorespaces in particular for after table header use
self.body.append('%\n\\end{footnotetext}\\ignorespaces ')
def visit_captioned_literal_block(self, node):
# type: (nodes.Node) -> None
pass
def depart_captioned_literal_block(self, node):
# type: (nodes.Node) -> None
pass
def visit_literal_block(self, node):
# type: (nodes.Node) -> None
if node.rawsource != node.astext():
@ -2229,9 +2205,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('\\begin{sphinxalltt}\n')
else:
labels = self.hypertarget_to(node)
# LaTeX code will insert \phantomsection prior to \label
if isinstance(node.parent, captioned_literal_block):
labels += self.hypertarget_to(node.parent)
if labels and not self.in_footnote:
self.body.append('\n\\def\\sphinxLiteralBlockLabel{' + labels + '}')
code = node.astext()
lang = self.hlsettingstack[-1][0]
linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1
@ -2458,22 +2436,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_container(self, node):
# type: (nodes.Node) -> None
if node.get('literal_block'):
self.in_container_literal_block += 1
ids = '' # type: unicode
for id in self.pop_hyperlink_ids('code-block'):
ids += self.hypertarget(id, anchor=False)
if node['ids']:
# suppress with anchor=False \phantomsection insertion
ids += self.hypertarget(node['ids'][0], anchor=False)
# define label for use in caption.
if ids:
self.body.append('\n\\def\\sphinxLiteralBlockLabel{' + ids + '}\n')
pass
def depart_container(self, node):
# type: (nodes.Node) -> None
if node.get('literal_block'):
self.in_container_literal_block -= 1
pass
def visit_decoration(self, node):
# type: (nodes.Node) -> None
@ -2603,6 +2570,32 @@ class LaTeXTranslator(nodes.NodeVisitor):
RemovedInSphinx30Warning)
return []
@property
def in_container_literal_block(self):
# type: () -> int
warnings.warn('LaTeXTranslator.in_container_literal_block is deprecated.',
RemovedInSphinx30Warning)
return 0
@property
def next_hyperlink_ids(self):
# type: () -> Dict
warnings.warn('LaTeXTranslator.next_hyperlink_ids is deprecated.',
RemovedInSphinx30Warning)
return {}
def push_hyperlink_ids(self, figtype, ids):
# type: (unicode, Set[unicode]) -> None
warnings.warn('LaTeXTranslator.push_hyperlink_ids() is deprecated.',
RemovedInSphinx30Warning)
pass
def pop_hyperlink_ids(self, figtype):
# type: (unicode) -> Set[unicode]
warnings.warn('LaTeXTranslator.pop_hyperlink_ids() is deprecated.',
RemovedInSphinx30Warning)
return set()
# Import old modules here for compatibility
# They should be imported after `LaTeXTranslator` to avoid recursive import.