[Tex/LaTex] How to extend fancyref for listings

cross-referencingfancyreflistings

I use a listings environment to format source code such as a JSON file.

\begin{lstlisting}[label={lst:json-example},caption=A JSON example]
{
  "title" : "JSON specification",
  "author" : "Douglas Crockford",
  "mimeType" : "application/json",
  "published" : "July 2006",
  "reference" : "http://tools.ietf.org/html/rfc4627"
}
\end{lstlisting}

To reference the listing from within the text I would like to use fancyref as I use it does a good job for figures, tables, sections and so on. However, I noticed that it does not take care of listings.
From the documentation I managed to figure out how to define a basic extension as you can see in the MWE at the bottom of this question.

As you probably know fancyref adds some magic to floating enviroments such as figures and tables and for chapter, sections and so on. When a reference is located on another page, the refering text changes automatically.

chapter 1 on the following page
Chapter 1 on the previous page
figure 1 on the facing page
Figure 1 on the page before

How can I enhance the above extension to automatically provide those magic references?


Here is a MWE to test the behavior.

\documentclass{scrreprt}

\usepackage{fancyref}
\usepackage{listings}

% ---------------------------------------------------------------
% Listing extension for fancyref using the prefix "lst".
% ---------------------------------------------------------------
\newcommand*{\fancyreflstlabelprefix}{lst}

% Main format
\frefformat{main}{\fancyreflstlabelprefix}{%
\MakeUppercase{\freflstname}\fancyrefdefaultspacing#1#2%
}%
\Frefformat{main}{\fancyreflstlabelprefix}{%
\MakeUppercase{\Freflstname}\fancyrefdefaultspacing#1#2%
}%
\Frefformat{main}{\fancyreflstlabelprefix}{Listing~#1}
\frefformat{main}{\fancyreflstlabelprefix}{listing~#1}

% Vario format
\frefformat{vario}{\fancyreflstlabelprefix}{%
\MakeUppercase{\freflstname}\fancyrefdefaultspacing#1#2%
}%
\Frefformat{vario}{\fancyreflstlabelprefix}{%
\MakeUppercase{\Freflstname}\fancyrefdefaultspacing#1#2%
}%
\Frefformat{vario}{\fancyreflstlabelprefix}{Listing~#1 on page #2}
\frefformat{vario}{\fancyreflstlabelprefix}{listing~#1 on page #2}

\begin{document}

I want to refer to a \fref{lst:example-1} and to a \fref{lst:example-2}.

\begin{lstlisting}[label={lst:example-1},caption=A first example]
{
  "name" : "Listing 1"
}
\end{lstlisting}

\pagebreak

\begin{lstlisting}[label={lst:example-2},caption=A second example]
{
  "name" : "Listing 2"
}
\end{lstlisting}


\end{document}

Best Answer

The following things had to be corrected:

  • The counterpart to the vario option (which is enabled by default) is named not main but plain.

  • \frefformat{plain}, \frefformat{vario} and their uppercase variants should be defined only one time for \fancyreflstlabelprefix (a second definition simply overides the first), and they should be modelled on the proper respective definitions for other elements.

  • \frefformat{vario} must use the first and third underlying argument (#1#3).

  • \freflstname and \Freflstname must be defined for all document languages (in the example: english).

  • Always use \fancyrefdefaultspacing instead of ~ (to which it points to by default).


\documentclass{scrreprt}

\usepackage{fancyref}% option `vario` is default
\usepackage{listings}

\newcommand*{\fancyreflstlabelprefix}{lst}

\fancyrefaddcaptions{english}{%
  \providecommand*{\freflstname}{listing}%
  \providecommand*{\Freflstname}{Listing}%
}

\frefformat{plain}{\fancyreflstlabelprefix}{\freflstname\fancyrefdefaultspacing#1}
\Frefformat{plain}{\fancyreflstlabelprefix}{\Freflstname\fancyrefdefaultspacing#1}

\frefformat{vario}{\fancyreflstlabelprefix}{%
  \freflstname\fancyrefdefaultspacing#1#3%
}
\Frefformat{vario}{\fancyreflstlabelprefix}{%
  \Freflstname\fancyrefdefaultspacing#1#3%
}

\begin{document}

I want to refer to a \fref{lst:example-1}, to a \fref{lst:example-2}, and to a
    \fref{lst:example-3}.

\begin{lstlisting}[label={lst:example-1},caption=A first example]
{
  "name" : "Listing 1"
}
\end{lstlisting}

\clearpage

\begin{lstlisting}[label={lst:example-2},caption=A second example]
{
  "name" : "Listing 2"
}
\end{lstlisting}

\clearpage

\begin{lstlisting}[label={lst:example-3},caption=A third example]
{
  "name" : "Listing 3"
}
\end{lstlisting}

\end{document}

enter image description here