Enable pdf hyperlinks to named literal-blocks without caption.

This is tango between latex.py and sphinx.sty to handle PDF hyperlinks
to literal-blocks (both code-block and literalinclude) either with name
or caption (then numref can be used) or both.

	modified:   sphinx/texinputs/sphinx.sty
	modified:   sphinx/writers/latex.py

This test file is now back to original.

	modified:   tests/test_directive_code.py
This commit is contained in:
jfbu
2016-04-07 11:27:33 +02:00
parent 238a3346d9
commit 261ff1a9d2
3 changed files with 35 additions and 11 deletions

View File

@@ -186,8 +186,11 @@
\newcommand*\SphinxVerbatimTitle {}
\newcommand*\SphinxSetupCaptionForVerbatim [2]
{%
\def\SphinxVerbatimTitle{\captionof{#1}{#2}\smallskip }%
\needspace{\literalblockneedspace}\vspace{\literalblockcaptiontopvspace}%
\def\SphinxVerbatimTitle
{\captionof{#1}{\SphinxLiteralBlockLabel #2}\smallskip }%
}
\newcommand*\SphinxLiteralBlockLabel {}
% \SphinxCustomFBox is copied from framed.sty's \CustomFBox, but
% #1=title/caption is to be set _above_ the top rule, not _below_
@@ -246,6 +249,16 @@
\bgroup\parskip\z@skip
\smallskip
% use customized framed environment
% first, check if has caption
\ifx\SphinxVerbatimTitle\empty
% no caption. Require space if at bottom of page
\needspace{\literalblockwithoutcaptionneedspace}%
% if there is a label insert hypertarget.
\ifx\SphinxLiteralBlockLabel\empty\else
\phantomsection\SphinxLiteralBlockLabel
\fi
\fi
% non empty \SphinxVerbatimTitle has label inside if there is one.
\let\SphinxFrameTitle\SphinxVerbatimTitle
\global\Sphinx@myfirstframedpasstrue
% The list environement is needed to control perfectly the vertical
@@ -625,5 +638,6 @@
\RequirePackage{needspace}
% if the left page space is less than \literalblockneedsapce, insert page-break
\newcommand{\literalblockneedspace}{5\baselineskip}
\newcommand{\literalblockwithoutcaptionneedspace}{1.5\baselineskip}
% margin before the caption of literal-block
\newcommand{\literalblockcaptiontopvspace}{0.5\baselineskip}

View File

@@ -1443,10 +1443,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_caption(self, node):
self.in_caption += 1
if self.in_container_literal_block:
self.body.append('\\needspace{\\literalblockneedspace}')
self.body.append('\\vspace{\\literalblockcaptiontopvspace}\n')
self.body.append('\\SphinxSetupCaptionForVerbatim{literal-block}{'
'' + self.context.pop())
self.body.append('\\SphinxSetupCaptionForVerbatim{literal-block}{')
elif self.in_minipage and isinstance(node.parent, nodes.figure):
self.body.append('\\captionof{figure}{')
else:
@@ -1801,6 +1798,16 @@ class LaTeXTranslator(nodes.NodeVisitor):
# most probably a parsed-literal block -- don't highlight
self.body.append('\\begin{alltt}\n')
else:
ids = ''
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, or directly if none exist.
# LaTeX code will add the \phantomsection in latter case.
if ids:
self.body.append('\n\\def\\SphinxLiteralBlockLabel{' + ids + '}')
code = node.astext()
lang = self.hlsettingstack[-1][0]
linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1
@@ -1834,6 +1841,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
hlcode = hlcode.rstrip()[:-14] # strip \end{Verbatim}
self.body.append('\n' + hlcode + '\\end{%sVerbatim}\n' %
(self.table and 'Original' or ''))
if ids:
self.body.append('\\let\\SphinxLiteralBlockLabel\empty\n')
raise nodes.SkipNode
def depart_literal_block(self, node):
@@ -1992,15 +2001,16 @@ class LaTeXTranslator(nodes.NodeVisitor):
for id in self.pop_hyperlink_ids('code-block'):
ids += self.hypertarget(id, anchor=False)
if node['ids']:
# suppress with anchor=False \phantomsection generation
# suppress with anchor=False \phantomsection insertion
ids += self.hypertarget(node['ids'][0], anchor=False)
self.body.append('\n')
# context.pop will be done in visit_caption
self.context.append(ids)
# define label for use in caption.
if ids:
self.body.append('\n\\def\\SphinxLiteralBlockLabel{' + ids + '}\n')
def depart_container(self, node):
if node.get('literal_block'):
self.in_container_literal_block -= 1
self.body.append('\\let\\SphinxLiteralBlockLabel\\empty\n')
def visit_decoration(self, node):
pass

View File

@@ -64,7 +64,7 @@ def test_code_block_caption_html(app, status, warning):
def test_code_block_caption_latex(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
caption = '\\SphinxSetupCaptionForVerbatim{literal-block}{\label{caption:caption-test-rb}caption \\emph{test} rb}'
caption = '\\SphinxSetupCaptionForVerbatim{literal-block}{caption \\emph{test} rb}'
assert caption in latex
@@ -229,7 +229,7 @@ def test_literalinclude_caption_html(app, status, warning):
def test_literalinclude_caption_latex(app, status, warning):
app.builder.build('index')
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
caption = '\\SphinxSetupCaptionForVerbatim{literal-block}{\label{caption:caption-test-py}caption \\textbf{test} py}'
caption = '\\SphinxSetupCaptionForVerbatim{literal-block}{caption \\textbf{test} py}'
assert caption in latex