Estou vendo as seguintes mensagens de erro do pdflatex em um projeto realmente gigantesco:
(see the transcript file for additional information)pdfTeX warning (dest): name
{lstnumber.-14.11} has been referenced but does not exist, replaced by a fixed
one
pdfTeX warning (dest): name{lstnumber.-18.22} has been referenced but does not
exist, replaced by a fixed one
pdfTeX warning (dest): name{lstnumber.-9.40} has been referenced but does not e
xist, replaced by a fixed one
pdfTeX warning (dest): name{lstnumber.-4.3} has been referenced but does not ex
ist, replaced by a fixed one
A parte superior do meu arquivo principal fica assim:
\documentclass[ebook,10pt,oneside,final]{memoir}
\usepackage{microtype}
% support for code listings
\usepackage[final]{listings}
\include{autodedent}
\lstset{
basicstyle=\ttfamily\footnotesize,
numberstyle=\footnotesize,
breaklines=true,
numbers=left,
firstnumber=1,
rangeprefix=//,
includerangemarker=false
}
% support for indexing
\usepackage{makeidx}
\makeindex
% make _ a non-special character
\usepackage{underscore}
% support for cross-references
\usepackage{hyperref}
% \newcommand{\href}[2]{#2}
% fix spacing in \tableofcontents
\renewcommand\partnumberline[1]{#1\hspace{1em}}
% custom commands for use in the text of the book itself
\newcommand{\newterm}[1]{\textit{#1}}
\newcommand{\code}[1]{\mbox{\lstinline[basicstyle=\ttfamily]$#1$}}
\newcommand{\slurl}[1]{\href{https://#1}{\textsl{#1}}}
\newcommand{\codeblock}[2]{\label{foo#1#2}\hspace{1em}\lstinputlisting[linerange=ex#2-dex#2,autodedent]{examples-ch#1.cc}}
\newcommand{\codeblockref}[2]{\pageref{foo#1#2}}
\newcommand{\Csharp}{C\#}
\begin{document}
\frontmatter
\include{preface}
\tableofcontents
\mainmatter
% ...and so on...
Um exemplo do \codeblock
corpo do texto:
Let's write a function to multiply each of the elements
in an array by 2.
\codeblock{1}{1}
Our function \code{double_each_element} works \emph{only} with objects of type
\code{array_of_int}...
E um exemplo de \codeblockref
:
Compare this version of the code to the version on page
\codeblockref{1}{1}.
Infelizmente, se você juntar apenas esses trechos em um arquivo de teste e executá pdflatex test.tex; pdflatex test.tex
-lo, tudo funcionará bem! (Exceto que o hiperlink no número "1" na verdade vai para o índice, não para a página 1.) Mas quando faço a mesma coisa na escala de muitos capítulos, recebo as mensagens de erro vistas lstnumber.-14.11
no topo do essa questão.
Eu descobri que esse lstnumber.-<some number>
é o formato dos rótulos gerados automaticamente pelo listings
pacote, então presumo que seja uma interação ruim entre listings
e hyperref
. Mas o que exatamente está errado e o que posso fazer para consertar?
O que \hspace{1em}
está na minha \codeblock
macro foi minha tentativa ingênua de contornar o bug descritoaqui, caso esse fosse o problema.
Responder1
Aqui está o exemplo de como isso deve ser feito, na minha opinião:
No \codeblock
comando \label
é aplicado antes da \lstinputlisting
macro ser usada, ou seja, antes do listings
contador ter sido aumentado para permitir a referência com \refstepcounter
-- usar \label
antes \refstepcounter
é um erro muito comum e como tal, a informação de referência cruzada escrita por \label
é usada a partir de um potencial \refstepcounter
usado antes , que pode estar em conjunto com um section
contador etc., portanto, as informações estão erradas e as coordenadas da hiperâncora são obtidas de uma instância de âncora mais antiga. Dessa forma, os links apontam para uma posição errada.
Na verdade, \lstinputlisting
tem a label=
opção de especificar o nome do rótulo.
O seguinte é um formulário muito reduzido fornecido por quem não é MWE, mas funciona.
\documentclass[ebook,10pt,oneside,final]{memoir}
\usepackage{microtype}
% support for code listings
\begin{filecontents}{examplehelloworld.c}
#include<stdio.h>
int main(int argc,char **argv)
{
printf("Hello World!\n");
return(0);
}
\end{filecontents}
\usepackage[final]{listings}
%\include{autodedent}
\lstset{
basicstyle=\ttfamily\footnotesize,
numberstyle=\footnotesize,
breaklines=true,
numbers=left,
firstnumber=1,
rangeprefix=//,
includerangemarker=false
}
% support for indexing
\usepackage{makeidx}
\makeindex
% make _ a non-special character
\usepackage{underscore}
% support for cross-references
\usepackage{hyperref}
% \newcommand{\href}[2]{#2}
% fix spacing in \tableofcontents
\renewcommand\partnumberline[1]{#1\hspace{1em}}
% custom commands for use in the text of the book itself
\newcommand{\newterm}[1]{\textit{#1}}
\newcommand{\code}[1]{\mbox{\lstinline[basicstyle=\ttfamily]$#1$}}
\newcommand{\slurl}[1]{\href{https://#1}{\textsl{#1}}}
\newcommand{\codeblock}[2]{\hspace{1em}\lstinputlisting[language={C},label={lst:#1-#2}]{examplehelloworld.c}}
\newcommand{\codeblockref}[2]{\pageref{lst:#1-#2}}
\newcommand{\Csharp}{C\#}
\usepackage{blindtext}
\begin{document}
\frontmatter
%\include{preface}
\tableofcontents
\mainmatter
\blindtext[3]
Reference: \codeblockref{1}{4}
\blindtext[5]
\codeblock{1}{4}
\end{document}
Responder2
No processo de postar esta pergunta, me deparei com a resposta! (Não que eu entendapor quefunciona...)
se você juntar apenas esses trechos em um arquivo de teste e executar
pdflatex test.tex; pdflatex test.tex
- funciona bem! (Exceto que o hiperlink no número "1" na verdade vai para o índice, não para a página 1.)
Quando houve erros, não fiquei surpreso que o hiperref tenha ido para o lugar errado. Com o caso de teste reduzido, porém, fiquei intrigado. Então fui ler sobrequeproblema, e descobri que o que eu queria era \phantomsection
assim:
\newcommand{\codeblock}[2]{\phantomsection\label{lst:#1-#2}\lstinputlisting[linerange=ex#2-dex#2,autodedent]{examples-ch#1.cc}}
\newcommand{\codeblockref}[2]{\pageref{lst:#1-#2}}
Observe que meu culto à carga \hspace{1em}
não é mais necessário (AFAIK); e consegui colocar de volta os caracteres especiais que lst:#1-#2
substituí foo#1#2
ao tentar reduzir o caso de teste.
...E num passe de mágica, de repente meu projeto gigantesco compila perfeitamente! Não há mais mensagens de erro misteriosas. Todos os links de hiperref vão para as páginas corretas e mostram o corpo do texto correto.
Não tenho ideia de por que a omissão \phantomsection
causou tanto estrago, mas depois de colocá-lo, está tudo consertado!