8

I have some code listings (using the listings environment or the lstinline macro from the listings package) where I'd like to link all the identifiers defined in the present document to their definition. I only care about PDF output via pdflatex.

I'm satisfied with the indexing infrastructure that I already have, where I manually indicate where each identifier is defined, and I can manually link an occurrence of an identifier to its definition. For example (vastly simplified for the purpose of this question) I can write \DefinedHere{foo} to create an index entry and a hyperref target, and \LinkDefinition{foo} to typeset foo and link it to the hyperref target.

My question here is how to make the listings infrastructure invoke \LinkDefinition automatically (or some similar macro with a different syntax), either for all identifiers or for a predefined list of identifiers, so that each identifier is hyperlinked to the manually-defined target in the PDF.

MWE:

\documentclass{article}
\usepackage{hyperref}
\usepackage{alltt}
\usepackage{listings}
\lstset{basicstyle=\ttfamily,columns=flexible}

\newcommand{\DefinedHere}[1]{\hypertarget{def.#1}{}}
\newcommand{\LinkToDefinition}[1]{\hyperlink{def.#1}{#1}}

\begin{document}

\section{Yin}

\begin{alltt}
def \LinkToDefinition{yin} = not \LinkToDefinition{yang}
\end{alltt}
\begin{lstlisting}
def yin = not yang
\end{lstlisting}

\newpage
\section{Yang}
\hypertarget{def.yang}{}
\begin{alltt}
def \LinkToDefinition{yang} = not \LinkToDefinition{yin}
\end{alltt}
\begin{lstlisting}
def yang = not yin
\end{lstlisting}

\end{document}

The alltt sections illustrate the manual use of \LinkToDefinition. (If I was doing this manually, I might not index the occurrence in the definition itself, i.e. I wouldn't have def yin link to the definition of yin, but I don't care if that happens: .) I want to use listings package and achieve the same links as in the alltt examples, automatically, without having to add annotations to each listing.

I thought of adding something like this in my preamble:

\lstset{emph={yin,yang},emphstyle={\LinkToDefinition}}

but the emphstyle key expects a state-changing command, it doesn't take the word as an argument. Or

\lstset{index={yin,yang},indexstyle={\LinkToDefinition}}

but that typesets the identifier twice, because the argument of the indexstyle isn't expected to typeset the word. I can change \LinkToDefinition to typeset nothing, but that creates a zero-width link, instead of linking the word. Is there a way to combine the two?

7

You can use literate inside your lstset:

\lstset{basicstyle=\ttfamily,columns=flexible,
        literate={yin}{\LinkToDefinition{yin}}{4}{yang}{\LinkToDefinition{yang}}{5},
        }

MWE:

\documentclass{article}
\usepackage{hyperref}
\usepackage{listings}
\lstset{basicstyle=\ttfamily,columns=flexible,
        literate={yin}{\LinkToDefinition{yin}}{4}{yang}{\LinkToDefinition{yang}}{5},
        }

\newcommand{\DefinedHere}[1]{\hypertarget{def.#1}{}}
\newcommand{\LinkToDefinition}[1]{\hyperlink{def.#1}{#1}}

\begin{document}

\section{Yin}
\DefinedHere{yin}
\begin{lstlisting}
def yin = not yang
\end{lstlisting}

\newpage
\section{Yang}
\DefinedHere{yang}
\begin{lstlisting}
def yang = not yin
\end{lstlisting}

\end{document} 

Output:

enter image description here

  • @Gilles Sorry, I've misunderstood the question. Is it now OK? – karlkoeller Jan 9 '15 at 20:02
  • Aha, now that looks good. Is there a way to pass the text as the argument to the key value, so that I don't have to define a literate class for each identifier? Not a big hurdle, I suppose, it shouldn't matter with modern memory sizes. – Gilles Jan 9 '15 at 20:22
  • @Gilles Not that I know.... – karlkoeller Jan 9 '15 at 20:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.