4

Consider the following MWE:

\documentclass{article}

\usepackage{tikz}

\usepackage{listings}

\lstset{% basicstyle =\ttfamily, language = Python, keywordstyle = \bfseries, commentstyle = \itshape, numbers = left, numberstyle = \tiny\sffamily, escapechar = |, gobble = 2, }

\begin{document}

\begin{lstlisting} import numpy as np from matplotlib import pyplot as plt

t = np.linspace(0, 1, 100) |\label{that-line}| plt.plot(t, t**2) plt.show() |\label{that-other-line}| \end{lstlisting}

Please see line~\ref{that-line} and line~\ref{that-other-line}.

\end{document}

The current output is:

listing-output

I'd like the numbers corresponding to the lines that are \ref'ed (so lines 4 and 6 in my MWE) to have a specific style (e.g. typesetted inside a square or a circle, ideally arbitrary tikz code). For example:

with-circles

cjorssen
  • 10,032
  • 4
  • 36
  • 126
  • Try \def\REF#1{AAA-\ref{#1}}. Change the AAA to what you need. – yannisl Jan 18 '24 at 10:47
  • @yannisl Thanks but I meant the numbers in the listing. – cjorssen Jan 18 '24 at 10:58
  • Thanks Let me think about this. This is harder, what I do I format the label with circled numbers. Like you see in some computer books and leave the listing numbering alone. – yannisl Jan 18 '24 at 11:24
  • Like this https://imgur.com/P5k2Yhd – yannisl Jan 18 '24 at 11:33
  • @yannisl Unfortunately, no. That's not what I've been asked. – cjorssen Jan 18 '24 at 12:06
  • Maybe use zref to add a porporty to the label so that we know it is inside the lstlisting environment. Then parse all labels that belongs to the specific lstlisting environment and finally compate \lst@lineno with the lines corresponding to the selected labels. – cjorssen Jan 18 '24 at 12:19
  • 1
    I made a draft with a boolean and it is working but needs some cleanup to fix a bug. Will post a solution in the morning, if nobody else answers. – yannisl Jan 18 '24 at 12:45

1 Answers1

4

An adaptation of my answer at How to add referrable numbered circle symbols to code listings?:

\documentclass{article}

\usepackage{tikz}

\usepackage{listings}

\usepackage{circledsteps} \pgfkeys{/csteps/outer color=orange}

\lstset{% basicstyle =\ttfamily, language = Python, keywordstyle = \bfseries, commentstyle = \itshape, numbers = left, numberstyle = \tiny\sffamily, escapechar = |, gobble = 2, } \makeatletter \newcommand*\CircleNext{% \lst@AddToHook{OnNewLine}{% \def\thelstnumber{\Circled{\arabic{lstnumber}}\hskip-2.1pt}}% } \def\circlabel#1{ \lst@AddToHook{OnNewLine}{% \def\thelstnumber{\arabic{lstnumber}}}% \label{#1}% } \makeatother \begin{document}

\begin{lstlisting} import numpy as np from matplotlib import pyplot as plt |\CircleNext| t = np.linspace(0, 1, 100) |\circlabel{that-line}| plt.plot(t, t**2)|\CircleNext| plt.show() |\circlabel{that-other-line}| \end{lstlisting}

Please see line~\ref{that-line} and line~\ref{that-other-line}.

\end{document}

enter image description here


Below a variant that doesn't need the \CircleNext commands. It works by writing an extra label consisting of the format listing number-line number. Instead of an OnNewLine hook for listings, now the command \thelstnumber (which prints the line number for every line) is modified to check if the label for the current listing and current line exists or not. If the label exists then the number is circled (at the next run).

Unfortunately \thelstnumber is also written to the .aux file as the label text which is read by \ref. To prevent circled numbers in the main text a solution is to temporarily redefine \thelstnumber to be just the number when writing the regular \label.

The rest of the code is bookkeeping to create and increment the listings counter that is used in the new label.

Code:

\documentclass{article}
\usepackage{tikz}
\newcounter{lstprefix}
\setcounter{lstprefix}{0}
\usepackage{listings}
\AddToHook{env/lstlisting/before}{\stepcounter{lstprefix}}

\usepackage{circledsteps} \pgfkeys{/csteps/outer color=orange}

\lstset{% basicstyle =\ttfamily, language = Python, keywordstyle = \bfseries, commentstyle = \itshape, numbers = left, numberstyle = \tiny\sffamily, escapechar = |, gobble = 2, } \makeatletter \def\thelstnumber{% \ifcsname r@lst\thelstprefix-\arabic{lstnumber}\endcsname% \Circled{\arabic{lstnumber}}\hskip-2.1pt% \else% \arabic{lstnumber}% \fi% } \def\circlabel#1{ {\def\thelstnumber{\arabic{lstnumber}}\label{#1}}% \label{lst\thelstprefix-\arabic{lstnumber}}% } \makeatother \begin{document}

\begin{lstlisting} import numpy as np from matplotlib import pyplot as plt

t = np.linspace(0, 1, 100) |\circlabel{that-line}| plt.plot(t, t**2) plt.show() |\circlabel{that-other-line}| \end{lstlisting}

Please see line~\ref{that-line} and line~\ref{that-other-line}.

\begin{lstlisting} import numpy as np from matplotlib import pyplot as plt |\circlabel{import-line}|

t = np.linspace(0, 1, 100) plt.plot(t, t**2) plt.show() \end{lstlisting} See also line \ref{import-line}. \end{document}

This creates the following .aux file:

\relax 
\newlabel{that-line}{{4}{1}}
\newlabel{lst1-4}{{\Circled {4}\hskip -2.1pt}{1}}
\newlabel{that-other-line}{{6}{1}}
\newlabel{lst1-6}{{\Circled {6}\hskip -2.1pt}{1}}
\newlabel{import-line}{{2}{1}}
\newlabel{lst2-2}{{\Circled {2}\hskip -2.1pt}{1}}
\gdef \@abspage@last{1}
Marijn
  • 37,699
  • Thanks (+1)! It works nicely. It would be even better if I did not have to add \CircleNext to the line before the label. But I understand it is quite tricky. – cjorssen Jan 18 '24 at 15:19
  • 2
    @cjorssen Once you are at the label the line number has already been generated, so then it's too late. Maybe you can leverage the information in the .aux file to circle the relevant lines on the second run, then \CircleNext may not be needed. If I have time I'll look into that. – Marijn Jan 18 '24 at 16:07
  • @cjorssen I added a version without \CircleNext. – Marijn Jan 18 '24 at 22:45
  • @Marijn Any idea how to make it work with hyperref? – yannisl Jan 19 '24 at 04:11
  • Super nice! Thanks and accepted. – cjorssen Jan 19 '24 at 07:02
  • 2
    @cjorssen indeed as Yannis commented it does not work with hyperref at the moment, I'm not quite sure how that can be fixed but maybe I can take another look later. – Marijn Jan 19 '24 at 07:09