[Tex/LaTex] Latex and code blocks: how to mark statements that way

listings

I’d like to show you a nice technique used in this book to describe code listings (see pag. 6 and 7 of the PDF — 116 and 117 of the book), in which relevant statement are labeled with special “markers”.

Can you tell me how to replicate such technique in Latex?

I know that the packet listings allows escaping (so it is possible to insert Latex code within code listings) but I cannot figure out how to typeset the markers (hopefully with auto numbering within the listing itself) — in the book, the numbering for the markers wraps around at each listing.

I was thinking to something like the following:

% preamble
\lstset{
    (...)
    escapechar=§,
}

% Definition for the command `mycoderef`

(...) 
% begin document

% Marked listing
\begin{lstlisting}[language=c,label=src-hello-c]
    #include <stdio.h>

    int
    main(int argc, char *argv[])
    {
        §\mycoderef{mylabel1}§printf("Hello, World!\n");
        return 0;
    }
\end{lstlisting}

% The text refers to the marked statement
The hello message is printed with the statement printf\autoref{mylabel1}.

Thanks,
Giorgio

Best Answer

Here's how you could do it. I didn't go into the trouble of printing the markers exactly as in your book, but I think this will be quite easy. Notice that the counter is initialized once; if you have more listings, it will keep the previous value. This should be fixed too.

\documentclass[11pt]{article}
\usepackage{listings}

\lstset{basicstyle=\normalsize\ttfamily,
        showstringspaces=false,
        basewidth=1.2ex,
        fontadjust=true,
        escapechar=§}

\newcount\mymark
\makeatletter
\def\mycoderef#1{%
  \global\advance\mymark by 1%
  \protected@write \@auxout {}{\string \newlabel {#1}{{\the\mymark}{}}}%
  \makebox[0pt][r]{{\scriptsize\bfseries \the\mymark~}}%
}
\makeatother

\begin{document}
\begin{lstlisting}[language=c,label=src-hello-c]
#include <stdio.h>

int main(int argc, char *argv[])
{
    §\mycoderef{mylabel1}§printf("Hello world!\n");
    printf("Love, peace and harmony!\n");
    §\mycoderef{mylabel2}§return 0;
}
\end{lstlisting}

The hello message is printed with the statement printf at \ref{mylabel1}.
Yet another message is printed similarly.
Then, the program returns with \ref{mylabel2}.
\end{document}

Addendum

This is a very basic approach with TikZ to recreate boxed numbers.

\documentclass[11pt]{article}
\usepackage{tikz}
\usepackage{listings}

\lstset{basicstyle=\normalsize\ttfamily,
        showstringspaces=false,
        basewidth=1.2ex,
        fontadjust=true,
        escapechar=§}

\newcommand{\roundbox}[1]{%
  \tikz[baseline=-1ex]%
  \node[%
  inner sep=1.5pt,
  draw=black,
  fill=black,
  text=white,
  rounded corners=2.5pt]{#1};}

\newcommand{\boxref}[1]{%
  \begingroup%
  \scriptsize\ttfamily%
  \roundbox{\ref{#1}}%
  \endgroup%
}

\newcount\mymark
\makeatletter
\def\mycoderef#1{%
  \global\advance\mymark by 1%
  \protected@write \@auxout {}{\string \newlabel {#1}{{\the\mymark}{}}}%
  \makebox[0pt][r]{{\scriptsize\roundbox{\the\mymark}~}}%
}
\makeatother

\begin{document}
\begin{lstlisting}[language=c,label=src-hello-c]
#include <stdio.h>

int main(int argc, char *argv[])
{
    §\mycoderef{mylabel1}§printf("Hello world!\n");
    printf("Love, peace and harmony!\n");
    §\mycoderef{mylabel2}§return 0;
}
\end{lstlisting}

The hello message is printed with the statement printf at \boxref{mylabel1}.
Yet another message is printed similarly.
Then, the program returns with \boxref{mylabel2}.
\end{document} 

enter image description here

Related Question