Document Classeslistings | Line Number Reference in subsequent Call

Information and discussion about specific document classes and how to create your own document classes.
Post Reply
you2000too
Posts: 4
Joined: Mon Jan 16, 2012 3:09 pm

listings | Line Number Reference in subsequent Call

Post by you2000too »

Dear all,

After listing a piece of code using listings, I want to use the reference of a line number as the first number of a new listing.

This is a minimal example:

Code: Select all

\documentclass[oldfontcommands, 12pt]{memoir}
\usepackage{listings}         

% Parameters for Python listings
\lstset{
  language=Python,
  basicstyle=\ttfamily,
  numbers=left,
  numberstyle=\tiny,
  numbersep=5pt,
  showstringspaces=false
}

\begin{document}

\begin{lstlisting}[firstnumber=1,escapeinside={@}{@}]
def foo(int x):
 @\label{lst:myListing_2}@doSomething()
 doMore()
\end{lstlisting}

When doSomething is invoked:

\begin{lstlisting}[firstnumber=\ref{lst:myListing_2}]
    doSomething()
\end{lstlisting}

\end{document}
But I got the following errors:

Code: Select all

listingsbasic.tex(32): Error: Misplaced alignment tab character &.
listingsbasic.tex(32): Error: You can't use `macro parameter character #' in vertical mode.
listingsbasic.tex(32): Error: You can't use `macro parameter character #' in horizontal mode.
listingsbasic.tex(32): Error: You can't use `macro parameter character #' in horizontal mode.
listingsbasic.tex(32): Error: Undefined control sequence.
listingsbasic.tex(32): Error: You can't use `macro parameter character #' in horizontal mode.
listingsbasic.tex(32): Error: Missing $ inserted.
listingsbasic.tex(32): Error: Misplaced alignment tab character &.
listingsbasic.tex(32): Error: Undefined control sequence.
listingsbasic.tex(32): Error: Missing $ inserted.
listingsbasic.tex(32): Error: Missing \endgroup inserted.
listingsbasic.tex(32): Underfull \hbox (badness 10000) in paragraph at lines 32--32
listingsbasic.tex(34): Error: Undefined control sequence.
listingsbasic.tex(1): Error: File ended while scanning use of \lst@IfNextChars@@.
listingsbasic.tex(1): Error: Emergency stop.
listingsbasic.tex(1): Error:  ==> Fatal error occurred, no output PDF file produced!
How can this be achieved?

Thank you!

yt.

Recommended reading 2024:

LaTeXguide.org • LaTeX-Cookbook.net • TikZ.org
LaTeX Beginner's Guide LaTeX Cookbook LaTeX TikZ graphics TikZによるLaTeXグラフィックス
User avatar
cgnieder
Site Moderator
Posts: 2000
Joined: Sat Apr 16, 2011 7:27 pm

listings | Line Number Reference in subsequent Call

Post by cgnieder »

It seems the \ref needs to be expanded first. I haven't hunted down what happens exactly so there are probably easier solutions:

Code: Select all

\documentclass[oldfontcommands, 12pt]{memoir}
\usepackage{listings}

% Parameters for Python listings
\lstset{
  language=Python,
  basicstyle=\ttfamily,
  numbers=left,
  numberstyle=\tiny,
  numbersep=5pt,
  showstringspaces=false,
}

\makeatletter
\def\explstopts@reorder[#1]#2#3{#2{#3}[#1]}
\protected\long\def\explstopts#1#2[#3]{%
  \begingroup
    \let\null\relax
    \xdef\@explstopts{[#3]}%
  \endgroup
  \expandafter\explstopts@reorder\@explstopts{#1}{#2}%
}
\makeatother

\begin{document}

\begin{lstlisting}[firstnumber=1,escapeinside={@}{@}]
def foo(int x):
 @\label{lst:myListing_2}@doSomething()
 doMore()
\end{lstlisting}

\explstopts
\begin{lstlisting}[firstnumber=\ref{lst:myListing_2}]
doSomething()
\end{lstlisting}

\end{document}
This example needs to be compiled twice and produces errors the first time.

If you have other options containing macros you might need to add \noexpand accordingly.

Regards
site moderator & package author
jha
Posts: 1
Joined: Tue Jan 05, 2016 7:52 pm

listings | Line Number Reference in subsequent Call

Post by jha »

First of all thank you for the solution. Worked almost perfectly.

Unfortunately there is two things that still don't work as I hoped for (mainly due to the fact that I have no clue how TeX really works and what in particular your macro does).

If used with the babel package (ngerman option) it doesn't work any more. bable seems to change the \ref macro, so I could "fix" it by redefining \ref to what it was without babel while using babel. That worked.

Using \explstopt seems to introduce some whitespace and this is where I'm really stuck at. Any help would be really welcome. Thank you in advance.

Here is an example

Code: Select all

\documentclass{scrartcl}

\usepackage{listings}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}

\lstset{
  basicstyle=\footnotesize,        % the size of the fonts that are used for the code
  breaklines=true,                 % sets automatic line breaking
  captionpos=b,                    % sets the caption-position to bottom
  numberstyle=\tiny,numbers=left,
  frame=single,                    % adds a frame around the code
  language=Java,                 % the language of the code
  keywordstyle=\bfseries,
}

\makeatletter
\def\explstopts@reorder[#1]#2#3{#2{#3}[#1]}
 \protected\long\def\explstopts#1#2[#3]{%
   \begingroup
     \let\null\relax
     \xdef\@explstopts{[#3]}%
   \endgroup
   \expandafter\explstopts@reorder\@explstopts{#1}{#2}%
 }
\makeatother
% this redefines ref to what it was before it got changed by the babel package. 
% Needed because the above hack assumes to be working with this style of reference resolving 
\makeatletter
\renewcommand{\ref}[1]{\expandafter \@setref \csname r@#1\endcsname \@firstoftwo {#1}}
\makeatother

\begin{document}
\begin{lstlisting}[escapeinside={@}{@}]
  public static void main(String[] args)
  {
    @\label{lst:beforeprint1}@String dataID = args[0];
    System.out.println("some output");
    @\label{lst:afterprint1}@
    
    @\label{lst:print2}@System.out.println("some other code");
  }
\end{lstlisting}
Text that explains stuff (\ref{lst:beforeprint1} to \ref{lst:afterprint1}). In line number \ref{lst:print2} you can see \ldots (whitespace)\explstopts \begin{lstlisting}[firstnumber=\ref{lst:print2}]
  System.out.println("some other code");
\end{lstlisting}
And here there is no extra space:
\begin{lstlisting}[firstnumber=7]
  System.out.println("some other code");
\end{lstlisting}
\end{document}
Post Reply